Skip to content

Commit 97135a3

Browse files
committed
Instrument exporters (#14)
* Allow for dual instrumentation * remove log * Add back mutators
1 parent c157b12 commit 97135a3

File tree

1 file changed

+129
-9
lines changed

1 file changed

+129
-9
lines changed

obsreport/obsreport_exporter.go

+129-9
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,44 @@ import (
2020
"go.opencensus.io/stats"
2121
"go.opencensus.io/tag"
2222
"go.opentelemetry.io/otel/attribute"
23+
"go.opentelemetry.io/otel/metric"
24+
"go.opentelemetry.io/otel/metric/instrument"
25+
"go.opentelemetry.io/otel/metric/instrument/syncint64"
26+
"go.opentelemetry.io/otel/metric/unit"
2327
"go.opentelemetry.io/otel/trace"
28+
"go.uber.org/zap"
2429

2530
"go.opentelemetry.io/collector/component"
2631
"go.opentelemetry.io/collector/config"
2732
"go.opentelemetry.io/collector/config/configtelemetry"
33+
"go.opentelemetry.io/collector/featuregate"
34+
"go.opentelemetry.io/collector/internal/obsreportconfig"
2835
"go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics"
2936
)
3037

38+
const (
39+
exporterName = "exporter"
40+
41+
exporterScope = scopeName + nameSep + exporterName
42+
)
43+
3144
// Exporter is a helper to add observability to a component.Exporter.
3245
type Exporter struct {
3346
level configtelemetry.Level
3447
spanNamePrefix string
3548
mutators []tag.Mutator
3649
tracer trace.Tracer
50+
meter metric.Meter
51+
logger *zap.Logger
52+
53+
useOtelForMetrics bool
54+
otelAttrs []attribute.KeyValue
55+
sentSpans syncint64.Counter
56+
failedToSendSpans syncint64.Counter
57+
sentMetricPoints syncint64.Counter
58+
failedToSendMetricPoints syncint64.Counter
59+
sentLogRecords syncint64.Counter
60+
failedToSendLogRecords syncint64.Counter
3761
}
3862

3963
// ExporterSettings are settings for creating an Exporter.
@@ -44,12 +68,70 @@ type ExporterSettings struct {
4468

4569
// NewExporter creates a new Exporter.
4670
func NewExporter(cfg ExporterSettings) *Exporter {
47-
return &Exporter{
71+
exp := &Exporter{
4872
level: cfg.ExporterCreateSettings.TelemetrySettings.MetricsLevel,
4973
spanNamePrefix: obsmetrics.ExporterPrefix + cfg.ExporterID.String(),
5074
mutators: []tag.Mutator{tag.Upsert(obsmetrics.TagKeyExporter, cfg.ExporterID.String(), tag.WithTTL(tag.TTLNoPropagation))},
5175
tracer: cfg.ExporterCreateSettings.TracerProvider.Tracer(cfg.ExporterID.String()),
76+
meter: cfg.ExporterCreateSettings.MeterProvider.Meter(exporterScope),
77+
logger: cfg.ExporterCreateSettings.Logger,
78+
79+
useOtelForMetrics: featuregate.GetRegistry().IsEnabled(obsreportconfig.UseOtelForInternalMetricsfeatureGateID),
80+
otelAttrs: []attribute.KeyValue{
81+
attribute.String(obsmetrics.ExporterKey, cfg.ExporterID.String()),
82+
},
5283
}
84+
exp.createOtelMetrics()
85+
86+
return exp
87+
}
88+
89+
func (exp *Exporter) createOtelMetrics() {
90+
if !exp.useOtelForMetrics {
91+
return
92+
}
93+
94+
var err error
95+
handleError := func(metricName string, err error) {
96+
if err != nil {
97+
exp.logger.Warn("failed to create otel instrument", zap.Error(err), zap.String("metric", metricName))
98+
}
99+
}
100+
exp.sentSpans, err = exp.meter.SyncInt64().Counter(
101+
obsmetrics.ExporterPrefix+obsmetrics.SentSpansKey,
102+
instrument.WithDescription("Number of spans successfully sent to destination."),
103+
instrument.WithUnit(unit.Dimensionless))
104+
handleError(obsmetrics.ExporterPrefix+obsmetrics.SentSpansKey, err)
105+
106+
exp.failedToSendSpans, err = exp.meter.SyncInt64().Counter(
107+
obsmetrics.ExporterPrefix+obsmetrics.FailedToSendSpansKey,
108+
instrument.WithDescription("Number of spans in failed attempts to send to destination."),
109+
instrument.WithUnit(unit.Dimensionless))
110+
handleError(obsmetrics.ExporterPrefix+obsmetrics.FailedToSendSpansKey, err)
111+
112+
exp.sentMetricPoints, err = exp.meter.SyncInt64().Counter(
113+
obsmetrics.ExporterPrefix+obsmetrics.SentMetricPointsKey,
114+
instrument.WithDescription("Number of metric points successfully sent to destination."),
115+
instrument.WithUnit(unit.Dimensionless))
116+
handleError(obsmetrics.ExporterPrefix+obsmetrics.SentMetricPointsKey, err)
117+
118+
exp.failedToSendMetricPoints, err = exp.meter.SyncInt64().Counter(
119+
obsmetrics.ExporterPrefix+obsmetrics.FailedToSendMetricPointsKey,
120+
instrument.WithDescription("Number of metric points in failed attempts to send to destination."),
121+
instrument.WithUnit(unit.Dimensionless))
122+
handleError(obsmetrics.ExporterPrefix+obsmetrics.FailedToSendMetricPointsKey, err)
123+
124+
exp.sentLogRecords, err = exp.meter.SyncInt64().Counter(
125+
obsmetrics.ExporterPrefix+obsmetrics.SentLogRecordsKey,
126+
instrument.WithDescription("Number of log record successfully sent to destination."),
127+
instrument.WithUnit(unit.Dimensionless))
128+
handleError(obsmetrics.ExporterPrefix+obsmetrics.SentLogRecordsKey, err)
129+
130+
exp.failedToSendLogRecords, err = exp.meter.SyncInt64().Counter(
131+
obsmetrics.ExporterPrefix+obsmetrics.FailedToSendLogRecordsKey,
132+
instrument.WithDescription("Number of log records in failed attempts to send to destination."),
133+
instrument.WithUnit(unit.Dimensionless))
134+
handleError(obsmetrics.ExporterPrefix+obsmetrics.FailedToSendLogRecordsKey, err)
53135
}
54136

55137
// StartTracesOp is called at the start of an Export operation.
@@ -62,7 +144,7 @@ func (exp *Exporter) StartTracesOp(ctx context.Context) context.Context {
62144
// EndTracesOp completes the export operation that was started with StartTracesOp.
63145
func (exp *Exporter) EndTracesOp(ctx context.Context, numSpans int, err error) {
64146
numSent, numFailedToSend := toNumItems(numSpans, err)
65-
exp.recordMetrics(ctx, numSent, numFailedToSend, obsmetrics.ExporterSentSpans, obsmetrics.ExporterFailedToSendSpans)
147+
exp.recordMetrics(ctx, config.TracesDataType, numSent, numFailedToSend)
66148
endSpan(ctx, err, numSent, numFailedToSend, obsmetrics.SentSpansKey, obsmetrics.FailedToSendSpansKey)
67149
}
68150

@@ -77,7 +159,7 @@ func (exp *Exporter) StartMetricsOp(ctx context.Context) context.Context {
77159
// StartMetricsOp.
78160
func (exp *Exporter) EndMetricsOp(ctx context.Context, numMetricPoints int, err error) {
79161
numSent, numFailedToSend := toNumItems(numMetricPoints, err)
80-
exp.recordMetrics(ctx, numSent, numFailedToSend, obsmetrics.ExporterSentMetricPoints, obsmetrics.ExporterFailedToSendMetricPoints)
162+
exp.recordMetrics(ctx, config.MetricsDataType, numSent, numFailedToSend)
81163
endSpan(ctx, err, numSent, numFailedToSend, obsmetrics.SentMetricPointsKey, obsmetrics.FailedToSendMetricPointsKey)
82164
}
83165

@@ -91,7 +173,7 @@ func (exp *Exporter) StartLogsOp(ctx context.Context) context.Context {
91173
// EndLogsOp completes the export operation that was started with StartLogsOp.
92174
func (exp *Exporter) EndLogsOp(ctx context.Context, numLogRecords int, err error) {
93175
numSent, numFailedToSend := toNumItems(numLogRecords, err)
94-
exp.recordMetrics(ctx, numSent, numFailedToSend, obsmetrics.ExporterSentLogRecords, obsmetrics.ExporterFailedToSendLogRecords)
176+
exp.recordMetrics(ctx, config.LogsDataType, numSent, numFailedToSend)
95177
endSpan(ctx, err, numSent, numFailedToSend, obsmetrics.SentLogRecordsKey, obsmetrics.FailedToSendLogRecordsKey)
96178
}
97179

@@ -103,16 +185,54 @@ func (exp *Exporter) startOp(ctx context.Context, operationSuffix string) contex
103185
return ctx
104186
}
105187

106-
func (exp *Exporter) recordMetrics(ctx context.Context, numSent, numFailedToSend int64, sentMeasure, failedToSendMeasure *stats.Int64Measure) {
188+
func (exp *Exporter) recordMetrics(ctx context.Context, dataType config.DataType, numSent, numFailed int64) {
107189
if exp.level == configtelemetry.LevelNone {
108190
return
109191
}
110-
// Ignore the error for now. This should not happen.
111-
if numFailedToSend > 0 {
112-
_ = stats.RecordWithTags(ctx, exp.mutators, sentMeasure.M(numSent), failedToSendMeasure.M(numFailedToSend))
192+
if exp.useOtelForMetrics {
193+
exp.recordWithOtel(ctx, dataType, numSent, numFailed)
113194
} else {
114-
_ = stats.RecordWithTags(ctx, exp.mutators, sentMeasure.M(numSent))
195+
exp.recordWithOC(ctx, dataType, numSent, numFailed)
196+
}
197+
}
198+
199+
func (exp *Exporter) recordWithOtel(ctx context.Context, dataType config.DataType, sent int64, failed int64) {
200+
var sentMeasure, failedMeasure syncint64.Counter
201+
switch dataType {
202+
case config.TracesDataType:
203+
sentMeasure = exp.sentSpans
204+
failedMeasure = exp.failedToSendSpans
205+
case config.MetricsDataType:
206+
sentMeasure = exp.sentMetricPoints
207+
failedMeasure = exp.failedToSendMetricPoints
208+
case config.LogsDataType:
209+
sentMeasure = exp.sentLogRecords
210+
failedMeasure = exp.failedToSendLogRecords
211+
}
212+
213+
sentMeasure.Add(ctx, sent, exp.otelAttrs...)
214+
failedMeasure.Add(ctx, failed, exp.otelAttrs...)
215+
}
216+
217+
func (exp *Exporter) recordWithOC(ctx context.Context, dataType config.DataType, sent int64, failed int64) {
218+
var sentMeasure, failedMeasure *stats.Int64Measure
219+
switch dataType {
220+
case config.TracesDataType:
221+
sentMeasure = obsmetrics.ExporterSentSpans
222+
failedMeasure = obsmetrics.ExporterFailedToSendSpans
223+
case config.MetricsDataType:
224+
sentMeasure = obsmetrics.ReceiverAcceptedMetricPoints
225+
failedMeasure = obsmetrics.ExporterFailedToSendMetricPoints
226+
case config.LogsDataType:
227+
sentMeasure = obsmetrics.ReceiverAcceptedLogRecords
228+
failedMeasure = obsmetrics.ExporterFailedToSendLogRecords
115229
}
230+
231+
_ = stats.RecordWithTags(
232+
ctx,
233+
exp.mutators,
234+
sentMeasure.M(sent),
235+
failedMeasure.M(failed))
116236
}
117237

118238
func endSpan(ctx context.Context, err error, numSent, numFailedToSend int64, sentItemsKey, failedToSendItemsKey string) {

0 commit comments

Comments
 (0)