mirror of
https://github.com/ClusterCockpit/cc-metric-collector.git
synced 2024-12-24 14:49:05 +01:00
Change CCMetric's internal data structure (#22)
* package ccmetric rewrite * Create deep copy in New() to avoid access conflicts * Renamed TagMap() -> Tags(), MetaMap() -> Meta Co-authored-by: Holger Obermaier <40787752+ho-ob@users.noreply.github.com>
This commit is contained in:
parent
862630a218
commit
6ff6cb7219
@ -14,62 +14,73 @@ import (
|
||||
//
|
||||
// See: https://docs.influxdata.com/influxdb/latest/reference/syntax/line-protocol/
|
||||
type ccMetric struct {
|
||||
name string // Measurement name
|
||||
tags []*lp.Tag // ordered list of of tags
|
||||
fields []*lp.Field // unordered list of of fields
|
||||
tm time.Time // timestamp
|
||||
meta []*lp.Tag // odered list of meta data tags
|
||||
name string // Measurement name
|
||||
meta map[string]string // map of meta data tags
|
||||
tags map[string]string // map of of tags
|
||||
fields []*lp.Field // unordered list of of fields
|
||||
tm time.Time // timestamp
|
||||
}
|
||||
|
||||
// ccmetric access functions
|
||||
type CCMetric interface {
|
||||
lp.MutableMetric // SetTime, AddTag, AddField
|
||||
AddMeta(key, value string) // Add a meta data tag
|
||||
MetaList() []*lp.Tag // Returns the meta data list
|
||||
RemoveTag(key string) // Remove a tag addressed by its key
|
||||
GetTag(key string) (string, bool) // Get a tag addressed by its key
|
||||
GetMeta(key string) (string, bool) // Get a meta data tab addressed by its key
|
||||
lp.Metric // Time(), Name(), TagList(), FieldList()
|
||||
|
||||
SetTime(t time.Time)
|
||||
|
||||
Meta() map[string]string // Map of meta data tags
|
||||
MetaList() []*lp.Tag // Ordered list of meta data
|
||||
AddMeta(key, value string) // Add a meta data tag
|
||||
GetMeta(key string) (string, bool) // Get a meta data tab addressed by its key
|
||||
|
||||
Tags() map[string]string // Map of tags
|
||||
AddTag(key, value string) // Add a tag
|
||||
GetTag(key string) (string, bool) // Get a tag by its key
|
||||
RemoveTag(key string) // Remove a tag by its key
|
||||
|
||||
GetField(key string) (interface{}, bool) // Get a field addressed by its key
|
||||
HasField(key string) bool // Check if a field key is present
|
||||
RemoveField(key string) // Remove a field addressed by its key
|
||||
}
|
||||
|
||||
// Meta returns the list of meta data tags as key-value mapping
|
||||
// Meta returns the meta data tags as key-value mapping
|
||||
func (m *ccMetric) Meta() map[string]string {
|
||||
meta := make(map[string]string, len(m.meta))
|
||||
for _, m := range m.meta {
|
||||
meta[m.Key] = m.Value
|
||||
}
|
||||
return meta
|
||||
return m.meta
|
||||
}
|
||||
|
||||
// MetaList returns the list of meta data tags
|
||||
// MetaList returns the the list of meta data tags as sorted list of key value tags
|
||||
func (m *ccMetric) MetaList() []*lp.Tag {
|
||||
return m.meta
|
||||
|
||||
ml := make([]*lp.Tag, 0, len(m.meta))
|
||||
for key, value := range m.meta {
|
||||
ml = append(ml, &lp.Tag{Key: key, Value: value})
|
||||
}
|
||||
sort.Slice(ml, func(i, j int) bool { return ml[i].Key < ml[j].Key })
|
||||
return ml
|
||||
}
|
||||
|
||||
// String implements the stringer interface for data type ccMetric
|
||||
func (m *ccMetric) String() string {
|
||||
return fmt.Sprintf("%s %v %v %v %d", m.name, m.Tags(), m.Meta(), m.Fields(), m.tm.UnixNano())
|
||||
return fmt.Sprintf("%s %v %v %v %d", m.name, m.tags, m.meta, m.Fields(), m.tm.UnixNano())
|
||||
}
|
||||
|
||||
// Name returns the metric name
|
||||
// Name returns the measurement name
|
||||
func (m *ccMetric) Name() string {
|
||||
return m.name
|
||||
}
|
||||
|
||||
// Tags returns the the list of tags as key-value-mapping
|
||||
func (m *ccMetric) Tags() map[string]string {
|
||||
tags := make(map[string]string, len(m.tags))
|
||||
for _, tag := range m.tags {
|
||||
tags[tag.Key] = tag.Value
|
||||
}
|
||||
return tags
|
||||
return m.tags
|
||||
}
|
||||
|
||||
// TagList returns the list of tags
|
||||
// TagList returns the the list of tags as sorted list of key value tags
|
||||
func (m *ccMetric) TagList() []*lp.Tag {
|
||||
return m.tags
|
||||
tl := make([]*lp.Tag, 0, len(m.tags))
|
||||
for key, value := range m.tags {
|
||||
tl = append(tl, &lp.Tag{Key: key, Value: value})
|
||||
}
|
||||
sort.Slice(tl, func(i, j int) bool { return tl[i].Key < tl[j].Key })
|
||||
return tl
|
||||
}
|
||||
|
||||
// Fields returns the list of fields as key-value-mapping
|
||||
@ -99,112 +110,50 @@ func (m *ccMetric) SetTime(t time.Time) {
|
||||
|
||||
// HasTag checks if a tag with key equal to <key> is present in the list of tags
|
||||
func (m *ccMetric) HasTag(key string) bool {
|
||||
for _, tag := range m.tags {
|
||||
if tag.Key == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
_, ok := m.tags[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
// GetTag returns the tag with tag's key equal to <key>
|
||||
func (m *ccMetric) GetTag(key string) (string, bool) {
|
||||
for _, tag := range m.tags {
|
||||
if tag.Key == key {
|
||||
return tag.Value, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
value, ok := m.tags[key]
|
||||
return value, ok
|
||||
}
|
||||
|
||||
// RemoveTag removes the tag with tag's key equal to <key>
|
||||
// and keeps the tag list ordered by the keys
|
||||
func (m *ccMetric) RemoveTag(key string) {
|
||||
for i, tag := range m.tags {
|
||||
if tag.Key == key {
|
||||
copy(m.tags[i:], m.tags[i+1:])
|
||||
m.tags[len(m.tags)-1] = nil
|
||||
m.tags = m.tags[:len(m.tags)-1]
|
||||
return
|
||||
}
|
||||
}
|
||||
delete(m.tags, key)
|
||||
}
|
||||
|
||||
// AddTag adds a tag (consisting of key and value)
|
||||
// and keeps the tag list ordered by the keys
|
||||
func (m *ccMetric) AddTag(key, value string) {
|
||||
for i, tag := range m.tags {
|
||||
if key > tag.Key {
|
||||
continue
|
||||
}
|
||||
|
||||
if key == tag.Key {
|
||||
tag.Value = value
|
||||
return
|
||||
}
|
||||
|
||||
m.tags = append(m.tags, nil)
|
||||
copy(m.tags[i+1:], m.tags[i:])
|
||||
m.tags[i] = &lp.Tag{Key: key, Value: value}
|
||||
return
|
||||
}
|
||||
|
||||
m.tags = append(m.tags, &lp.Tag{Key: key, Value: value})
|
||||
m.tags[key] = value
|
||||
}
|
||||
|
||||
// HasTag checks if a meta data tag with meta data's key equal to <key> is present in the list of meta data tags
|
||||
func (m *ccMetric) HasMeta(key string) bool {
|
||||
for _, tag := range m.meta {
|
||||
if tag.Key == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
_, ok := m.meta[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
// GetMeta returns the meta data tag with meta data's key equal to <key>
|
||||
func (m *ccMetric) GetMeta(key string) (string, bool) {
|
||||
for _, tag := range m.meta {
|
||||
if tag.Key == key {
|
||||
return tag.Value, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
value, ok := m.meta[key]
|
||||
return value, ok
|
||||
}
|
||||
|
||||
// RemoveMeta removes the meta data tag with tag's key equal to <key>
|
||||
// and keeps the meta data tag list ordered by the keys
|
||||
func (m *ccMetric) RemoveMeta(key string) {
|
||||
for i, tag := range m.meta {
|
||||
if tag.Key == key {
|
||||
copy(m.meta[i:], m.meta[i+1:])
|
||||
m.meta[len(m.meta)-1] = nil
|
||||
m.meta = m.meta[:len(m.meta)-1]
|
||||
return
|
||||
}
|
||||
}
|
||||
delete(m.meta, key)
|
||||
}
|
||||
|
||||
// AddMeta adds a meta data tag (consisting of key and value)
|
||||
// and keeps the meta data list ordered by the keys
|
||||
func (m *ccMetric) AddMeta(key, value string) {
|
||||
for i, tag := range m.meta {
|
||||
if key > tag.Key {
|
||||
continue
|
||||
}
|
||||
|
||||
if key == tag.Key {
|
||||
tag.Value = value
|
||||
return
|
||||
}
|
||||
|
||||
m.meta = append(m.meta, nil)
|
||||
copy(m.meta[i+1:], m.meta[i:])
|
||||
m.meta[i] = &lp.Tag{Key: key, Value: value}
|
||||
return
|
||||
}
|
||||
|
||||
m.meta = append(m.meta, &lp.Tag{Key: key, Value: value})
|
||||
m.meta[key] = value
|
||||
}
|
||||
|
||||
// AddField adds a field (consisting of key and value) to the unordered list of fields
|
||||
@ -261,62 +210,49 @@ func New(
|
||||
) (CCMetric, error) {
|
||||
m := &ccMetric{
|
||||
name: name,
|
||||
tags: nil,
|
||||
fields: nil,
|
||||
tags: make(map[string]string, len(tags)),
|
||||
meta: make(map[string]string, len(meta)),
|
||||
fields: make([]*lp.Field, 0, len(fields)),
|
||||
tm: tm,
|
||||
meta: nil,
|
||||
}
|
||||
|
||||
// Sorted list of tags
|
||||
if len(tags) > 0 {
|
||||
m.tags = make([]*lp.Tag, 0, len(tags))
|
||||
for k, v := range tags {
|
||||
m.tags = append(m.tags,
|
||||
&lp.Tag{Key: k, Value: v})
|
||||
}
|
||||
sort.Slice(m.tags, func(i, j int) bool { return m.tags[i].Key < m.tags[j].Key })
|
||||
// deep copy tags
|
||||
for k, v := range tags {
|
||||
m.tags[k] = v
|
||||
}
|
||||
|
||||
// Sorted list of meta data tags
|
||||
if len(meta) > 0 {
|
||||
m.meta = make([]*lp.Tag, 0, len(meta))
|
||||
for k, v := range meta {
|
||||
m.meta = append(m.meta,
|
||||
&lp.Tag{Key: k, Value: v})
|
||||
}
|
||||
sort.Slice(m.meta, func(i, j int) bool { return m.meta[i].Key < m.meta[j].Key })
|
||||
// deep copy meta data tags
|
||||
for k, v := range meta {
|
||||
m.meta[k] = v
|
||||
}
|
||||
|
||||
// Unsorted list of fields
|
||||
if len(fields) > 0 {
|
||||
m.fields = make([]*lp.Field, 0, len(fields))
|
||||
for k, v := range fields {
|
||||
v := convertField(v)
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
m.AddField(k, v)
|
||||
for k, v := range fields {
|
||||
v := convertField(v)
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
m.AddField(k, v)
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// FromMetric copies the metric <other>
|
||||
func FromMetric(other CCMetric) CCMetric {
|
||||
func FromMetric(other ccMetric) CCMetric {
|
||||
m := &ccMetric{
|
||||
name: other.Name(),
|
||||
tags: make([]*lp.Tag, len(other.TagList())),
|
||||
tags: make(map[string]string),
|
||||
fields: make([]*lp.Field, len(other.FieldList())),
|
||||
meta: make([]*lp.Tag, len(other.MetaList())),
|
||||
meta: make(map[string]string),
|
||||
tm: other.Time(),
|
||||
}
|
||||
|
||||
for i, tag := range other.TagList() {
|
||||
m.tags[i] = &lp.Tag{Key: tag.Key, Value: tag.Value}
|
||||
for key, value := range other.Tags() {
|
||||
m.tags[key] = value
|
||||
}
|
||||
for i, s := range other.MetaList() {
|
||||
m.meta[i] = &lp.Tag{Key: s.Key, Value: s.Value}
|
||||
for key, value := range other.Meta() {
|
||||
m.meta[key] = value
|
||||
}
|
||||
|
||||
for i, field := range other.FieldList() {
|
||||
@ -329,17 +265,14 @@ func FromMetric(other CCMetric) CCMetric {
|
||||
func FromInfluxMetric(other lp.Metric) CCMetric {
|
||||
m := &ccMetric{
|
||||
name: other.Name(),
|
||||
tags: make([]*lp.Tag, len(other.TagList())),
|
||||
tags: make(map[string]string),
|
||||
fields: make([]*lp.Field, len(other.FieldList())),
|
||||
meta: make([]*lp.Tag, 0),
|
||||
meta: make(map[string]string),
|
||||
tm: other.Time(),
|
||||
}
|
||||
|
||||
for i, otherTag := range other.TagList() {
|
||||
m.tags[i] = &lp.Tag{
|
||||
Key: otherTag.Key,
|
||||
Value: otherTag.Value,
|
||||
}
|
||||
for _, otherTag := range other.TagList() {
|
||||
m.tags[otherTag.Key] = otherTag.Value
|
||||
}
|
||||
|
||||
for i, otherField := range other.FieldList() {
|
||||
|
@ -141,11 +141,11 @@ func (r *metricRouter) EvalCondition(cond string, point lp.CCMetric) (bool, erro
|
||||
// Add metric name, tags, meta data, fields and timestamp to the parameter list
|
||||
params := make(map[string]interface{})
|
||||
params["name"] = point.Name()
|
||||
for _, t := range point.TagList() {
|
||||
params[t.Key] = t.Value
|
||||
for key, value := range point.Tags() {
|
||||
params[key] = value
|
||||
}
|
||||
for _, m := range point.MetaList() {
|
||||
params[m.Key] = m.Value
|
||||
for key, value := range point.Meta() {
|
||||
params[key] = value
|
||||
}
|
||||
for _, f := range point.FieldList() {
|
||||
params[f.Key] = f.Value
|
||||
|
@ -30,16 +30,16 @@ func (s *GangliaSink) Write(point lp.CCMetric) error {
|
||||
var err error = nil
|
||||
var tagsstr []string
|
||||
var argstr []string
|
||||
for _, t := range point.TagList() {
|
||||
switch t.Key {
|
||||
for key, value := range point.Tags() {
|
||||
switch key {
|
||||
case "cluster":
|
||||
argstr = append(argstr, fmt.Sprintf("--cluster=%s", t.Value))
|
||||
argstr = append(argstr, fmt.Sprintf("--cluster=%s", value))
|
||||
case "unit":
|
||||
argstr = append(argstr, fmt.Sprintf("--units=%s", t.Value))
|
||||
argstr = append(argstr, fmt.Sprintf("--units=%s", value))
|
||||
case "group":
|
||||
argstr = append(argstr, fmt.Sprintf("--group=%s", t.Value))
|
||||
argstr = append(argstr, fmt.Sprintf("--group=%s", value))
|
||||
default:
|
||||
tagsstr = append(tagsstr, fmt.Sprintf("%s=%s", t.Key, t.Value))
|
||||
tagsstr = append(tagsstr, fmt.Sprintf("%s=%s", key, value))
|
||||
}
|
||||
}
|
||||
if len(tagsstr) > 0 {
|
||||
|
@ -5,10 +5,11 @@ import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
lp "github.com/ClusterCockpit/cc-metric-collector/internal/ccMetric"
|
||||
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
|
||||
influxdb2Api "github.com/influxdata/influxdb-client-go/v2/api"
|
||||
"log"
|
||||
)
|
||||
|
||||
type InfluxSink struct {
|
||||
@ -61,12 +62,12 @@ func (s *InfluxSink) Init(config sinkConfig) error {
|
||||
func (s *InfluxSink) Write(point lp.CCMetric) error {
|
||||
tags := map[string]string{}
|
||||
fields := map[string]interface{}{}
|
||||
for _, t := range point.TagList() {
|
||||
tags[t.Key] = t.Value
|
||||
for key, value := range point.Tags() {
|
||||
tags[key] = value
|
||||
}
|
||||
if s.meta_as_tags {
|
||||
for _, m := range point.MetaList() {
|
||||
tags[m.Key] = m.Value
|
||||
for key, value := range point.Meta() {
|
||||
tags[key] = value
|
||||
}
|
||||
}
|
||||
for _, f := range point.FieldList() {
|
||||
|
Loading…
Reference in New Issue
Block a user