mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-21 13:23:07 +01:00
chore: uses zerolog instead of logrus (#3203)
This commit is contained in:
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -54,7 +54,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.22.x
|
||||
go-version: 1.23.x
|
||||
check-latest: true
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
4
go.mod
4
go.mod
@@ -15,7 +15,6 @@ require (
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/afero v1.11.0
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0
|
||||
@@ -30,6 +29,7 @@ require (
|
||||
github.com/go-chi/jwtauth/v5 v5.3.1
|
||||
github.com/goccy/go-json v0.10.3
|
||||
github.com/puzpuzpuz/xsync/v3 v3.4.0
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/samber/lo v1.47.0
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8
|
||||
github.com/yuin/goldmark v1.7.4
|
||||
@@ -59,6 +59,8 @@ require (
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.1 // indirect
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
|
||||
19
go.sum
19
go.sum
@@ -20,6 +20,7 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@@ -28,8 +29,6 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnN
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
|
||||
github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY=
|
||||
github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
@@ -51,6 +50,7 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@@ -85,6 +85,11 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk=
|
||||
@@ -102,8 +107,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/samber/lo v1.46.0 h1:w8G+oaCPgz1PoCJztqymCFaKwXt+5cCXn51uPxExFfQ=
|
||||
github.com/samber/lo v1.46.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
@@ -121,7 +127,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
@@ -183,10 +188,12 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/amir20/dozzle/internal/agent/pb"
|
||||
"github.com/amir20/dozzle/internal/docker"
|
||||
"github.com/amir20/dozzle/internal/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -32,7 +32,7 @@ func NewClient(endpoint string, certificates tls.Certificate, opts ...grpc.DialO
|
||||
caCertPool := x509.NewCertPool()
|
||||
c, err := x509.ParseCertificate(certificates.Certificate[0])
|
||||
if err != nil {
|
||||
log.Fatalf("failed to parse certificate: %v", err)
|
||||
return nil, fmt.Errorf("failed to parse certificate: %w", err)
|
||||
}
|
||||
caCertPool.AddCert(c)
|
||||
tlsConfig := &tls.Config{
|
||||
@@ -126,7 +126,8 @@ func sendLogs(stream pb.AgentService_StreamLogsClient, events chan<- *docker.Log
|
||||
|
||||
m, err := resp.Event.Message.UnmarshalNew()
|
||||
if err != nil {
|
||||
log.Fatalf("cannot unpack message %v", err)
|
||||
log.Error().Err(err).Msg("agent client: failed to unmarshal message")
|
||||
continue
|
||||
}
|
||||
|
||||
var message any
|
||||
@@ -136,8 +137,10 @@ func sendLogs(stream pb.AgentService_StreamLogsClient, events chan<- *docker.Log
|
||||
|
||||
case *pb.ComplexMessage:
|
||||
message = jsonBytesToOrderedMap(m.Data)
|
||||
|
||||
default:
|
||||
log.Fatalf("agent client: unknown type %T", m)
|
||||
log.Error().Type("message", m).Msg("agent client: unknown message type")
|
||||
continue
|
||||
}
|
||||
|
||||
events <- &docker.LogEvent{
|
||||
@@ -175,7 +178,7 @@ func (c *Client) StreamRawBytes(ctx context.Context, containerID string, since t
|
||||
if err == io.EOF || err == context.Canceled {
|
||||
return
|
||||
} else {
|
||||
log.Warnf("error while streaming raw bytes %v", err)
|
||||
log.Error().Err(err).Msg("agent client: failed to receive raw bytes")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ func init() {
|
||||
Stats: utils.NewRingBuffer[docker.ContainerStat](300),
|
||||
}, nil)
|
||||
|
||||
server := NewServer(client, certs, "test")
|
||||
server, _ := NewServer(client, certs, "test")
|
||||
|
||||
go server.Serve(lis)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,14 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/amir20/dozzle/internal/agent/pb"
|
||||
"github.com/amir20/dozzle/internal/docker"
|
||||
"github.com/rs/zerolog/log"
|
||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
@@ -302,11 +303,11 @@ func (s *server) ContainerAction(ctx context.Context, in *pb.ContainerActionRequ
|
||||
return &pb.ContainerActionResponse{}, nil
|
||||
}
|
||||
|
||||
func NewServer(client docker.Client, certificates tls.Certificate, dozzleVersion string) *grpc.Server {
|
||||
func NewServer(client docker.Client, certificates tls.Certificate, dozzleVersion string) (*grpc.Server, error) {
|
||||
caCertPool := x509.NewCertPool()
|
||||
c, err := x509.ParseCertificate(certificates.Certificate[0])
|
||||
if err != nil {
|
||||
log.Fatalf("failed to parse certificate: %v", err)
|
||||
return nil, fmt.Errorf("failed to parse certificate: %w", err)
|
||||
}
|
||||
caCertPool.AddCert(c)
|
||||
|
||||
@@ -323,7 +324,7 @@ func NewServer(client docker.Client, certificates tls.Certificate, dozzleVersion
|
||||
grpcServer := grpc.NewServer(grpc.Creds(creds))
|
||||
pb.RegisterAgentServiceServer(grpcServer, newServer(client, dozzleVersion))
|
||||
|
||||
return grpcServer
|
||||
return grpcServer, nil
|
||||
}
|
||||
|
||||
func logEventToPb(event *docker.LogEvent) *pb.LogEvent {
|
||||
@@ -344,7 +345,7 @@ func logEventToPb(event *docker.LogEvent) *pb.LogEvent {
|
||||
})
|
||||
|
||||
default:
|
||||
log.Fatalf("agent server: unknown type %T", event.Message)
|
||||
log.Error().Type("message", event.Message).Msg("agent server: unknown message type")
|
||||
}
|
||||
|
||||
return &pb.LogEvent{
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func SendBeacon(e BeaconEvent) error {
|
||||
log.Tracef("sending beacon: %+v", e)
|
||||
log.Trace().Interface("event", e).Msg("sending beacon")
|
||||
jsonValue, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -33,7 +33,7 @@ func SendBeacon(e BeaconEvent) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("%v", string(dump))
|
||||
log.Debug().Str("response", string(dump)).Msg("google analytics returned non-2xx status code")
|
||||
return fmt.Errorf("google analytics returned non-2xx status code: %v", response.Status)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
@@ -49,6 +49,6 @@ func (p *proxyAuthContext) AuthMiddleware(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
func (p *proxyAuthContext) CreateToken(username, password string) (string, error) {
|
||||
log.Fatalf("CreateToken not implemented for proxy auth")
|
||||
log.Fatal().Msg("CreateToken not implemented in proxy auth")
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -90,11 +90,11 @@ func decodeUsersFromFile(path string) (UserDatabase, error) {
|
||||
for username, user := range users.Users {
|
||||
user.Username = username
|
||||
if user.Password == "" {
|
||||
log.Fatalf("User %s has no password", username)
|
||||
log.Fatal().Msgf("User %s has an empty password", username)
|
||||
}
|
||||
|
||||
if len(user.Password) != 64 {
|
||||
log.Fatalf("User %s has an invalid password hash", username)
|
||||
log.Fatal().Str("password", user.Password).Msgf("User %s has an invalid password hash", username)
|
||||
}
|
||||
|
||||
if user.Name == "" {
|
||||
@@ -115,7 +115,7 @@ func (u *UserDatabase) readFileIfChanged() error {
|
||||
}
|
||||
|
||||
if info.ModTime().After(u.LastRead) {
|
||||
log.Infof("Found changes to %s. Updating users...", u.Path)
|
||||
log.Info().Msg("Reloading user database")
|
||||
users, err := decodeUsersFromFile(u.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -129,7 +129,8 @@ func (u *UserDatabase) readFileIfChanged() error {
|
||||
|
||||
func (u *UserDatabase) Find(username string) *User {
|
||||
if err := u.readFileIfChanged(); err != nil {
|
||||
log.Errorf("Error reading users file: %s", err)
|
||||
log.Error().Err(err).Msg("Failed to read user database")
|
||||
return nil
|
||||
}
|
||||
user, ok := u.Users[username]
|
||||
if !ok {
|
||||
|
||||
8
internal/cache/expire.go
vendored
8
internal/cache/expire.go
vendored
@@ -4,7 +4,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type Cache[T any] struct {
|
||||
@@ -36,11 +36,7 @@ func (c *Cache[T]) GetWithHit() (T, error, bool) {
|
||||
}
|
||||
c.Timestamp = time.Now()
|
||||
}
|
||||
if hit {
|
||||
log.Debugf("Cache hit for %T", c.Data)
|
||||
} else {
|
||||
log.Debugf("Cache miss for %T", c.Data)
|
||||
}
|
||||
log.Debug().Bool("hit", hit).Type("data", c.Data).Msg("Cache hit")
|
||||
return c.Data, nil, hit
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -21,7 +20,7 @@ import (
|
||||
"github.com/docker/docker/api/types/system"
|
||||
"github.com/docker/docker/client"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type StdType int
|
||||
@@ -83,7 +82,7 @@ type httpClient struct {
|
||||
func NewClient(cli DockerCLI, filters filters.Args, host Host) Client {
|
||||
info, err := cli.Info(context.Background())
|
||||
if err != nil {
|
||||
log.Errorf("unable to get docker info: %v", err)
|
||||
log.Error().Err(err).Msg("Failed to get docker info")
|
||||
}
|
||||
|
||||
host.NCPU = info.NCPU
|
||||
@@ -107,7 +106,7 @@ func NewLocalClient(f map[string][]string, hostname string) (Client, error) {
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("filterArgs = %v", filterArgs)
|
||||
log.Debug().Interface("filterArgs", filterArgs).Msg("Creating local client")
|
||||
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
|
||||
@@ -149,10 +148,10 @@ func NewRemoteClient(f map[string][]string, host Host) (Client, error) {
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("filterArgs = %v", filterArgs)
|
||||
log.Debug().Interface("filterArgs", filterArgs).Msg("Creating remote client")
|
||||
|
||||
if host.URL.Scheme != "tcp" {
|
||||
log.Fatal("Only tcp scheme is supported")
|
||||
return nil, fmt.Errorf("invalid scheme: %s", host.URL.Scheme)
|
||||
}
|
||||
|
||||
opts := []client.Opt{
|
||||
@@ -160,10 +159,10 @@ func NewRemoteClient(f map[string][]string, host Host) (Client, error) {
|
||||
}
|
||||
|
||||
if host.ValidCerts {
|
||||
log.Debugf("Using TLS client config with certs at: %s", filepath.Dir(host.CertPath))
|
||||
log.Debug().Str("caCertPath", host.CACertPath).Str("certPath", host.CertPath).Str("keyPath", host.KeyPath).Msg("Using TLS for remote client")
|
||||
opts = append(opts, client.WithTLSClientConfig(host.CACertPath, host.CertPath, host.KeyPath))
|
||||
} else {
|
||||
log.Debugf("No valid certs found, using plain TCP")
|
||||
log.Debug().Msg("Not using TLS for remote client")
|
||||
}
|
||||
|
||||
opts = append(opts, client.WithAPIVersionNegotiation())
|
||||
@@ -181,7 +180,7 @@ func NewRemoteClient(f map[string][]string, host Host) (Client, error) {
|
||||
|
||||
// Finds a container by id, skipping the filters
|
||||
func (d *httpClient) FindContainer(id string) (Container, error) {
|
||||
log.Debugf("finding container with id: %s", id)
|
||||
log.Debug().Str("id", id).Msg("Finding container")
|
||||
if json, err := d.cli.ContainerInspect(context.Background(), id); err == nil {
|
||||
return newContainerFromJSON(json, d.host.ID), nil
|
||||
} else {
|
||||
@@ -204,7 +203,7 @@ func (d *httpClient) ContainerActions(action ContainerAction, containerID string
|
||||
}
|
||||
|
||||
func (d *httpClient) ListContainers() ([]Container, error) {
|
||||
log.Debugf("listing containers with filters: %v", d.filters)
|
||||
log.Debug().Interface("filter", d.filters).Str("host", d.host.Name).Msg("Listing containers")
|
||||
containerListOptions := container.ListOptions{
|
||||
Filters: d.filters,
|
||||
All: true,
|
||||
@@ -277,7 +276,7 @@ func (d *httpClient) ContainerStats(ctx context.Context, id string, stats chan<-
|
||||
}
|
||||
|
||||
func (d *httpClient) ContainerLogs(ctx context.Context, id string, since time.Time, stdType StdType) (io.ReadCloser, error) {
|
||||
log.WithField("id", id).WithField("since", since).WithField("stdType", stdType).Debug("streaming logs for container")
|
||||
log.Debug().Str("id", id).Time("since", since).Stringer("stdType", stdType).Str("host", d.host.Name).Msg("Streaming logs for container")
|
||||
|
||||
sinceQuery := since.Add(-50 * time.Millisecond).Format(time.RFC3339Nano)
|
||||
options := container.LogsOptions{
|
||||
@@ -320,6 +319,7 @@ func (d *httpClient) ContainerEvents(ctx context.Context, messages chan<- Contai
|
||||
}
|
||||
|
||||
func (d *httpClient) ContainerLogsBetweenDates(ctx context.Context, id string, from time.Time, to time.Time, stdType StdType) (io.ReadCloser, error) {
|
||||
log.Debug().Str("id", id).Time("from", from).Time("to", to).Stringer("stdType", stdType).Str("host", d.host.Name).Msg("Fetching logs between dates for container")
|
||||
options := container.LogsOptions{
|
||||
ShowStdout: stdType&STDOUT != 0,
|
||||
ShowStderr: stdType&STDERR != 0,
|
||||
@@ -328,8 +328,6 @@ func (d *httpClient) ContainerLogsBetweenDates(ctx context.Context, id string, f
|
||||
Until: to.Format(time.RFC3339Nano),
|
||||
}
|
||||
|
||||
log.Debugf("fetching logs from Docker with option: %+v", options)
|
||||
|
||||
reader, err := d.cli.ContainerLogs(ctx, id, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/samber/lo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
@@ -51,10 +51,10 @@ var (
|
||||
func (s *ContainerStore) checkConnectivity() error {
|
||||
if s.connected.CompareAndSwap(false, true) {
|
||||
go func() {
|
||||
log.Debugf("subscribing to docker events from container store %s", s.client.Host())
|
||||
log.Debug().Str("host", s.client.Host().Name).Msg("docker store subscribing docker events")
|
||||
err := s.client.ContainerEvents(s.ctx, s.events)
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
log.Errorf("docker store unexpectedly disconnected from docker events from %s with %v", s.client.Host(), err)
|
||||
log.Error().Err(err).Str("host", s.client.Host().Name).Msg("docker store unexpectedly disconnected from docker events")
|
||||
}
|
||||
s.connected.Store(false)
|
||||
}()
|
||||
@@ -76,7 +76,7 @@ func (s *ContainerStore) checkConnectivity() error {
|
||||
|
||||
for i, c := range running {
|
||||
if err := sem.Acquire(s.ctx, 1); err != nil {
|
||||
log.Errorf("failed to acquire semaphore: %v", err)
|
||||
log.Error().Err(err).Msg("failed to acquire semaphore")
|
||||
break
|
||||
}
|
||||
go func(c Container, i int) {
|
||||
@@ -88,10 +88,10 @@ func (s *ContainerStore) checkConnectivity() error {
|
||||
}
|
||||
|
||||
if err := sem.Acquire(s.ctx, maxFetchParallelism); err != nil {
|
||||
log.Errorf("failed to acquire semaphore: %v", err)
|
||||
log.Error().Err(err).Msg("failed to acquire semaphore")
|
||||
}
|
||||
|
||||
log.Debugf("finished initializing container store with %d containers", len(containers))
|
||||
log.Debug().Int("containers", len(containers)).Msg("finished initializing container store")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ func (s *ContainerStore) FindContainer(id string) (Container, error) {
|
||||
if ok {
|
||||
return *container, nil
|
||||
} else {
|
||||
log.Warnf("container %s not found in store", id)
|
||||
log.Warn().Str("id", id).Msg("container not found")
|
||||
return Container{}, ErrContainerNotFound
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,6 @@ func (s *ContainerStore) Client() Client {
|
||||
func (s *ContainerStore) SubscribeEvents(ctx context.Context, events chan<- ContainerEvent) {
|
||||
go func() {
|
||||
if s.statsCollector.Start(s.ctx) {
|
||||
log.Debug("clearing container stats as stats collector has been stopped")
|
||||
s.containers.Range(func(_ string, c *Container) bool {
|
||||
c.Stats.Clear()
|
||||
return true
|
||||
@@ -171,7 +170,7 @@ func (s *ContainerStore) init() {
|
||||
for {
|
||||
select {
|
||||
case event := <-s.events:
|
||||
log.Tracef("received event: %+v", event)
|
||||
log.Trace().Str("event", event.Name).Str("id", event.ActorID).Msg("received container event")
|
||||
switch event.Name {
|
||||
case "start":
|
||||
if container, err := s.client.FindContainer(event.ActorID); err == nil {
|
||||
@@ -183,7 +182,7 @@ func (s *ContainerStore) init() {
|
||||
})
|
||||
|
||||
if valid {
|
||||
log.Debugf("container %s started", container.ID)
|
||||
log.Debug().Str("id", container.ID).Msg("container started")
|
||||
s.containers.Store(container.ID, &container)
|
||||
s.newContainerSubscribers.Range(func(c context.Context, containers chan<- Container) bool {
|
||||
select {
|
||||
@@ -195,13 +194,13 @@ func (s *ContainerStore) init() {
|
||||
}
|
||||
}
|
||||
case "destroy":
|
||||
log.Debugf("container %s destroyed", event.ActorID)
|
||||
log.Debug().Str("id", event.ActorID).Msg("container destroyed")
|
||||
s.containers.Delete(event.ActorID)
|
||||
|
||||
case "die":
|
||||
s.containers.Compute(event.ActorID, func(c *Container, loaded bool) (*Container, bool) {
|
||||
if loaded {
|
||||
log.Debugf("container %s died", c.ID)
|
||||
log.Debug().Str("id", c.ID).Msg("container died")
|
||||
c.State = "exited"
|
||||
return c, false
|
||||
} else {
|
||||
@@ -216,7 +215,7 @@ func (s *ContainerStore) init() {
|
||||
|
||||
s.containers.Compute(event.ActorID, func(c *Container, loaded bool) (*Container, bool) {
|
||||
if loaded {
|
||||
log.Debugf("health status for container %s is %s", c.ID, healthy)
|
||||
log.Debug().Str("id", c.ID).Str("health", healthy).Msg("container health status changed")
|
||||
c.Health = healthy
|
||||
return c, false
|
||||
} else {
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
|
||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type EventGenerator struct {
|
||||
@@ -100,7 +100,6 @@ func (g *EventGenerator) consumeReader() {
|
||||
|
||||
if readerError != nil {
|
||||
if readerError != ErrBadHeader {
|
||||
log.Tracef("reader error: %v", readerError)
|
||||
g.Errors <- readerError
|
||||
close(g.buffer)
|
||||
break
|
||||
@@ -141,7 +140,7 @@ func readEvent(reader *bufio.Reader, tty bool) (string, StdType, error) {
|
||||
return "", streamType, err
|
||||
}
|
||||
if n != 8 {
|
||||
log.Warnf("unable to read header: %v", header)
|
||||
log.Warn().Bytes("header", header).Msg("short read")
|
||||
message, _ := reader.ReadString('\n')
|
||||
return message, streamType, ErrBadHeader
|
||||
}
|
||||
@@ -152,7 +151,7 @@ func readEvent(reader *bufio.Reader, tty bool) (string, StdType, error) {
|
||||
case 2:
|
||||
streamType = STDERR
|
||||
default:
|
||||
log.Warnf("unknown stream type: %v", header[0])
|
||||
log.Warn().Bytes("header", header).Msg("unknown stream type")
|
||||
}
|
||||
|
||||
count := binary.BigEndian.Uint32(header[4:])
|
||||
@@ -183,7 +182,7 @@ func createEvent(message string, streamType StdType) *LogEvent {
|
||||
var jsonErr *json.UnmarshalTypeError
|
||||
if errors.As(err, &jsonErr) {
|
||||
if jsonErr.Value == "string" {
|
||||
log.Warnf("unable to parse json logs - error was \"%v\" while trying unmarshal \"%v\"", err.Error(), message)
|
||||
log.Warn().Err(err).Str("value", jsonErr.Value).Msg("failed to unmarshal json")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type Host struct {
|
||||
@@ -49,14 +49,14 @@ func ParseConnection(connection string) (Host, error) {
|
||||
|
||||
basePath, err := filepath.Abs("./certs")
|
||||
if err != nil {
|
||||
log.Fatalf("error converting certs path to absolute: %s", err)
|
||||
return Host{}, err
|
||||
}
|
||||
|
||||
host := remoteUrl.Hostname()
|
||||
if _, err := os.Stat(filepath.Join(basePath, host)); !os.IsNotExist(err) {
|
||||
basePath = filepath.Join(basePath, host)
|
||||
} else {
|
||||
log.Debugf("Remote host certificate path does not exist %s, falling back to default: %s", filepath.Join(basePath, host), basePath)
|
||||
log.Debug().Msgf("Remote host certificate path does not exist %s, falling back to default: %s", filepath.Join(basePath, host), basePath)
|
||||
}
|
||||
|
||||
cacertPath := filepath.Join(basePath, "ca.pem")
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||
)
|
||||
|
||||
@@ -74,7 +74,7 @@ func guessLogLevel(logEvent *LogEvent) string {
|
||||
}
|
||||
|
||||
default:
|
||||
log.Debugf("unknown type to guess level: %T", value)
|
||||
log.Debug().Type("type", value).Msg("unknown logEvent type")
|
||||
}
|
||||
|
||||
return ""
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type StatsCollector struct {
|
||||
@@ -48,7 +48,7 @@ func (c *StatsCollector) forceStop() {
|
||||
if c.stopper != nil {
|
||||
c.stopper()
|
||||
c.stopper = nil
|
||||
log.Debug("stopping container stats collector")
|
||||
log.Debug().Str("host", c.client.Host().ID).Msg("stopped container stats collector")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ func (c *StatsCollector) Stop() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.totalStarted.Add(-1) == 0 {
|
||||
log.Tracef("scheduled to stop container stats collector %s", c.client.Host())
|
||||
c.timer = time.AfterFunc(timeToStop, func() {
|
||||
c.forceStop()
|
||||
})
|
||||
@@ -66,7 +65,6 @@ func (c *StatsCollector) Stop() {
|
||||
func (c *StatsCollector) reset() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
log.Tracef("resetting timer for container stats collector %s", c.client.Host())
|
||||
if c.timer != nil {
|
||||
c.timer.Stop()
|
||||
}
|
||||
@@ -76,11 +74,11 @@ func (c *StatsCollector) reset() {
|
||||
func streamStats(parent context.Context, sc *StatsCollector, id string) {
|
||||
ctx, cancel := context.WithCancel(parent)
|
||||
sc.cancelers.Store(id, cancel)
|
||||
log.Debugf("starting to stream stats for: %s", id)
|
||||
log.Debug().Str("container", id).Str("host", sc.client.Host().Name).Msg("starting to stream stats")
|
||||
if err := sc.client.ContainerStats(ctx, id, sc.stream); err != nil {
|
||||
log.Debugf("stopping to stream stats for: %s", id)
|
||||
log.Debug().Str("container", id).Str("host", sc.client.Host().Name).Err(err).Msg("stopping to stream stats")
|
||||
if !errors.Is(err, context.Canceled) && !errors.Is(err, io.EOF) {
|
||||
log.Errorf("unexpected error when streaming container stats: %v", err)
|
||||
log.Error().Str("container", id).Str("host", sc.client.Host().Name).Err(err).Msg("unexpected error while streaming stats")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,16 +104,16 @@ func (sc *StatsCollector) Start(parentCtx context.Context) bool {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Errorf("error while listing containers: %v", err)
|
||||
log.Error().Str("host", sc.client.Host().Name).Err(err).Msg("failed to list containers")
|
||||
}
|
||||
|
||||
events := make(chan ContainerEvent)
|
||||
|
||||
go func() {
|
||||
log.Debugf("subscribing to docker events from stats collector %s", sc.client.Host())
|
||||
log.Debug().Str("host", sc.client.Host().Name).Msg("starting to listen to docker events")
|
||||
err := sc.client.ContainerEvents(context.Background(), events)
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
log.Errorf("stats collector unexpectedly disconnected from docker events from %s with %v", sc.client.Host(), err)
|
||||
log.Error().Str("host", sc.client.Host().Name).Err(err).Msg("unexpected error while listening to docker events")
|
||||
}
|
||||
sc.forceStop()
|
||||
}()
|
||||
@@ -137,7 +135,7 @@ func (sc *StatsCollector) Start(parentCtx context.Context) bool {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Info("stopped collecting container stats")
|
||||
log.Info().Str("host", sc.client.Host().Name).Msg("stopped container stats collector")
|
||||
return true
|
||||
case stat := <-sc.stream:
|
||||
sc.subscribers.Range(func(c context.Context, stats chan<- ContainerStat) bool {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func HttpRequest(addr string, base string) error {
|
||||
@@ -23,7 +23,7 @@ func HttpRequest(addr string, base string) error {
|
||||
url = "http://" + url
|
||||
}
|
||||
|
||||
log.Info("Checking health of " + url)
|
||||
log.Info().Str("url", url).Msg("performing healthcheck")
|
||||
resp, err := http.Get(url)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -4,15 +4,15 @@ import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/amir20/dozzle/internal/agent"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func RPCRequest(addr string, certs tls.Certificate) error {
|
||||
client, err := agent.NewClient(addr, certs)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create agent client: %v", err)
|
||||
log.Fatal().Err(err).Msg("Failed to create agent client")
|
||||
}
|
||||
containers, err := client.ListContainers()
|
||||
log.Tracef("Found %d containers.", len(containers))
|
||||
log.Trace().Int("containers", len(containers)).Msg("Healtcheck RPC request completed")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/amir20/dozzle/internal/auth"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -51,12 +51,12 @@ var mux = &sync.Mutex{}
|
||||
func init() {
|
||||
path, err := filepath.Abs("./data")
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to get absolute path for data directory: %s", err)
|
||||
log.Fatal().Err(err).Msg("Unable to get absolute path")
|
||||
return
|
||||
}
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
if err := os.Mkdir(path, 0755); err != nil {
|
||||
log.Fatalf("Unable to create data directory: %s", err)
|
||||
log.Fatal().Err(err).Msg("Unable to create data directory")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func Save(user auth.User, profile Profile) error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("Saved settings for user %s", user.Username)
|
||||
log.Debug().Str("path", filePath).Msg("Profile saved")
|
||||
|
||||
return f.Sync()
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package cli
|
||||
import (
|
||||
"github.com/amir20/dozzle/internal/analytics"
|
||||
"github.com/amir20/dozzle/internal/docker"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func StartEvent(args Args, mode string, client docker.Client, subCommand string) {
|
||||
@@ -33,8 +33,8 @@ func StartEvent(args Args, mode string, client docker.Client, subCommand string)
|
||||
event.ServerID = "n/a"
|
||||
}
|
||||
|
||||
log.Tracef("sending beacon event: %+v", event)
|
||||
log.Trace().Interface("event", event).Msg("Sending analytics event")
|
||||
if err := analytics.SendBeacon(event); err != nil {
|
||||
log.Debug(err)
|
||||
log.Debug().Err(err).Msg("Failed to send analytics event")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,16 @@ import (
|
||||
"embed"
|
||||
"os"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func ReadCertificates(certs embed.FS) (tls.Certificate, error) {
|
||||
if pair, err := tls.LoadX509KeyPair("dozzle_cert.pem", "dozzle_key.pem"); err == nil {
|
||||
log.Infof("Found dozzle certificate and key at ./dozzle_cert.pem and ./dozzle_key.pem")
|
||||
log.Info().Msg("Loaded custom dozzle certificate and key")
|
||||
return pair, nil
|
||||
} else {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Errorf("Failed to load dozzle certificate and key: %v", err)
|
||||
log.Warnf("Falling back to shared certificate and key")
|
||||
log.Fatal().Err(err).Msg("Failed to load custom dozzle certificate and key. Stopping...")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,31 +5,30 @@ import (
|
||||
|
||||
"github.com/amir20/dozzle/internal/docker"
|
||||
docker_support "github.com/amir20/dozzle/internal/support/docker"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func CreateMultiHostService(embeddedCerts embed.FS, args Args) (docker.Client, *docker_support.MultiHostService) {
|
||||
var clients []docker_support.ClientService
|
||||
if len(args.RemoteHost) > 0 {
|
||||
log.Warnf(`Remote host flag is deprecated and will be removed in future versions. Agents will replace remote hosts as a safer and performant option. See https://github.com/amir20/dozzle/issues/3066 for discussion.`)
|
||||
log.Warn().Msg(`Remote host flag is deprecated and will be removed in future versions. Agents will replace remote hosts as a safer and performant option. See https://github.com/amir20/dozzle/issues/3066 for discussion.`)
|
||||
}
|
||||
|
||||
for _, remoteHost := range args.RemoteHost {
|
||||
host, err := docker.ParseConnection(remoteHost)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not parse remote host %s: %s", remoteHost, err)
|
||||
log.Fatal().Err(err).Interface("host", remoteHost).Msg("Could not parse remote host")
|
||||
}
|
||||
log.Debugf("creating remote client for %s with %+v", host.Name, host)
|
||||
log.Infof("Creating client for %s with %s", host.Name, host.URL.String())
|
||||
|
||||
log.Info().Interface("host", host).Msg("Adding remote host")
|
||||
if client, err := docker.NewRemoteClient(args.Filter, host); err == nil {
|
||||
if _, err := client.ListContainers(); err == nil {
|
||||
log.Debugf("connected to local Docker Engine")
|
||||
clients = append(clients, docker_support.NewDockerClientService(client))
|
||||
} else {
|
||||
log.Warnf("Could not connect to remote host %s: %s", host.ID, err)
|
||||
log.Warn().Err(err).Interface("host", host).Msg("Could not connect to remote host")
|
||||
}
|
||||
} else {
|
||||
log.Warnf("Could not create client for %s: %s", host.ID, err)
|
||||
log.Warn().Err(err).Interface("host", host).Msg("Could not create remote client")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,16 +36,16 @@ func CreateMultiHostService(embeddedCerts embed.FS, args Args) (docker.Client, *
|
||||
if err == nil {
|
||||
_, err := localClient.ListContainers()
|
||||
if err != nil {
|
||||
log.Debugf("could not connect to local Docker Engine: %s", err)
|
||||
log.Debug().Err(err).Msg("Could not connect to local Docker Engine")
|
||||
} else {
|
||||
log.Debugf("connected to local Docker Engine")
|
||||
log.Debug().Msg("Adding local Docker Engine")
|
||||
clients = append(clients, docker_support.NewDockerClientService(localClient))
|
||||
}
|
||||
}
|
||||
|
||||
certs, err := ReadCertificates(embeddedCerts)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read certificates: %v", err)
|
||||
log.Fatal().Err(err).Msg("Could not read certificates")
|
||||
}
|
||||
|
||||
clientManager := docker_support.NewRetriableClientManager(args.RemoteAgent, certs, clients...)
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"os"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func ConfigureLogger(level string) {
|
||||
if l, err := log.ParseLevel(level); err == nil {
|
||||
log.SetLevel(l)
|
||||
if level, err := zerolog.ParseLevel(level); err == nil {
|
||||
zerolog.SetGlobalLevel(level)
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
DisableLevelTruncation: true,
|
||||
})
|
||||
_, dev := os.LookupEnv("DEV")
|
||||
|
||||
if dev {
|
||||
writer := zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) {
|
||||
w.FieldsOrder = []string{"id", "from", "to", "since"}
|
||||
})
|
||||
log.Logger = log.Output(writer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func ValidateEnvVars(types ...interface{}) {
|
||||
@@ -26,7 +26,7 @@ func ValidateEnvVars(types ...interface{}) {
|
||||
for _, env := range os.Environ() {
|
||||
actual := strings.Split(env, "=")[0]
|
||||
if strings.HasPrefix(actual, "DOZZLE_") && !expectedEnvs[actual] {
|
||||
log.Warnf("Unexpected environment variable %s", actual)
|
||||
log.Warn().Str("env", actual).Msg("Unexpected environment variable")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/amir20/dozzle/internal/docker"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type ContainerFilter = func(*docker.Container) bool
|
||||
@@ -36,8 +36,6 @@ func NewMultiHostService(manager ClientManager) *MultiHostService {
|
||||
manager: manager,
|
||||
}
|
||||
|
||||
log.Debugf("created multi host service manager %s", manager)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -75,7 +73,7 @@ func (m *MultiHostService) ListAllContainers() ([]docker.Container, []error) {
|
||||
list, err := client.ListContainers()
|
||||
if err != nil {
|
||||
host, _ := client.Host()
|
||||
log.Debugf("error listing containers for host %s: %v", host.ID, err)
|
||||
log.Debug().Err(err).Str("host", host.Name).Msg("error listing containers")
|
||||
host.Available = false
|
||||
errors = append(errors, &HostUnavailableError{Host: host, Err: err})
|
||||
continue
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
lop "github.com/samber/lo/parallel"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type RetriableClientManager struct {
|
||||
@@ -23,18 +23,16 @@ type RetriableClientManager struct {
|
||||
}
|
||||
|
||||
func NewRetriableClientManager(agents []string, certs tls.Certificate, clients ...ClientService) *RetriableClientManager {
|
||||
log.Debugf("creating retriable client manager with %d clients and %d agents", len(clients), len(agents))
|
||||
|
||||
clientMap := make(map[string]ClientService)
|
||||
for _, client := range clients {
|
||||
host, err := client.Host()
|
||||
if err != nil {
|
||||
log.Warnf("error fetching host info for client %s: %v", host.ID, err)
|
||||
log.Warn().Err(err).Str("host", host.Name).Msg("error fetching host info for client")
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := clientMap[host.ID]; ok {
|
||||
log.Warnf("duplicate client found for host %s", host.ID)
|
||||
log.Warn().Str("host", host.Name).Msg("duplicate client found")
|
||||
} else {
|
||||
clientMap[host.ID] = client
|
||||
}
|
||||
@@ -44,20 +42,20 @@ func NewRetriableClientManager(agents []string, certs tls.Certificate, clients .
|
||||
for _, endpoint := range agents {
|
||||
agent, err := agent.NewClient(endpoint, certs)
|
||||
if err != nil {
|
||||
log.Warnf("error creating agent client for %s: %v", endpoint, err)
|
||||
log.Warn().Err(err).Str("endpoint", endpoint).Msg("error creating agent client")
|
||||
failed = append(failed, endpoint)
|
||||
continue
|
||||
}
|
||||
|
||||
host, err := agent.Host()
|
||||
if err != nil {
|
||||
log.Warnf("error fetching host info for agent %s: %v", endpoint, err)
|
||||
log.Warn().Err(err).Str("endpoint", endpoint).Msg("error fetching host info for agent")
|
||||
failed = append(failed, endpoint)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := clientMap[host.ID]; ok {
|
||||
log.Warnf("duplicate client found for host %s", host.ID)
|
||||
log.Warn().Str("host", host.Name).Str("id", host.ID).Msg("duplicate host with same ID found")
|
||||
} else {
|
||||
clientMap[host.ID] = NewAgentService(agent)
|
||||
}
|
||||
@@ -88,7 +86,7 @@ func (m *RetriableClientManager) RetryAndList() ([]ClientService, []error) {
|
||||
for _, endpoint := range m.failedAgents {
|
||||
agent, err := agent.NewClient(endpoint, m.certs)
|
||||
if err != nil {
|
||||
log.Warnf("error creating agent client for %s: %v", endpoint, err)
|
||||
log.Warn().Err(err).Str("endpoint", endpoint).Msg("error creating agent client")
|
||||
errors = append(errors, err)
|
||||
newFailed = append(newFailed, endpoint)
|
||||
continue
|
||||
@@ -96,7 +94,7 @@ func (m *RetriableClientManager) RetryAndList() ([]ClientService, []error) {
|
||||
|
||||
host, err := agent.Host()
|
||||
if err != nil {
|
||||
log.Warnf("error fetching host info for agent %s: %v", endpoint, err)
|
||||
log.Warn().Err(err).Str("endpoint", endpoint).Msg("error fetching host info for agent")
|
||||
errors = append(errors, err)
|
||||
newFailed = append(newFailed, endpoint)
|
||||
continue
|
||||
@@ -153,7 +151,6 @@ func (m *RetriableClientManager) Hosts() []docker.Host {
|
||||
|
||||
hosts := lop.Map(clients, func(client ClientService, _ int) docker.Host {
|
||||
host, err := client.Host()
|
||||
log.Debugf("host: %v, err: %v", host, err)
|
||||
if err != nil {
|
||||
host.Available = false
|
||||
} else {
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/samber/lo"
|
||||
lop "github.com/samber/lo/parallel"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type SwarmClientManager struct {
|
||||
@@ -51,17 +51,17 @@ func NewSwarmClientManager(localClient docker.Client, certs tls.Certificate) *Sw
|
||||
|
||||
id, ok := os.LookupEnv("HOSTNAME")
|
||||
if !ok {
|
||||
log.Fatal("HOSTNAME environment variable not set when looking for swarm service name")
|
||||
log.Fatal().Msg("HOSTNAME environment variable not set when looking for swarm service name")
|
||||
}
|
||||
|
||||
container, err := localClient.FindContainer(id)
|
||||
if err != nil {
|
||||
log.Fatalf("error finding container %s: %v", id, err)
|
||||
log.Fatal().Err(err).Msg("error finding own container when looking for swarm service name")
|
||||
}
|
||||
|
||||
serviceName := container.Labels["com.docker.swarm.service.name"]
|
||||
|
||||
log.Debugf("found swarm internal service name: %s", serviceName)
|
||||
log.Debug().Str("service", serviceName).Msg("found swarm service name")
|
||||
|
||||
return &SwarmClientManager{
|
||||
localClient: localClient,
|
||||
@@ -85,12 +85,11 @@ func (m *SwarmClientManager) Subscribe(ctx context.Context, channel chan<- docke
|
||||
func (m *SwarmClientManager) RetryAndList() ([]ClientService, []error) {
|
||||
m.mu.Lock()
|
||||
|
||||
log.Debugf("looking up swarm services: tasks.%s", m.name)
|
||||
ips, err := net.LookupIP(fmt.Sprintf("tasks.%s", m.name))
|
||||
|
||||
errors := make([]error, 0)
|
||||
if err != nil {
|
||||
log.Fatalf("error looking up swarm services: %v", err)
|
||||
log.Fatal().Err(err).Msg("error looking up swarm service tasks")
|
||||
errors = append(errors, err)
|
||||
m.mu.Unlock()
|
||||
return m.List(), errors
|
||||
@@ -102,47 +101,51 @@ func (m *SwarmClientManager) RetryAndList() ([]ClientService, []error) {
|
||||
return host.Endpoint
|
||||
})
|
||||
|
||||
log.Debugf("tasks.dozzle = %v, localIP = %v, clients.endpoints = %v", ips, m.localIPs, lo.Keys(endpoints))
|
||||
ipStrings := lo.Map(ips, func(ip net.IP, _ int) string {
|
||||
return ip.String()
|
||||
})
|
||||
|
||||
log.Debug().Strs(fmt.Sprintf("tasks.%s", m.name), ipStrings).Strs("localIPs", m.localIPs).Strs("clients.endpoints", lo.Keys(endpoints)).Msg("found swarm service tasks")
|
||||
|
||||
for _, ip := range ips {
|
||||
if lo.Contains(m.localIPs, ip.String()) {
|
||||
log.Debugf("skipping local ip %s", ip.String())
|
||||
log.Debug().Stringer("ip", ip).Msg("skipping local IP")
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := endpoints[ip.String()+":7007"]; ok {
|
||||
log.Debugf("skipping existing client for %s", ip.String())
|
||||
log.Debug().Stringer("ip", ip).Msg("skipping existing client")
|
||||
continue
|
||||
}
|
||||
|
||||
agent, err := agent.NewClient(ip.String()+":7007", m.certs)
|
||||
if err != nil {
|
||||
log.Warnf("error creating client for %s: %v", ip, err)
|
||||
log.Warn().Err(err).Stringer("ip", ip).Msg("error creating agent client")
|
||||
errors = append(errors, err)
|
||||
continue
|
||||
}
|
||||
|
||||
host, err := agent.Host()
|
||||
if err != nil {
|
||||
log.Warnf("error getting host data for agent %s: %v", ip, err)
|
||||
log.Warn().Err(err).Stringer("ip", ip).Msg("error getting host from agent client")
|
||||
errors = append(errors, err)
|
||||
if err := agent.Close(); err != nil {
|
||||
log.Warnf("error closing local client: %v", err)
|
||||
log.Warn().Err(err).Stringer("ip", ip).Msg("error closing agent client")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if host.ID == m.localClient.Host().ID {
|
||||
log.Debugf("skipping local client with ID %s", host.ID)
|
||||
log.Debug().Stringer("ip", ip).Msg("skipping local client")
|
||||
if err := agent.Close(); err != nil {
|
||||
log.Warnf("error closing local client: %v", err)
|
||||
log.Warn().Err(err).Stringer("ip", ip).Msg("error closing agent client")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
client := NewAgentService(agent)
|
||||
m.clients[host.ID] = client
|
||||
log.Infof("added client for %s", host.ID)
|
||||
log.Info().Stringer("ip", ip).Str("id", host.ID).Str("name", host.Name).Msg("added new swarm agent")
|
||||
|
||||
m.subscribers.Range(func(ctx context.Context, channel chan<- docker.Host) bool {
|
||||
host.Available = true
|
||||
|
||||
@@ -5,35 +5,33 @@ import (
|
||||
|
||||
"github.com/amir20/dozzle/internal/docker"
|
||||
"github.com/go-chi/chi/v5"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (h *handler) containerActions(w http.ResponseWriter, r *http.Request) {
|
||||
action := chi.URLParam(r, "action")
|
||||
id := chi.URLParam(r, "id")
|
||||
|
||||
log.Debugf("container action: %s, container id: %s", action, id)
|
||||
|
||||
containerService, err := h.multiHostService.FindContainer(hostKey(r), id)
|
||||
if err != nil {
|
||||
log.Errorf("error while trying to find container: %v", err)
|
||||
log.Error().Err(err).Msg("error while trying to find container")
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
parsedAction, err := docker.ParseContainerAction(action)
|
||||
if err != nil {
|
||||
log.Errorf("error while trying to parse action: %s", action)
|
||||
log.Error().Err(err).Msg("error while trying to parse action")
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := containerService.Action(parsedAction); err != nil {
|
||||
log.Errorf("error while trying to perform action: %s", action)
|
||||
log.Error().Err(err).Msg("error while trying to perform container action")
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
log.Infof("container action performed: %s; container id: %s", action, id)
|
||||
log.Info().Str("action", action).Str("container", containerService.Container.Name).Msg("container action performed")
|
||||
http.Error(w, "", http.StatusNoContent)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (h *handler) createToken(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -19,11 +19,11 @@ func (h *handler) createToken(w http.ResponseWriter, r *http.Request) {
|
||||
Path: "/",
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
log.Infof("Token created for user %s", user)
|
||||
log.Info().Str("user", user).Msg("Token created")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(http.StatusText(http.StatusOK)))
|
||||
} else {
|
||||
log.Errorf("Error while creating token: %v", err)
|
||||
log.Error().Err(err).Msg("Failed to create token")
|
||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@ import (
|
||||
"github.com/amir20/dozzle/internal/analytics"
|
||||
"github.com/amir20/dozzle/internal/docker"
|
||||
docker_support "github.com/amir20/dozzle/internal/support/docker"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (h *handler) streamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -37,17 +36,18 @@ func (h *handler) streamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
allContainers, errors := h.multiHostService.ListAllContainers()
|
||||
|
||||
for _, err := range errors {
|
||||
log.Warnf("error listing containers: %v", err)
|
||||
log.Warn().Err(err).Msg("error listing containers")
|
||||
if hostNotAvailableError, ok := err.(*docker_support.HostUnavailableError); ok {
|
||||
bytes, _ := json.Marshal(hostNotAvailableError.Host)
|
||||
if _, err := fmt.Fprintf(w, "event: update-host\ndata: %s\n\n", string(bytes)); err != nil {
|
||||
log.Errorf("error writing event to event stream: %v", err)
|
||||
log.Error().Err(err).Msg("error writing event to event stream")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := sendContainersJSON(allContainers, w); err != nil {
|
||||
log.Errorf("error writing containers to event stream: %v", err)
|
||||
log.Error().Err(err).Msg("error writing containers to event stream")
|
||||
return
|
||||
}
|
||||
|
||||
f.Flush()
|
||||
@@ -59,13 +59,13 @@ func (h *handler) streamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
case host := <-availableHosts:
|
||||
bytes, _ := json.Marshal(host)
|
||||
if _, err := fmt.Fprintf(w, "event: update-host\ndata: %s\n\n", string(bytes)); err != nil {
|
||||
log.Errorf("error writing event to event stream: %v", err)
|
||||
log.Error().Err(err).Msg("error writing event to event stream")
|
||||
}
|
||||
f.Flush()
|
||||
case stat := <-stats:
|
||||
bytes, _ := json.Marshal(stat)
|
||||
if _, err := fmt.Fprintf(w, "event: container-stat\ndata: %s\n\n", string(bytes)); err != nil {
|
||||
log.Errorf("error writing stat to event stream: %v", err)
|
||||
log.Error().Err(err).Msg("error writing event to event stream")
|
||||
return
|
||||
}
|
||||
f.Flush()
|
||||
@@ -76,10 +76,10 @@ func (h *handler) streamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
switch event.Name {
|
||||
case "start", "die", "destroy":
|
||||
if event.Name == "start" {
|
||||
log.Debugf("found new container with id: %v", event.ActorID)
|
||||
log.Debug().Str("container", event.ActorID).Msg("container started")
|
||||
if containers, err := h.multiHostService.ListContainersForHost(event.Host); err == nil {
|
||||
if err := sendContainersJSON(containers, w); err != nil {
|
||||
log.Errorf("error encoding containers to stream: %v", err)
|
||||
log.Error().Err(err).Msg("error writing containers to event stream")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -87,14 +87,14 @@ func (h *handler) streamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
bytes, _ := json.Marshal(event)
|
||||
if _, err := fmt.Fprintf(w, "event: container-event\ndata: %s\n\n", string(bytes)); err != nil {
|
||||
log.Errorf("error writing event to event stream: %v", err)
|
||||
log.Error().Err(err).Msg("error writing event to event stream")
|
||||
return
|
||||
}
|
||||
|
||||
f.Flush()
|
||||
|
||||
case "health_status: healthy", "health_status: unhealthy":
|
||||
log.Debugf("triggering docker health event: %v", event.Name)
|
||||
log.Debug().Str("container", event.ActorID).Str("health", event.Name).Msg("container health status")
|
||||
healthy := "unhealthy"
|
||||
if event.Name == "health_status: healthy" {
|
||||
healthy = "healthy"
|
||||
@@ -105,13 +105,12 @@ func (h *handler) streamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
bytes, _ := json.Marshal(payload)
|
||||
if _, err := fmt.Fprintf(w, "event: container-health\ndata: %s\n\n", string(bytes)); err != nil {
|
||||
log.Errorf("error writing event to event stream: %v", err)
|
||||
log.Error().Err(err).Msg("error writing event to event stream")
|
||||
return
|
||||
}
|
||||
f.Flush()
|
||||
}
|
||||
case <-ctx.Done():
|
||||
log.Debugf("context done, closing event stream")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -140,7 +139,7 @@ func sendBeaconEvent(h *handler, r *http.Request, runningContainers int) {
|
||||
}
|
||||
|
||||
if err := analytics.SendBeacon(b); err != nil {
|
||||
log.Debugf("error sending beacon: %v", err)
|
||||
log.Debug().Err(err).Msg("error sending beacon")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,17 @@ package web
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (h *handler) healthcheck(w http.ResponseWriter, r *http.Request) {
|
||||
log.Trace("Executing healthcheck request")
|
||||
log.Trace().Msg("Healthcheck request received")
|
||||
|
||||
_, errors := h.multiHostService.ListAllContainers()
|
||||
if len(errors) > 0 {
|
||||
log.Error(errors)
|
||||
log.Error().Err(errors[0]).Msg("Error listing containers")
|
||||
http.Error(w, "Error listing containers", http.StatusInternalServerError)
|
||||
} else {
|
||||
http.Error(w, "OK", http.StatusOK)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/amir20/dozzle/internal/auth"
|
||||
"github.com/amir20/dozzle/internal/profile"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (h *handler) index(w http.ResponseWriter, req *http.Request) {
|
||||
@@ -70,15 +70,15 @@ func (h *handler) executeTemplate(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
config["user"] = user
|
||||
} else if h.config.Authorization.Provider == FORWARD_PROXY {
|
||||
log.Error("Unable to find remote user. Please check your proxy configuration. Expecting headers Remote-Email, Remote-User, Remote-Name.")
|
||||
log.Debugf("Dumping all headers for url /%s", req.URL.String())
|
||||
log.Error().Msg("Unable to find remote user. Please check your proxy configuration. Expecting headers Remote-Email, Remote-User, Remote-Name.")
|
||||
log.Debug().Str("url", req.URL.String()).Msg("Dumping all headers for request")
|
||||
for k, v := range req.Header {
|
||||
log.Debugf("%s: %s", k, v)
|
||||
log.Debug().Strs(k, v).Send()
|
||||
}
|
||||
http.Error(w, "Unauthorized user", http.StatusUnauthorized)
|
||||
return
|
||||
} else if h.config.Authorization.Provider == SIMPLE && req.URL.Path != "login" {
|
||||
log.Debugf("Redirecting to login page for url /%s", req.URL.String())
|
||||
log.Debug().Str("url", req.URL.String()).Msg("Redirecting to login page")
|
||||
http.Redirect(w, req, path.Clean(h.config.Base+"/login")+"?redirectUrl=/"+req.URL.String(), http.StatusTemporaryRedirect)
|
||||
return
|
||||
}
|
||||
@@ -91,11 +91,11 @@ func (h *handler) executeTemplate(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
file, err := h.content.Open("index.html")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
log.Fatal().Err(err).Msg("Could not open index.html")
|
||||
}
|
||||
bytes, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
log.Fatal().Err(err).Msg("Could not read index.html")
|
||||
}
|
||||
tmpl, err := template.New("index.html").Funcs(template.FuncMap{
|
||||
"marshal": func(v interface{}) template.JS {
|
||||
@@ -109,13 +109,12 @@ func (h *handler) executeTemplate(w http.ResponseWriter, req *http.Request) {
|
||||
},
|
||||
}).Parse(string(bytes))
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
log.Fatal().Err(err).Msg("Could not parse index.html")
|
||||
}
|
||||
|
||||
err = tmpl.Execute(w, data)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
log.Fatal().Err(err).Msg("Could not execute index.html")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,12 +129,12 @@ func (h *handler) readManifest() map[string]interface{} {
|
||||
}
|
||||
bytes, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read .vite/manifest.json: %v", err)
|
||||
log.Fatal().Err(err).Msg("Could not read .vite/manifest.json")
|
||||
}
|
||||
var manifest map[string]interface{}
|
||||
err = json.Unmarshal(bytes, &manifest)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not parse .vite/manifest.json: %v", err)
|
||||
log.Fatal().Err(err).Msg("Could not unmarshal .vite/manifest.json")
|
||||
}
|
||||
return manifest
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -105,7 +105,9 @@ func (h *handler) fetchLogsBetweenDates(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
events, err := containerService.LogsBetweenDates(r.Context(), from, to, stdTypes)
|
||||
if err != nil {
|
||||
log.Errorf("error while streaming logs %v", err.Error())
|
||||
log.Error().Err(err).Msg("error fetching logs")
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
buffer := utils.NewRingBuffer[*docker.LogEvent](500)
|
||||
@@ -117,7 +119,8 @@ func (h *handler) fetchLogsBetweenDates(w http.ResponseWriter, r *http.Request)
|
||||
encoder := json.NewEncoder(w)
|
||||
for _, event := range buffer.Data() {
|
||||
if err := encoder.Encode(event); err != nil {
|
||||
log.Errorf("json encoding error while streaming %v", err.Error())
|
||||
log.Error().Err(err).Msg("error encoding log event")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,22 +205,22 @@ func streamLogsForContainers(w http.ResponseWriter, r *http.Request, multiHostCl
|
||||
defer ticker.Stop()
|
||||
existingContainers, errs := multiHostClient.ListAllContainersFiltered(filter)
|
||||
if len(errs) > 0 {
|
||||
log.Warnf("error while listing containers %v", errs)
|
||||
log.Warn().Err(errs[0]).Msg("error while listing containers")
|
||||
}
|
||||
|
||||
streamLogs := func(container docker.Container) {
|
||||
containerService, err := multiHostClient.FindContainer(container.Host, container.ID)
|
||||
if err != nil {
|
||||
log.Errorf("error while finding container %v", err.Error())
|
||||
log.Error().Err(err).Msg("error while finding container")
|
||||
return
|
||||
}
|
||||
err = containerService.StreamLogs(r.Context(), container.StartedAt, stdTypes, logs)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
log.WithError(err).Debugf("stream closed for container %v", container.Name)
|
||||
log.Debug().Str("container", container.ID).Msg("streaming ended")
|
||||
events <- &docker.ContainerEvent{ActorID: container.ID, Name: "container-stopped", Host: container.Host}
|
||||
} else if !errors.Is(err, context.Canceled) {
|
||||
log.Errorf("unknown error while streaming %v", err.Error())
|
||||
log.Error().Err(err).Str("container", container.ID).Msg("unknown error while streaming logs")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,7 +237,7 @@ loop:
|
||||
select {
|
||||
case event := <-logs:
|
||||
if buf, err := json.Marshal(event); err != nil {
|
||||
log.Errorf("json encoding error while streaming %v", err.Error())
|
||||
log.Error().Err(err).Msg("error encoding log event")
|
||||
} else {
|
||||
fmt.Fprintf(w, "data: %s\n", buf)
|
||||
}
|
||||
@@ -251,28 +254,26 @@ loop:
|
||||
go streamLogs(container)
|
||||
|
||||
case event := <-events:
|
||||
log.Debugf("received container event %v", event)
|
||||
log.Debug().Str("event", event.Name).Str("container", event.ActorID).Msg("received event")
|
||||
if buf, err := json.Marshal(event); err != nil {
|
||||
log.Errorf("json encoding error while streaming %v", err.Error())
|
||||
log.Error().Err(err).Msg("error encoding container event")
|
||||
} else {
|
||||
fmt.Fprintf(w, "event: container-event\ndata: %s\n\n", buf)
|
||||
f.Flush()
|
||||
}
|
||||
|
||||
case <-r.Context().Done():
|
||||
log.Debugf("context cancelled")
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
if log.IsLevelEnabled(log.DebugLevel) {
|
||||
if e := log.Debug(); e.Enabled() {
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
log.WithFields(log.Fields{
|
||||
"allocated": humanize.Bytes(m.Alloc),
|
||||
"totalAllocated": humanize.Bytes(m.TotalAlloc),
|
||||
"system": humanize.Bytes(m.Sys),
|
||||
"routines": runtime.NumGoroutine(),
|
||||
}).Debug("runtime mem stats")
|
||||
e.Str("allocated", humanize.Bytes(m.Alloc)).
|
||||
Str("totalAllocated", humanize.Bytes(m.TotalAlloc)).
|
||||
Str("system", humanize.Bytes(m.Sys)).
|
||||
Int("routines", runtime.NumGoroutine()).
|
||||
Msg("runtime mem stats")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/amir20/dozzle/internal/auth"
|
||||
"github.com/amir20/dozzle/internal/profile"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (h *handler) updateProfile(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -18,7 +18,7 @@ func (h *handler) updateProfile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err := profile.UpdateFromReader(*user, r.Body); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
log.Errorf("Unable to save user settings: %s", err)
|
||||
log.Error().Err(err).Msg("Failed to update profile")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func (h *handler) avatar(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("Fetching avatar from %s", url)
|
||||
log.Trace().Str("url", url).Msg("Fetching avatar")
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
@@ -49,7 +49,7 @@ func (h *handler) avatar(w http.ResponseWriter, r *http.Request) {
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
log.Errorf("Received status code %d from %s", response.StatusCode, url)
|
||||
log.Error().Str("url", url).Int("status", response.StatusCode).Msg("Failed to fetch avatar")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/amir20/dozzle/internal/cache"
|
||||
"github.com/amir20/dozzle/internal/releases"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
var cachedReleases *cache.Cache[[]releases.Release]
|
||||
@@ -22,7 +22,7 @@ func (h *handler) releases(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
log.Debugf("error reading releases: %v", err)
|
||||
log.Debug().Err(err).Msg("error fetching releases")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ func (h *handler) releases(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(releases); err != nil {
|
||||
log.Errorf("json encoding error while streaming %v", err.Error())
|
||||
log.Error().Err(err).Msg("error encoding releases")
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
docker_support "github.com/amir20/dozzle/internal/support/docker"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type AuthProvider string
|
||||
@@ -73,7 +73,7 @@ func createRouter(h *handler) *chi.Mux {
|
||||
}
|
||||
|
||||
if h.config.Authorization.Provider != NONE && h.config.Authorization.Authorizer == nil {
|
||||
log.Panic("Authorization provider is set but no authorizer is provided")
|
||||
log.Fatal().Msg("Authorization provider is set but no authorizer is provided")
|
||||
}
|
||||
|
||||
r.Route(base, func(r chi.Router) {
|
||||
@@ -134,7 +134,7 @@ func hostKey(r *http.Request) string {
|
||||
host := chi.URLParam(r, "host")
|
||||
|
||||
if host == "" {
|
||||
log.Fatalf("No host found for url %v", r.URL)
|
||||
log.Fatal().Str("url", r.URL.String()).Msg("Host parameter not found in the URL path")
|
||||
}
|
||||
|
||||
return host
|
||||
|
||||
102
main.go
102
main.go
@@ -21,8 +21,7 @@ import (
|
||||
"github.com/amir20/dozzle/internal/support/cli"
|
||||
docker_support "github.com/amir20/dozzle/internal/support/docker"
|
||||
"github.com/amir20/dozzle/internal/web"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
//go:embed all:dist
|
||||
@@ -40,44 +39,48 @@ func main() {
|
||||
case *cli.AgentCmd:
|
||||
client, err := docker.NewLocalClient(args.Filter, args.Hostname)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not create docker client: %v", err)
|
||||
log.Fatal().Err(err).Msg("Could not create docker client")
|
||||
}
|
||||
certs, err := cli.ReadCertificates(certs)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read certificates: %v", err)
|
||||
log.Fatal().Err(err).Msg("Could not read certificates")
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", args.Agent.Addr)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
log.Fatal().Err(err).Msg("failed to listen")
|
||||
}
|
||||
tempFile, err := os.CreateTemp("./", "agent-*.addr")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create temp file: %v", err)
|
||||
log.Fatal().Err(err).Msg("failed to create temp file")
|
||||
}
|
||||
io.WriteString(tempFile, listener.Addr().String())
|
||||
go cli.StartEvent(args, "", client, "agent")
|
||||
server := agent.NewServer(client, certs, args.Version())
|
||||
server, err := agent.NewServer(client, certs, args.Version())
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("failed to create agent server")
|
||||
}
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer stop()
|
||||
go func() {
|
||||
log.Infof("Dozzle agent version %s", args.Version())
|
||||
log.Infof("Agent listening on %s", listener.Addr().String())
|
||||
log.Info().Msgf("Dozzle agent version %s", args.Version())
|
||||
log.Info().Msgf("Agent listening on %s", listener.Addr().String())
|
||||
|
||||
if err := server.Serve(listener); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
log.Error().Err(err).Msg("failed to serve")
|
||||
}
|
||||
}()
|
||||
<-ctx.Done()
|
||||
stop()
|
||||
log.Info("Shutting down agent")
|
||||
log.Info().Msg("Shutting down agent")
|
||||
server.Stop()
|
||||
log.Debugf("deleting %s", tempFile.Name())
|
||||
log.Debug().Str("file", tempFile.Name()).Msg("Removing temp file")
|
||||
os.Remove(tempFile.Name())
|
||||
|
||||
case *cli.HealthcheckCmd:
|
||||
files, err := os.ReadDir(".")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read directory: %v", err)
|
||||
log.Fatal().Err(err).Msg("Failed to read directory")
|
||||
}
|
||||
|
||||
agentAddress := ""
|
||||
@@ -85,7 +88,7 @@ func main() {
|
||||
if match, _ := filepath.Match("agent-*.addr", file.Name()); match {
|
||||
data, err := os.ReadFile(file.Name())
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read file: %v", err)
|
||||
log.Fatal().Err(err).Msg("Failed to read file")
|
||||
}
|
||||
agentAddress = string(data)
|
||||
break
|
||||
@@ -93,22 +96,22 @@ func main() {
|
||||
}
|
||||
if agentAddress == "" {
|
||||
if err := healthcheck.HttpRequest(args.Addr, args.Base); err != nil {
|
||||
log.Fatalf("Failed to make request: %v", err)
|
||||
log.Fatal().Err(err).Msg("Failed to make request")
|
||||
}
|
||||
} else {
|
||||
certs, err := cli.ReadCertificates(certs)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read certificates: %v", err)
|
||||
log.Fatal().Err(err).Msg("Could not read certificates")
|
||||
}
|
||||
if err := healthcheck.RPCRequest(agentAddress, certs); err != nil {
|
||||
log.Fatalf("Failed to make request: %v", err)
|
||||
log.Fatal().Err(err).Msg("Failed to make request")
|
||||
}
|
||||
}
|
||||
|
||||
case *cli.GenerateCmd:
|
||||
cli.StartEvent(args, "", nil, "generate")
|
||||
if args.Generate.Username == "" || args.Generate.Password == "" {
|
||||
log.Fatal("Username and password are required")
|
||||
log.Fatal().Msg("Username and password are required")
|
||||
}
|
||||
|
||||
buffer := auth.GenerateUsers(auth.User{
|
||||
@@ -119,7 +122,7 @@ func main() {
|
||||
}, true)
|
||||
|
||||
if _, err := os.Stdout.Write(buffer.Bytes()); err != nil {
|
||||
log.Fatalf("Failed to write to stdout: %v", err)
|
||||
log.Fatal().Err(err).Msg("Failed to write to stdout")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,55 +130,58 @@ func main() {
|
||||
}
|
||||
|
||||
if args.AuthProvider != "none" && args.AuthProvider != "forward-proxy" && args.AuthProvider != "simple" {
|
||||
log.Fatalf("Invalid auth provider %s", args.AuthProvider)
|
||||
log.Fatal().Str("provider", args.AuthProvider).Msg("Invalid auth provider")
|
||||
}
|
||||
|
||||
log.Infof("Dozzle version %s", args.Version())
|
||||
log.Info().Msgf("Dozzle version %s", args.Version())
|
||||
|
||||
var multiHostService *docker_support.MultiHostService
|
||||
if args.Mode == "server" {
|
||||
var localClient docker.Client
|
||||
localClient, multiHostService = cli.CreateMultiHostService(certs, args)
|
||||
if multiHostService.TotalClients() == 0 {
|
||||
log.Fatal("Could not connect to any Docker Engines")
|
||||
log.Fatal().Msg("Could not connect to any Docker Engine")
|
||||
} else {
|
||||
log.Infof("Connected to %d Docker Engine(s)", multiHostService.TotalClients())
|
||||
log.Info().Int("clients", multiHostService.TotalClients()).Msg("Connected to Docker")
|
||||
}
|
||||
go cli.StartEvent(args, "server", localClient, "")
|
||||
|
||||
} else if args.Mode == "swarm" {
|
||||
localClient, err := docker.NewLocalClient(args.Filter, args.Hostname)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not connect to local Docker Engine: %s", err)
|
||||
log.Fatal().Err(err).Msg("Could not create docker client")
|
||||
}
|
||||
certs, err := cli.ReadCertificates(certs)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read certificates: %v", err)
|
||||
log.Fatal().Err(err).Msg("Could not read certificates")
|
||||
}
|
||||
manager := docker_support.NewSwarmClientManager(localClient, certs)
|
||||
multiHostService = docker_support.NewMultiHostService(manager)
|
||||
log.Infof("Starting in Swarm mode")
|
||||
log.Info().Msg("Starting in swarm mode")
|
||||
listener, err := net.Listen("tcp", ":7007")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
log.Fatal().Err(err).Msg("failed to listen")
|
||||
}
|
||||
server, err := agent.NewServer(localClient, certs, args.Version())
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("failed to create agent")
|
||||
}
|
||||
server := agent.NewServer(localClient, certs, args.Version())
|
||||
go cli.StartEvent(args, "swarm", localClient, "")
|
||||
go func() {
|
||||
log.Infof("Agent listening on %s", listener.Addr().String())
|
||||
log.Info().Msgf("Dozzle agent version %s", args.Version())
|
||||
if err := server.Serve(listener); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
log.Error().Err(err).Msg("failed to serve")
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
log.Fatalf("Invalid mode %s", args.Mode)
|
||||
log.Fatal().Str("mode", args.Mode).Msg("Invalid mode")
|
||||
}
|
||||
|
||||
srv := createServer(args, multiHostService)
|
||||
go func() {
|
||||
log.Infof("Accepting connections on %s", srv.Addr)
|
||||
log.Info().Msgf("Accepting connections on %s", args.Addr)
|
||||
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
||||
log.Fatal(err)
|
||||
log.Fatal().Err(err).Msg("failed to listen")
|
||||
}
|
||||
}()
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
@@ -183,13 +189,13 @@ func main() {
|
||||
|
||||
<-ctx.Done()
|
||||
stop()
|
||||
log.Info("shutting down gracefully, press Ctrl+C again to force")
|
||||
log.Info().Msg("shutting down gracefully, press Ctrl+C again to force")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
if err := srv.Shutdown(ctx); err != nil {
|
||||
log.Fatal(err)
|
||||
log.Error().Err(err).Msg("failed to shut down")
|
||||
}
|
||||
log.Debug("shutdown complete")
|
||||
log.Debug().Msg("shut down complete")
|
||||
}
|
||||
|
||||
func createServer(args cli.Args, multiHostService *docker_support.MultiHostService) *http.Server {
|
||||
@@ -198,29 +204,29 @@ func createServer(args cli.Args, multiHostService *docker_support.MultiHostServi
|
||||
var provider web.AuthProvider = web.NONE
|
||||
var authorizer web.Authorizer
|
||||
if args.AuthProvider == "forward-proxy" {
|
||||
log.Debug("Using forward proxy authentication")
|
||||
log.Debug().Msg("Using forward proxy authentication")
|
||||
provider = web.FORWARD_PROXY
|
||||
authorizer = auth.NewForwardProxyAuth(args.AuthHeaderUser, args.AuthHeaderEmail, args.AuthHeaderName)
|
||||
} else if args.AuthProvider == "simple" {
|
||||
log.Debug("Using simple authentication")
|
||||
log.Debug().Msg("Using simple authentication")
|
||||
provider = web.SIMPLE
|
||||
|
||||
path, err := filepath.Abs("./data/users.yml")
|
||||
if err != nil {
|
||||
log.Fatalf("Could not find absolute path to users.yml file: %s", err)
|
||||
log.Fatal().Err(err).Msg("Could not get absolute path")
|
||||
}
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
log.Fatalf("Could not find users.yml file at %s", path)
|
||||
log.Fatal().Msg("users.yml file does not exist")
|
||||
}
|
||||
|
||||
log.Debugf("Reading users from %s", path)
|
||||
log.Debug().Str("path", path).Msg("Reading users.yml file")
|
||||
|
||||
db, err := auth.ReadUsersFromFile(path)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read users.yml file at %s: %s", path, err)
|
||||
log.Fatal().Err(err).Msg("Could not read users.yml file")
|
||||
}
|
||||
|
||||
log.Debugf("Read %d users", len(db.Users))
|
||||
log.Debug().Int("users", len(db.Users)).Msg("Loaded users")
|
||||
authorizer = auth.NewSimpleAuth(db)
|
||||
}
|
||||
|
||||
@@ -240,25 +246,25 @@ func createServer(args cli.Args, multiHostService *docker_support.MultiHostServi
|
||||
|
||||
assets, err := fs.Sub(content, "dist")
|
||||
if err != nil {
|
||||
log.Fatalf("Could not open embedded dist folder: %v", err)
|
||||
log.Fatal().Err(err).Msg("Could not get sub filesystem")
|
||||
}
|
||||
|
||||
if _, ok := os.LookupEnv("LIVE_FS"); ok {
|
||||
if dev {
|
||||
log.Info("Using live filesystem at ./public")
|
||||
log.Info().Msg("Using live filesystem at ./public")
|
||||
assets = os.DirFS("./public")
|
||||
} else {
|
||||
log.Info("Using live filesystem at ./dist")
|
||||
log.Info().Msg("Using live filesystem at ./dist")
|
||||
assets = os.DirFS("./dist")
|
||||
}
|
||||
}
|
||||
|
||||
if !dev {
|
||||
if _, err := assets.Open(".vite/manifest.json"); err != nil {
|
||||
log.Fatal(".vite/manifest.json not found")
|
||||
log.Fatal().Msg("manifest.json not found")
|
||||
}
|
||||
if _, err := assets.Open("index.html"); err != nil {
|
||||
log.Fatal("index.html not found")
|
||||
log.Fatal().Msg("index.html not found")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"license": "ISC",
|
||||
"author": "Amir Raminfar <findamir@gmail.com>",
|
||||
"scripts": {
|
||||
"agent:dev": "DOZZLE_AGENT_ADDR=localhost:7007 reflex -c .reflex.agent",
|
||||
"agent:dev": "DOZZLE_AGENT_ADDR=localhost:7007 DEV=true reflex -c .reflex.agent",
|
||||
"watch:frontend": "vite --open http://localhost:3100/",
|
||||
"watch:backend": "LIVE_FS=true DEV=true DOZZLE_ADDR=localhost:3100 reflex -c .reflex.server",
|
||||
"dev": "concurrently --kill-others \"npm:watch:*\"",
|
||||
|
||||
Reference in New Issue
Block a user