github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/debuglog_db.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package apiserver 5 6 import ( 7 "net/http" 8 "time" 9 10 "github.com/juju/clock" 11 "github.com/juju/errors" 12 13 "github.com/juju/juju/apiserver/authentication" 14 corelogger "github.com/juju/juju/core/logger" 15 "github.com/juju/juju/rpc/params" 16 "github.com/juju/juju/state" 17 ) 18 19 func newDebugLogDBHandler( 20 ctxt httpContext, 21 authenticator authentication.HTTPAuthenticator, 22 authorizer authentication.Authorizer, 23 ) http.Handler { 24 return newDebugLogHandler(ctxt, authenticator, authorizer, handleDebugLogDBRequest) 25 } 26 27 func handleDebugLogDBRequest( 28 clock clock.Clock, 29 maxDuration time.Duration, 30 st state.LogTailerState, 31 reqParams debugLogParams, 32 socket debugLogSocket, 33 stop <-chan struct{}, 34 ) error { 35 tailerParams := makeLogTailerParams(reqParams) 36 tailer, err := newLogTailer(st, tailerParams) 37 if err != nil { 38 return errors.Trace(err) 39 } 40 defer func() { _ = tailer.Stop() }() 41 42 // Indicate that all is well. 43 socket.sendOk() 44 45 timeout := clock.After(maxDuration) 46 47 var lineCount uint 48 for { 49 select { 50 case <-stop: 51 return nil 52 case <-timeout: 53 return nil 54 case rec, ok := <-tailer.Logs(): 55 if !ok { 56 return errors.Annotate(tailer.Err(), "tailer stopped") 57 } 58 59 if err := socket.sendLogRecord(formatLogRecord(rec)); err != nil { 60 return errors.Annotate(err, "sending failed") 61 } 62 63 lineCount++ 64 if reqParams.maxLines > 0 && lineCount == reqParams.maxLines { 65 return nil 66 } 67 } 68 } 69 } 70 71 func makeLogTailerParams(reqParams debugLogParams) corelogger.LogTailerParams { 72 tailerParams := corelogger.LogTailerParams{ 73 MinLevel: reqParams.filterLevel, 74 NoTail: reqParams.noTail, 75 StartTime: reqParams.startTime, 76 InitialLines: int(reqParams.backlog), 77 IncludeEntity: reqParams.includeEntity, 78 ExcludeEntity: reqParams.excludeEntity, 79 IncludeModule: reqParams.includeModule, 80 ExcludeModule: reqParams.excludeModule, 81 IncludeLabel: reqParams.includeLabel, 82 ExcludeLabel: reqParams.excludeLabel, 83 } 84 if reqParams.fromTheStart { 85 tailerParams.InitialLines = 0 86 } 87 return tailerParams 88 } 89 90 func formatLogRecord(r *corelogger.LogRecord) *params.LogMessage { 91 return ¶ms.LogMessage{ 92 Entity: r.Entity, 93 Timestamp: r.Time, 94 Severity: r.Level.String(), 95 Module: r.Module, 96 Location: r.Location, 97 Message: r.Message, 98 Labels: r.Labels, 99 } 100 } 101 102 var newLogTailer = _newLogTailer // For replacing in tests 103 104 func _newLogTailer(st state.LogTailerState, params corelogger.LogTailerParams) (corelogger.LogTailer, error) { 105 return state.NewLogTailer(st, params, nil) 106 }