mirror of
				https://github.com/ClusterCockpit/cc-metric-collector.git
				synced 2025-11-04 02:35:07 +01:00 
			
		
		
		
	Units with cc-units (#64)
* Add option to normalize units with cc-unit * Add unit conversion to router * Add option to change unit prefix in the router * Add to MetricRouter README * Add order of operations in router to README * Use second add_tags/del_tags only if metric gets renamed
This commit is contained in:
		@@ -52,6 +52,11 @@ The CCMetric router sits in between the collectors and the sinks and can be used
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "rename_metrics" : {
 | 
					    "rename_metrics" : {
 | 
				
			||||||
        "metric_12345" : "mymetric"
 | 
					        "metric_12345" : "mymetric"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "normalize_units" : true,
 | 
				
			||||||
 | 
					    "change_unit_prefix" {
 | 
				
			||||||
 | 
					      "mem_used" : "G",
 | 
				
			||||||
 | 
					      "mem_total" : "G"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
@@ -192,6 +197,14 @@ This option takes a list of evaluable conditions and performs them one after the
 | 
				
			|||||||
```
 | 
					```
 | 
				
			||||||
The first line is comparable with the example in `drop_metrics`, it drops all metrics starting with `drop_metric_` and ending with a number. The second line drops all metrics of the first hardware thread (**not** recommended)
 | 
					The first line is comparable with the example in `drop_metrics`, it drops all metrics starting with `drop_metric_` and ending with a number. The second line drops all metrics of the first hardware thread (**not** recommended)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Manipulating the metric units
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## The `normalize_units` option
 | 
				
			||||||
 | 
					The cc-metric-collector tries to read the data from the system as it is reported. If available, it tries to read the metric unit from the system as well (e.g. from `/proc/meminfo`). The problem is that, depending on the source, the metric units are named differently. Just think about `byte`, `Byte`, `B`, `bytes`, ...
 | 
				
			||||||
 | 
					The [cc-units](https://github.com/ClusterCockpit/cc-units) package provides us a normalization option to use the same metric unit name for all metrics. It this option is set to true, all `unit` meta tags are normalized.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## The `change_unit_prefix` section
 | 
				
			||||||
 | 
					It is often the case that metrics are reported by the system using a rather outdated unit prefix (like `/proc/meminfo` still uses kByte despite current memory sizes are in the GByte range). If you want to change the prefix of a unit, you can do that with the help of [cc-units](https://github.com/ClusterCockpit/cc-units). The setting works on the metric name and requires the new prefix for the metric. The cc-units package determines the scaling factor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Aggregate metric values of the current interval with the `interval_aggregates` option
 | 
					# Aggregate metric values of the current interval with the `interval_aggregates` option
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -239,3 +252,22 @@ Use cases for `interval_aggregates`:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Order of operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The router performs the above mentioned options in a specific order. In order to get the logic you want for a specific metric, it is crucial to know the processing order:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Add the `hostname` tag (c)
 | 
				
			||||||
 | 
					- Manipulate the timestamp to the interval timestamp (c,r)
 | 
				
			||||||
 | 
					- Drop metrics based on `drop_metrics` and `drop_metrics_if` (c,r)
 | 
				
			||||||
 | 
					- Add tags based on `add_tags` (c,r)
 | 
				
			||||||
 | 
					- Delete tags based on `del_tags` (c,r)
 | 
				
			||||||
 | 
					- Rename metric based on `rename_metric` (c,r)
 | 
				
			||||||
 | 
					  - Add tags based on `add_tags` to still work if the configuration uses the new name (c,r) 
 | 
				
			||||||
 | 
					  - Delete tags based on `del_tags` to still work if the configuration uses the new name (c,r)
 | 
				
			||||||
 | 
					- Normalize units when `normalize_units` is set (c,r)
 | 
				
			||||||
 | 
					- Convert unit prefix based on `change_unit_prefix` (c,r)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Legend:
 | 
				
			||||||
 | 
					- 'c' if metric is coming from a collector
 | 
				
			||||||
 | 
					- 'r' if metric is coming from a receiver
 | 
				
			||||||
@@ -12,6 +12,7 @@ import (
 | 
				
			|||||||
	lp "github.com/ClusterCockpit/cc-metric-collector/internal/ccMetric"
 | 
						lp "github.com/ClusterCockpit/cc-metric-collector/internal/ccMetric"
 | 
				
			||||||
	agg "github.com/ClusterCockpit/cc-metric-collector/internal/metricAggregator"
 | 
						agg "github.com/ClusterCockpit/cc-metric-collector/internal/metricAggregator"
 | 
				
			||||||
	mct "github.com/ClusterCockpit/cc-metric-collector/internal/multiChanTicker"
 | 
						mct "github.com/ClusterCockpit/cc-metric-collector/internal/multiChanTicker"
 | 
				
			||||||
 | 
						units "github.com/ClusterCockpit/cc-units"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ROUTER_MAX_FORWARD = 50
 | 
					const ROUTER_MAX_FORWARD = 50
 | 
				
			||||||
@@ -35,6 +36,8 @@ type metricRouterConfig struct {
 | 
				
			|||||||
	IntervalStamp     bool                                 `json:"interval_timestamp"`  // Update timestamp periodically by ticker each interval?
 | 
						IntervalStamp     bool                                 `json:"interval_timestamp"`  // Update timestamp periodically by ticker each interval?
 | 
				
			||||||
	NumCacheIntervals int                                  `json:"num_cache_intervals"` // Number of intervals of cached metrics for evaluation
 | 
						NumCacheIntervals int                                  `json:"num_cache_intervals"` // Number of intervals of cached metrics for evaluation
 | 
				
			||||||
	MaxForward        int                                  `json:"max_forward"`         // Number of maximal forwarded metrics at one select
 | 
						MaxForward        int                                  `json:"max_forward"`         // Number of maximal forwarded metrics at one select
 | 
				
			||||||
 | 
						NormalizeUnits    bool                                 `json:"normalize_units"`     // Check unit meta flag and normalize it using cc-units
 | 
				
			||||||
 | 
						ChangeUnitPrefix  map[string]string                    `json:"change_unit_prefix"`  // Add prefix that should be applied to the metrics
 | 
				
			||||||
	dropMetrics       map[string]bool                      // Internal map for O(1) lookup
 | 
						dropMetrics       map[string]bool                      // Internal map for O(1) lookup
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -207,6 +210,38 @@ func (r *metricRouter) dropMetric(point lp.CCMetric) bool {
 | 
				
			|||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *metricRouter) prepareUnit(point lp.CCMetric) bool {
 | 
				
			||||||
 | 
						if r.config.NormalizeUnits {
 | 
				
			||||||
 | 
							if in_unit, ok := point.GetMeta("unit"); ok {
 | 
				
			||||||
 | 
								u := units.NewUnit(in_unit)
 | 
				
			||||||
 | 
								if u.Valid() {
 | 
				
			||||||
 | 
									point.AddMeta("unit", u.Short())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if newP, ok := r.config.ChangeUnitPrefix[point.Name()]; ok {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							newPrefix := units.NewPrefix(newP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if in_unit, ok := point.GetMeta("unit"); ok && newPrefix != units.InvalidPrefix {
 | 
				
			||||||
 | 
								u := units.NewUnit(in_unit)
 | 
				
			||||||
 | 
								if u.Valid() {
 | 
				
			||||||
 | 
									cclog.ComponentDebug("MetricRouter", "Change prefix to", newP, "for metric", point.Name())
 | 
				
			||||||
 | 
									conv, out_unit := units.GetUnitPrefixFactor(u, newPrefix)
 | 
				
			||||||
 | 
									if conv != nil && out_unit.Valid() {
 | 
				
			||||||
 | 
										if val, ok := point.GetField("value"); ok {
 | 
				
			||||||
 | 
											point.AddField("value", conv(val))
 | 
				
			||||||
 | 
											point.AddMeta("unit", out_unit.Short())
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Start starts the metric router
 | 
					// Start starts the metric router
 | 
				
			||||||
func (r *metricRouter) Start() {
 | 
					func (r *metricRouter) Start() {
 | 
				
			||||||
	// start timer if configured
 | 
						// start timer if configured
 | 
				
			||||||
@@ -232,9 +267,11 @@ func (r *metricRouter) Start() {
 | 
				
			|||||||
		if new, ok := r.config.RenameMetrics[name]; ok {
 | 
							if new, ok := r.config.RenameMetrics[name]; ok {
 | 
				
			||||||
			point.SetName(new)
 | 
								point.SetName(new)
 | 
				
			||||||
			point.AddMeta("oldname", name)
 | 
								point.AddMeta("oldname", name)
 | 
				
			||||||
 | 
								r.DoAddTags(point)
 | 
				
			||||||
 | 
								r.DoDelTags(point)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		r.DoAddTags(point)
 | 
					
 | 
				
			||||||
		r.DoDelTags(point)
 | 
							r.prepareUnit(point)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for _, o := range r.outputs {
 | 
							for _, o := range r.outputs {
 | 
				
			||||||
			o <- point
 | 
								o <- point
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user