| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | package collectorapi |
| 4 | |
| 5 | import ( |
| 6 | "fmt" |
| 7 | |
| 8 | "github.com/netdata/netdata/go/plugins/pkg/funcapi" |
| 9 | "github.com/netdata/netdata/go/plugins/plugin/framework/chartengine" |
| 10 | ) |
| 11 | |
| 12 | const ( |
| 13 | UpdateEvery = 1 |
| 14 | AutoDetectionRetry = 0 |
| 15 | Priority = chartengine.Priority |
| 16 | ) |
| 17 | |
| 18 | // Defaults is a set of module default parameters. |
| 19 | type Defaults struct { |
| 20 | UpdateEvery int |
| 21 | AutoDetectionRetry int |
| 22 | Priority int |
| 23 | Disabled bool |
| 24 | } |
| 25 | |
| 26 | type ( |
| 27 | // Creator is a Job builder. |
| 28 | // Optional function fields (Methods/MethodHandler) enable the FunctionProvider pattern: |
| 29 | // modules that set these fields can expose data functions to the UI. |
| 30 | Creator struct { |
| 31 | Defaults |
| 32 | Create func() CollectorV1 |
| 33 | CreateV2 func() CollectorV2 |
| 34 | JobConfigSchema string |
| 35 | Config func() any |
| 36 | |
| 37 | // Optional: FunctionProvider fields for exposing data functions |
| 38 | // If Methods is non-nil, this module provides functions |
| 39 | Methods func() []funcapi.MethodConfig |
| 40 | |
| 41 | // Optional: MethodHandler returns a handler for method requests on a specific job. |
| 42 | // The handler implements funcapi.MethodHandler interface with: |
| 43 | // - MethodParams(ctx, method) for dynamic params |
| 44 | // - Handle(ctx, method, params) for request handling |
| 45 | // When nil, methods are disabled for this module. |
| 46 | MethodHandler func(job RuntimeJob) funcapi.MethodHandler |
| 47 | |
| 48 | // Optional: JobMethods returns methods to register when a job starts. |
| 49 | // Each method is registered as "moduleName:methodID" and unregistered when the job stops. |
| 50 | // This enables per-job function registration instead of static module-level functions. |
| 51 | // If nil, no per-job methods are registered. |
| 52 | JobMethods func(job RuntimeJob) []funcapi.MethodConfig |
| 53 | |
| 54 | // FunctionOnly indicates this module provides only functions, no metrics. |
| 55 | // Jobs created from this module skip data collection and chart creation. |
| 56 | // The module must still implement Init() and Check() for connectivity validation. |
| 57 | FunctionOnly bool |
| 58 | } |
| 59 | // Registry is a collection of Creators. |
| 60 | Registry map[string]Creator |
| 61 | ) |
| 62 | |
| 63 | // DefaultRegistry DefaultRegistry. |
| 64 | var DefaultRegistry = Registry{} |
| 65 | |
| 66 | // Register registers a module in the DefaultRegistry. |
| 67 | func Register(name string, creator Creator) { |
| 68 | DefaultRegistry.Register(name, creator) |
| 69 | } |
| 70 | |
| 71 | // Register registers a module. |
| 72 | func (r Registry) Register(name string, creator Creator) { |
| 73 | if _, ok := r[name]; ok { |
| 74 | panic(fmt.Sprintf("%s is already in registry", name)) |
| 75 | } |
| 76 | if creator.Methods != nil && creator.JobMethods != nil { |
| 77 | panic(fmt.Sprintf("%s has both Methods and JobMethods defined (mutually exclusive)", name)) |
| 78 | } |
| 79 | if creator.FunctionOnly && creator.Methods == nil && creator.JobMethods == nil { |
| 80 | panic(fmt.Sprintf("%s is FunctionOnly but has no Methods or JobMethods defined", name)) |
| 81 | } |
| 82 | r[name] = creator |
| 83 | } |
| 84 | |
| 85 | func (r Registry) Lookup(name string) (Creator, bool) { |
| 86 | v, ok := r[name] |
| 87 | return v, ok |
| 88 | } |