github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/querylogger/manifold.go (about) 1 // Copyright 2023 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package querylogger 5 6 import ( 7 "runtime/debug" 8 9 "github.com/juju/clock" 10 "github.com/juju/errors" 11 "github.com/juju/worker/v3" 12 "github.com/juju/worker/v3/dependency" 13 14 coredatabase "github.com/juju/juju/core/database" 15 "github.com/juju/juju/worker/common" 16 ) 17 18 // Logger is the interface that is used to log issues with the slow query 19 // logger. 20 type Logger interface { 21 Warningf(string, ...interface{}) 22 Errorf(string, ...interface{}) 23 } 24 25 // ManifoldConfig contains: 26 // - The names of other manifolds on which the DB accessor depends. 27 // - Other dependencies from ManifoldsConfig required by the worker. 28 type ManifoldConfig struct { 29 LogDir string 30 Clock clock.Clock 31 Logger Logger 32 } 33 34 func (cfg ManifoldConfig) Validate() error { 35 if cfg.LogDir == "" { 36 return errors.NotValidf("empty LogDir") 37 } 38 if cfg.Clock == nil { 39 return errors.NotValidf("nil Clock") 40 } 41 if cfg.Logger == nil { 42 return errors.NotValidf("nil Logger") 43 } 44 return nil 45 } 46 47 // Manifold returns a dependency manifold that runs the query logger 48 // worker, using the resource names defined in the supplied config. 49 func Manifold(config ManifoldConfig) dependency.Manifold { 50 return dependency.Manifold{ 51 Inputs: []string{}, 52 Output: output, 53 Start: func(context dependency.Context) (worker.Worker, error) { 54 if err := config.Validate(); err != nil { 55 return nil, errors.Trace(err) 56 } 57 58 cfg := &WorkerConfig{ 59 LogDir: config.LogDir, 60 Clock: config.Clock, 61 Logger: config.Logger, 62 StackGatherer: func() []byte { 63 // TODO (stickupkid): Drop the first frames that don't 64 // include the slow query logger. 65 return debug.Stack() 66 }, 67 } 68 69 w, err := newWorker(cfg) 70 if err != nil { 71 return nil, errors.Trace(err) 72 } 73 return w, nil 74 }, 75 } 76 } 77 78 func output(in worker.Worker, out interface{}) error { 79 if w, ok := in.(*common.CleanupWorker); ok { 80 in = w.Worker 81 } 82 w, ok := in.(*loggerWorker) 83 if !ok { 84 return errors.Errorf("expected input of type dbWorker, got %T", in) 85 } 86 87 switch out := out.(type) { 88 case *coredatabase.SlowQueryLogger: 89 var target coredatabase.SlowQueryLogger = w 90 *out = target 91 default: 92 return errors.Errorf("expected output of *database.SlowQueryLogger, got %T", out) 93 } 94 return nil 95 }