2022-01-25 15:37:43 +01:00
# CCMetric collectors
2021-05-18 15:42:11 +02:00
2022-01-25 15:37:43 +01:00
This folder contains the collectors for the cc-metric-collector.
2021-03-27 13:39:43 +01:00
2022-01-25 15:37:43 +01:00
# Configuration
2021-05-12 14:41:54 +02:00
2021-11-26 15:57:11 +01:00
```json
2022-01-25 15:37:43 +01:00
{
"collector_type" : {
< collector specific configuration >
2021-11-26 15:57:11 +01:00
}
2022-01-25 15:37:43 +01:00
}
2021-11-26 15:57:11 +01:00
```
2022-01-25 15:37:43 +01:00
In contrast to the configuration files for sinks and receivers, the collectors configuration is not a list but a set of dicts. This is required because we didn't manage to partially read the type before loading the remaining configuration. We are eager to change this to the same format.
2021-11-26 15:57:11 +01:00
2022-01-25 15:37:43 +01:00
# Available collectors
2021-11-26 15:57:11 +01:00
2022-01-25 15:37:43 +01:00
* [`cpustat` ](./cpustatMetric.md )
* [`memstat` ](./memstatMetric.md )
* [`diskstat` ](./diskstatMetric.md )
* [`loadavg` ](./loadavgMetric.md )
* [`netstat` ](./netstatMetric.md )
* [`ibstat` ](./infinibandMetric.md )
* [`tempstat` ](./tempMetric.md )
* [`lustre` ](./lustreMetric.md )
* [`likwid` ](./likwidMetric.md )
* [`nvidia` ](./nvidiaMetric.md )
* [`customcmd` ](./customCmdMetric.md )
* [`ipmistat` ](./ipmiMetric.md )
* [`topprocs` ](./topprocsMetric.md )
2022-02-07 15:43:01 +01:00
* [`nfs3stat` ](./nfs3Metric.md )
* [`nfs4stat` ](./nfs4Metric.md )
2021-03-29 15:21:56 +02:00
## Todos
2021-11-26 15:57:11 +01:00
2021-11-26 15:58:59 +01:00
* [ ] Exclude devices for `diskstat` collector
* [ ] Aggreate metrics to higher topology entity (sum hwthread metrics to socket metric, ...). Needs to be configurable
2021-03-29 15:21:56 +02:00
# Contributing own collectors
A collector reads data from any source, parses it to metrics and submits these metrics to the `metric-collector` . A collector provides three function:
2021-03-29 15:23:55 +02:00
2022-01-25 15:37:43 +01:00
* `Name() string` : Return the name of the collector
* `Init(config json.RawMessage) error` : Initializes the collector using the given collector-specific config in JSON. Check if needed files/commands exists, ...
* `Initialized() bool` : Check if a collector is successfully initialized
* `Read(duration time.Duration, output chan ccMetric.CCMetric)` : Read, parse and submit data to the `output` channel as [`CCMetric` ](../internal/ccMetric/README.md ). If the collector has to measure anything for some duration, use the provided function argument `duration` .
2021-03-29 15:21:56 +02:00
* `Close()` : Closes down the collector.
2021-11-26 15:57:11 +01:00
It is recommanded to call `setup()` in the `Init()` function.
2021-03-29 15:21:56 +02:00
2022-01-25 15:37:43 +01:00
Finally, the collector needs to be registered in the `collectorManager.go` . There is a list of collectors called `AvailableCollectors` which is a map (`collector_type_string` -> `pointer to MetricCollector interface` ). Add a new entry with a descriptive name and the new collector.
2021-03-29 15:23:55 +02:00
2021-11-26 15:57:11 +01:00
## Sample collector
2021-03-29 15:34:32 +02:00
2021-11-26 15:57:11 +01:00
```go
package collectors
import (
"encoding/json"
"time"
2022-01-25 15:37:43 +01:00
lp "github.com/ClusterCockpit/cc-metric-collector/internal/ccMetric"
2021-11-26 15:57:11 +01:00
)
// Struct for the collector-specific JSON config
type SampleCollectorConfig struct {
ExcludeMetrics []string `json:"exclude_metrics"`
}
type SampleCollector struct {
2022-01-25 15:37:43 +01:00
metricCollector
2021-11-26 15:57:11 +01:00
config SampleCollectorConfig
}
2022-01-25 15:37:43 +01:00
func (m *SampleCollector) Init(config json.RawMessage) error {
2022-02-03 15:02:13 +01:00
// Check if already initialized
if m.init {
return nil
}
2021-11-26 15:57:11 +01:00
m.name = "SampleCollector"
m.setup()
if len(config) > 0 {
err := json.Unmarshal(config, & m.config)
if err != nil {
return err
}
}
2022-01-25 15:37:43 +01:00
m.meta = map[string]string{"source": m.name, "group": "Sample"}
2021-11-26 15:57:11 +01:00
m.init = true
return nil
}
2022-01-25 15:37:43 +01:00
func (m *SampleCollector) Read(interval time.Duration, output chan lp.CCMetric) {
2021-11-26 15:57:11 +01:00
if !m.init {
return
}
// tags for the metric, if type != node use proper type and type-id
2022-01-20 16:32:10 +01:00
tags := map[string]string{"type" : "node"}
2022-02-04 14:42:42 +01:00
x, err := GetMetric()
if err != nil {
cclog.ComponentError(m.name, fmt.Sprintf("Read(): %v", err))
}
2021-11-26 15:57:11 +01:00
// Each metric has exactly one field: value !
2022-02-07 11:12:03 +01:00
value := map[string]interface{}{"value": int64(x)}
if y, err := lp.New("sample_metric", tags, m.meta, value, time.Now()); err == nil {
2022-01-25 15:37:43 +01:00
output < - y
2021-11-26 15:57:11 +01:00
}
}
func (m *SampleCollector) Close() {
m.init = false
return
}
```