1 package probers 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/letsencrypt/boulder/cmd" 9 "github.com/prometheus/client_golang/prometheus" 10 ) 11 12 var ( 13 // Registry is the global mapping of all `Configurer` types. Types 14 // are added to this mapping on import by including a call to 15 // `Register` in their `init` function. 16 Registry = make(map[string]Configurer) 17 ) 18 19 // Prober is the interface for `Prober` types. 20 type Prober interface { 21 // Name returns a name that uniquely identifies the monitor that 22 // configured this `Prober`. 23 Name() string 24 25 // Kind returns a name that uniquely identifies the `Kind` of 26 // `Prober`. 27 Kind() string 28 29 // Probe attempts the configured request or query, Each `Prober` 30 // must treat the duration passed to it as a timeout. 31 Probe(time.Duration) (bool, time.Duration) 32 } 33 34 // Configurer is the interface for `Configurer` types. 35 type Configurer interface { 36 // Kind returns a name that uniquely identifies the `Kind` of 37 // `Configurer`. 38 Kind() string 39 40 // UnmarshalSettings unmarshals YAML as bytes to a `Configurer` 41 // object. 42 UnmarshalSettings([]byte) (Configurer, error) 43 44 // MakeProber constructs a `Prober` object from the contents of the 45 // bound `Configurer` object. If the `Configurer` cannot be 46 // validated, an error appropriate for end-user consumption is 47 // returned instead. The map of `prometheus.Collector` objects passed to 48 // MakeProber should be the same as the return value from Instrument() 49 MakeProber(map[string]prometheus.Collector) (Prober, error) 50 51 // Instrument constructs any `prometheus.Collector` objects that a prober of 52 // the configured type will need to report its own metrics. A map is 53 // returned containing the constructed objects, indexed by the name of the 54 // prometheus metric. If no objects were constructed, nil is returned. 55 Instrument() map[string]prometheus.Collector 56 } 57 58 // Settings is exported as a temporary receiver for the `settings` field 59 // of `MonConf`. `Settings` is always marshaled back to bytes and then 60 // unmarshalled into the `Configurer` specified by the `Kind` field of 61 // the `MonConf`. 62 type Settings map[string]interface{} 63 64 // normalizeKind normalizes the input string by stripping spaces and 65 // transforming it into lowercase 66 func normalizeKind(kind string) string { 67 return strings.Trim(strings.ToLower(kind), " ") 68 } 69 70 // GetConfigurer returns the probe configurer specified by name from 71 // `Registry`. 72 func GetConfigurer(kind string) (Configurer, error) { 73 name := normalizeKind(kind) 74 // check if exists 75 if _, ok := Registry[name]; ok { 76 return Registry[name], nil 77 } 78 return nil, fmt.Errorf("%s is not a registered Prober type", kind) 79 } 80 81 // Register is called by the `init` function of every `Configurer` to 82 // add the caller to the global `Registry` map. If the caller attempts 83 // to add a `Configurer` to the registry using the same name as a prior 84 // `Configurer` Observer will exit after logging an error. 85 func Register(c Configurer) { 86 name := normalizeKind(c.Kind()) 87 // check for name collision 88 if _, exists := Registry[name]; exists { 89 cmd.Fail(fmt.Sprintf( 90 "problem registering configurer %s: name collision", c.Kind())) 91 } 92 Registry[name] = c 93 } 94