generated from honeycombio/.github
/
metrics.go
100 lines (88 loc) · 3.37 KB
/
metrics.go
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
package pipelines
import (
"context"
"crypto/tls"
"errors"
"fmt"
"time"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/encoding/gzip"
hostMetrics "go.opentelemetry.io/contrib/instrumentation/host"
runtimeMetrics "go.opentelemetry.io/contrib/instrumentation/runtime"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/sdk/metric"
)
// NewMetricsPipeline takes a PipelineConfig and builds a metrics pipeline.
// It returns a shutdown function that should be called when terminating the pipeline.
func NewMetricsPipeline(c PipelineConfig) (func() error, error) {
metricExporter, err := newMetricsExporter(c.Protocol, c.Endpoint, c.Insecure, c.Headers)
if err != nil {
return nil, fmt.Errorf("failed to create metric exporter: %v", err)
}
var readerOpts []metric.PeriodicReaderOption
if c.ReportingPeriod != "" {
period, err := time.ParseDuration(c.ReportingPeriod)
if err != nil {
return nil, fmt.Errorf("invalid metric reporting period: %v", err)
}
if period <= 0 {
return nil, fmt.Errorf("invalid metric reporting period: %v", c.ReportingPeriod)
}
readerOpts = append(readerOpts, metric.WithInterval(period))
}
meterProvider := metric.NewMeterProvider(
metric.WithResource(c.Resource),
metric.WithReader(metric.NewPeriodicReader(metricExporter, readerOpts...)))
if err = runtimeMetrics.Start(runtimeMetrics.WithMeterProvider(meterProvider)); err != nil {
return nil, fmt.Errorf("failed to start runtime metrics: %v", err)
}
if err = hostMetrics.Start(hostMetrics.WithMeterProvider(meterProvider)); err != nil {
return nil, fmt.Errorf("failed to start host metrics: %v", err)
}
otel.SetMeterProvider(meterProvider)
return func() error {
return meterProvider.Shutdown(context.Background())
}, nil
}
//revive:disable:flag-parameter bools are fine for an internal function
func newMetricsExporter(protocol Protocol, endpoint string, insecure bool, headers map[string]string) (metric.Exporter, error) {
switch protocol {
case ProtocolGRPC:
return newGRPCMetricsExporter(endpoint, insecure, headers)
case ProtocolHTTPProtobuf:
return newHTTPMetricsExporter(endpoint, insecure, headers)
case ProtocolHTTPJSON:
return nil, errors.New("http/json is currently unsupported")
default:
return nil, errors.New("'" + string(protocol) + "' is not a supported protocol")
}
}
func newGRPCMetricsExporter(endpoint string, insecure bool, headers map[string]string) (metric.Exporter, error) {
secureOption := otlpmetricgrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
if insecure {
secureOption = otlpmetricgrpc.WithInsecure()
}
return otlpmetricgrpc.New(
context.Background(),
secureOption,
otlpmetricgrpc.WithEndpoint(endpoint),
otlpmetricgrpc.WithHeaders(headers),
otlpmetricgrpc.WithCompressor(gzip.Name),
)
}
func newHTTPMetricsExporter(endpoint string, insecure bool, headers map[string]string) (metric.Exporter, error) {
tlsconfig := &tls.Config{}
secureOption := otlpmetrichttp.WithTLSClientConfig(tlsconfig)
if insecure {
secureOption = otlpmetrichttp.WithInsecure()
}
return otlpmetrichttp.New(
context.Background(),
secureOption,
otlpmetrichttp.WithEndpoint(endpoint),
otlpmetrichttp.WithHeaders(headers),
otlpmetrichttp.WithCompression(otlpmetrichttp.GzipCompression),
)
}