File: main.go

package info (click to toggle)
golang-collectd 0.3.0%2Bgit20181025.f80706d-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 312 kB
  • sloc: makefile: 3
file content (154 lines) | stat: -rw-r--r-- 4,235 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Package api defines data types representing core collectd data types.
package api // import "collectd.org/api"

import (
	"context"
	"fmt"
	"log"
	"strconv"
	"strings"
	"time"
)

// Value represents either a Gauge or a Derive. It is Go's equivalent to the C
// union value_t. If a function accepts a Value, you may pass in either a Gauge
// or a Derive. Passing in any other type may or may not panic.
type Value interface {
	Type() string
}

// Gauge represents a gauge metric value, such as a temperature.
// This is Go's equivalent to the C type "gauge_t".
type Gauge float64

// Type returns "gauge".
func (v Gauge) Type() string { return "gauge" }

// Derive represents a counter metric value, such as bytes sent over the
// network. When the counter wraps around (overflows) or is reset, this is
// interpreted as a (huge) negative rate, which is discarded.
// This is Go's equivalent to the C type "derive_t".
type Derive int64

// Type returns "derive".
func (v Derive) Type() string { return "derive" }

// Counter represents a counter metric value, such as bytes sent over the
// network. When a counter value is smaller than the previous value, a wrap
// around (overflow) is assumed. This causes huge spikes in case a counter is
// reset. Only use Counter for very specific cases. If in doubt, use Derive
// instead.
// This is Go's equivalent to the C type "counter_t".
type Counter uint64

// Type returns "counter".
func (v Counter) Type() string { return "counter" }

// Identifier identifies one metric.
type Identifier struct {
	Host                   string
	Plugin, PluginInstance string
	Type, TypeInstance     string
}

// ParseIdentifier parses the identifier encoded in s and returns it.
func ParseIdentifier(s string) (Identifier, error) {
	fields := strings.Split(s, "/")
	if len(fields) != 3 {
		return Identifier{}, fmt.Errorf("not a valid identifier: %q", s)
	}

	id := Identifier{
		Host:   fields[0],
		Plugin: fields[1],
		Type:   fields[2],
	}

	if i := strings.Index(id.Plugin, "-"); i != -1 {
		id.PluginInstance = id.Plugin[i+1:]
		id.Plugin = id.Plugin[:i]
	}

	if i := strings.Index(id.Type, "-"); i != -1 {
		id.TypeInstance = id.Type[i+1:]
		id.Type = id.Type[:i]
	}

	return id, nil
}

// ValueList represents one (set of) data point(s) of one metric. It is Go's
// equivalent of the C type value_list_t.
type ValueList struct {
	Identifier
	Time     time.Time
	Interval time.Duration
	Values   []Value
	DSNames  []string
}

// DSName returns the name of the data source at the given index. If vl.DSNames
// is nil, returns "value" if there is a single value and a string
// representation of index otherwise.
func (vl *ValueList) DSName(index int) string {
	if vl.DSNames != nil {
		return vl.DSNames[index]
	} else if len(vl.Values) != 1 {
		return strconv.FormatInt(int64(index), 10)
	}

	return "value"
}

// Writer are objects accepting a ValueList for writing, for example to the
// network.
type Writer interface {
	Write(context.Context, *ValueList) error
}

// String returns a string representation of the Identifier.
func (id Identifier) String() string {
	str := id.Host + "/" + id.Plugin
	if id.PluginInstance != "" {
		str += "-" + id.PluginInstance
	}
	str += "/" + id.Type
	if id.TypeInstance != "" {
		str += "-" + id.TypeInstance
	}
	return str
}

// Dispatcher implements a multiplexer for Writer, i.e. each ValueList
// written to it is copied and written to each registered Writer.
type Dispatcher struct {
	writers []Writer
}

// Add adds a Writer to the Dispatcher.
func (d *Dispatcher) Add(w Writer) {
	d.writers = append(d.writers, w)
}

// Len returns the number of Writers belonging to the Dispatcher.
func (d *Dispatcher) Len() int {
	return len(d.writers)
}

// Write starts a new Goroutine for each Writer which creates a copy of the
// ValueList and then calls the Writer with the copy. It returns nil
// immediately.
func (d *Dispatcher) Write(ctx context.Context, vl *ValueList) error {
	for _, w := range d.writers {
		go func(w Writer) {
			vlCopy := vl
			vlCopy.Values = make([]Value, len(vl.Values))
			copy(vlCopy.Values, vl.Values)

			if err := w.Write(ctx, vlCopy); err != nil {
				log.Printf("%T.Write(): %v", w, err)
			}
		}(w)
	}
	return nil
}