Skip to content

Commit

Permalink
add stdout exporter support (#8094)
Browse files Browse the repository at this point in the history
Internal metrics can now be additionally configure to export using the
stdout exporter.

Linked issue:
#7641

---------

Signed-off-by: Alex Boten <aboten@lightstep.com>
  • Loading branch information
Alex Boten authored Jul 17, 2023
1 parent cab1779 commit 7996c45
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 2 deletions.
18 changes: 18 additions & 0 deletions .chloggen/codeboten_add-console-exporter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: service

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add support for exporting internal metrics to the console

# One or more tracking issues or pull requests related to the change
issues: [7641]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: |
Internal collector metrics can now be exported to the console
using the otel-go stdout exporter.
1 change: 1 addition & 0 deletions cmd/otelcorecol/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ require (
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/bridge/opencensus v0.39.0 // indirect
go.opentelemetry.io/otel/exporters/prometheus v0.39.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.39.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions cmd/otelcorecol/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,8 @@ go.opentelemetry.io/otel/bridge/opencensus v0.39.0 h1:YHivttTaDhbZIHuPlg1sWsy2P5
go.opentelemetry.io/otel/bridge/opencensus v0.39.0/go.mod h1:vZ4537pNjFDXEx//WldAR6Ro2LC8wwmFC76njAXwNPE=
go.opentelemetry.io/otel/exporters/prometheus v0.39.0 h1:whAaiHxOatgtKd+w0dOi//1KUxj3KoPINZdtDaDj3IA=
go.opentelemetry.io/otel/exporters/prometheus v0.39.0/go.mod h1:4jo5Q4CROlCpSPsXLhymi+LYrDXd2ObU5wbKayfZs7Y=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0 h1:fl2WmyenEf6LYYlfHAtCUEDyGcpwJNqD4dHGO7PVm4w=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0/go.mod h1:csyQxQ0UHHKVA8KApS7eUO/klMO5sd/av5CNZNU4O6w=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ require (
go.opentelemetry.io/otel v1.16.0
go.opentelemetry.io/otel/bridge/opencensus v0.39.0
go.opentelemetry.io/otel/exporters/prometheus v0.39.0
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0
go.opentelemetry.io/otel/metric v1.16.0
go.opentelemetry.io/otel/sdk v1.16.0
go.opentelemetry.io/otel/sdk/metric v0.39.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ go.opentelemetry.io/otel/bridge/opencensus v0.39.0 h1:YHivttTaDhbZIHuPlg1sWsy2P5
go.opentelemetry.io/otel/bridge/opencensus v0.39.0/go.mod h1:vZ4537pNjFDXEx//WldAR6Ro2LC8wwmFC76njAXwNPE=
go.opentelemetry.io/otel/exporters/prometheus v0.39.0 h1:whAaiHxOatgtKd+w0dOi//1KUxj3KoPINZdtDaDj3IA=
go.opentelemetry.io/otel/exporters/prometheus v0.39.0/go.mod h1:4jo5Q4CROlCpSPsXLhymi+LYrDXd2ObU5wbKayfZs7Y=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0 h1:fl2WmyenEf6LYYlfHAtCUEDyGcpwJNqD4dHGO7PVm4w=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.39.0/go.mod h1:csyQxQ0UHHKVA8KApS7eUO/klMO5sd/av5CNZNU4O6w=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
Expand Down
25 changes: 23 additions & 2 deletions service/internal/proctelemetry/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ package proctelemetry // import "go.opentelemetry.io/collector/service/internal/

import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/bridge/opencensus"
otelprom "go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
"go.opentelemetry.io/otel/sdk/instrumentation"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/aggregation"
Expand Down Expand Up @@ -50,7 +53,10 @@ var (

func InitMetricReader(ctx context.Context, reader telemetry.MetricReader, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) {
if reader.Pull != nil {
return initExporter(ctx, reader.Pull.Exporter, asyncErrorChannel)
return initPullExporter(reader.Pull.Exporter, asyncErrorChannel)
}
if reader.Periodic != nil {
return initPeriodicExporter(ctx, reader.Periodic.Exporter)
}
return nil, nil, fmt.Errorf("unsupported metric reader type %v", reader)
}
Expand Down Expand Up @@ -148,9 +154,24 @@ func initPrometheusExporter(prometheusConfig *telemetry.Prometheus, asyncErrorCh
return exporter, InitPrometheusServer(promRegistry, fmt.Sprintf("%s:%d", *prometheusConfig.Host, *prometheusConfig.Port), asyncErrorChannel), nil
}

func initExporter(_ context.Context, exporter telemetry.MetricExporter, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) {
func initPullExporter(exporter telemetry.MetricExporter, asyncErrorChannel chan error) (sdkmetric.Reader, *http.Server, error) {
if exporter.Prometheus != nil {
return initPrometheusExporter(exporter.Prometheus, asyncErrorChannel)
}
return nil, nil, fmt.Errorf("no valid exporter")
}
func initPeriodicExporter(_ context.Context, exporter telemetry.MetricExporter) (sdkmetric.Reader, *http.Server, error) {
if exporter.Console != nil {
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")

exp, err := stdoutmetric.New(
stdoutmetric.WithEncoder(enc),
)
if err != nil {
return nil, nil, err
}
return sdkmetric.NewPeriodicReader(exp), nil, nil
}
return nil, nil, fmt.Errorf("no valid exporter")
}
31 changes: 31 additions & 0 deletions service/internal/proctelemetry/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,37 @@ func TestMetricReader(t *testing.T) {
},
},
},
{
name: "periodic/invalid-exporter",
reader: telemetry.MetricReader{
Periodic: &telemetry.PeriodicMetricReader{
Exporter: telemetry.MetricExporter{
Prometheus: &telemetry.Prometheus{
Host: strPtr("locahost"),
Port: intPtr(8080),
},
},
},
},
err: errors.New("no valid exporter"),
},
{
name: "periodic/no-exporter",
reader: telemetry.MetricReader{
Periodic: &telemetry.PeriodicMetricReader{},
},
err: errors.New("no valid exporter"),
},
{
name: "periodic/console-exporter",
reader: telemetry.MetricReader{
Periodic: &telemetry.PeriodicMetricReader{
Exporter: telemetry.MetricExporter{
Console: telemetry.Console{},
},
},
},
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions service/telemetry/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ func (mr *MetricReader) Unmarshal(conf *confmap.Conf) error {
}
return nil
}
if mr.Periodic != nil {
if mr.Periodic.Exporter.Console == nil {
return fmt.Errorf("invalid exporter configuration")
}
return nil
}

return fmt.Errorf("unsupported metric reader type %s", conf.AllKeys())
}
17 changes: 17 additions & 0 deletions service/telemetry/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,23 @@ func TestUnmarshalMetricReader(t *testing.T) {
},
}}),
},
{
name: "valid periodic reader type, valid console exporter",
cfg: confmap.NewFromStringMap(map[string]any{"periodic": PeriodicMetricReader{
Exporter: MetricExporter{
Console: Console{},
},
}}),
},
{
name: "valid periodic reader type, invalid console exporter",
cfg: confmap.NewFromStringMap(map[string]any{"periodic": PeriodicMetricReader{
Exporter: MetricExporter{
Prometheus: &Prometheus{},
},
}}),
err: "invalid exporter configuration",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down

0 comments on commit 7996c45

Please sign in to comment.