github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/agent/addons/addons.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package addons 5 6 import ( 7 "runtime" 8 9 "github.com/juju/clock" 10 "github.com/juju/errors" 11 "github.com/juju/loggo" 12 "github.com/juju/names/v5" 13 "github.com/juju/worker/v3" 14 "github.com/juju/worker/v3/dependency" 15 "github.com/prometheus/client_golang/prometheus" 16 17 "github.com/juju/juju/cmd/jujud/agent/engine" 18 "github.com/juju/juju/core/machinelock" 19 "github.com/juju/juju/core/presence" 20 "github.com/juju/juju/worker/introspection" 21 ) 22 23 var logger = loggo.GetLogger("juju.cmd.jujud.agent.addons") 24 25 // DefaultIntrospectionSocketName returns the socket name to use for the 26 // abstract domain socket that the introspection worker serves requests 27 // over. 28 func DefaultIntrospectionSocketName(entityTag names.Tag) string { 29 return "jujud-" + entityTag.String() 30 } 31 32 // IntrospectionConfig defines the various components that the introspection 33 // worker reports on or needs to start up. 34 type IntrospectionConfig struct { 35 AgentTag names.Tag 36 Engine *dependency.Engine 37 StatePoolReporter introspection.Reporter 38 PubSubReporter introspection.Reporter 39 MachineLock machinelock.Lock 40 PrometheusGatherer prometheus.Gatherer 41 PresenceRecorder presence.Recorder 42 Clock clock.Clock 43 LocalHub introspection.SimpleHub 44 CentralHub introspection.StructuredHub 45 46 NewSocketName func(names.Tag) string 47 WorkerFunc func(config introspection.Config) (worker.Worker, error) 48 } 49 50 // StartIntrospection creates the introspection worker. It cannot and should 51 // not be in the engine itself as it reports on the engine, and other aspects 52 // of the runtime. If we put it in the engine, then it is mostly likely shut 53 // down in the times we need it most, which is when the agent is having 54 // problems shutting down. Here we effectively start the worker and tie its 55 // life to that of the engine that is returned. 56 func StartIntrospection(cfg IntrospectionConfig) error { 57 if runtime.GOOS != "linux" { 58 logger.Debugf("introspection worker not supported on %q", runtime.GOOS) 59 return nil 60 } 61 62 socketName := cfg.NewSocketName(cfg.AgentTag) 63 w, err := cfg.WorkerFunc(introspection.Config{ 64 SocketName: socketName, 65 DepEngine: cfg.Engine, 66 StatePool: cfg.StatePoolReporter, 67 PubSub: cfg.PubSubReporter, 68 MachineLock: cfg.MachineLock, 69 PrometheusGatherer: cfg.PrometheusGatherer, 70 Presence: cfg.PresenceRecorder, 71 Clock: cfg.Clock, 72 LocalHub: cfg.LocalHub, 73 CentralHub: cfg.CentralHub, 74 // TODO(leases) - add lease introspection 75 }) 76 if err != nil { 77 return errors.Trace(err) 78 } 79 go func() { 80 _ = cfg.Engine.Wait() 81 logger.Debugf("engine stopped, stopping introspection") 82 w.Kill() 83 _ = w.Wait() 84 logger.Debugf("introspection stopped") 85 }() 86 87 return nil 88 } 89 90 // NewPrometheusRegistry returns a new prometheus.Registry with 91 // the Go and process metric collectors registered. This registry 92 // is exposed by the introspection abstract domain socket on all 93 // Linux agents. 94 func NewPrometheusRegistry() (*prometheus.Registry, error) { 95 r := prometheus.NewRegistry() 96 if err := r.Register(prometheus.NewGoCollector()); err != nil { 97 return nil, errors.Trace(err) 98 } 99 if err := r.Register(prometheus.NewProcessCollector( 100 prometheus.ProcessCollectorOpts{})); err != nil { 101 return nil, errors.Trace(err) 102 } 103 return r, nil 104 } 105 106 // RegisterEngineMetrics registers the metrics sink on a prometheus registerer, 107 // ensuring that we cleanup when the worker has stopped. 108 func RegisterEngineMetrics(registry prometheus.Registerer, metrics prometheus.Collector, worker worker.Worker, sink engine.MetricSink) error { 109 if err := registry.Register(metrics); err != nil { 110 return errors.Annotatef(err, "failed to register engine metrics") 111 } 112 113 go func() { 114 _ = worker.Wait() 115 _ = sink.Unregister() 116 _ = registry.Unregister(metrics) 117 }() 118 return nil 119 }