Skip to content

Commit e24d6b5

Browse files
committed
log exporter
1 parent b8aacd1 commit e24d6b5

File tree

9 files changed

+314
-29
lines changed

9 files changed

+314
-29
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
88

99
## [Unreleased]
1010

11+
### Added
12+
13+
- Add logs support and `OTEL_LOGS_EXPORTER` environment variable.
14+
`OTEL_LOGS_EXPORTER` accepts:
15+
`none` - logs disabled,
16+
`otlp` - OTLP gRPC exporter.
17+
Currently `OTEL_LOGS_EXPORTER` defaults to `none`
18+
as OpenTelemetry Go logs API and SDK are not stable yet.
19+
Set `OTEL_LOGS_EXPORTER=otlp` to enable
20+
logs support.
21+
1122
## [1.22.0] - 2024-11-14
1223

1324
This release upgrades [OpenTelemetry Go to v1.32.0/v0.54.0/v0.8.0/v0.0.11][otel-v1.32.0]

distro/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ const (
3535
// OpenTelemetry exporter to use.
3636
otelTracesExporterKey = "OTEL_TRACES_EXPORTER"
3737
otelMetricsExporterKey = "OTEL_METRICS_EXPORTER"
38+
otelLogsExporterKey = "OTEL_LOGS_EXPORTER"
3839

3940
// OpenTelemetry exporter endpoints.
4041
otelExporterJaegerEndpointKey = "OTEL_EXPORTER_JAEGER_ENDPOINT"
4142
otelExporterOTLPEndpointKey = "OTEL_EXPORTER_OTLP_ENDPOINT"
4243
otelExporterOTLPTracesEndpointKey = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"
4344
otelExporterOTLPMetricsEndpointKey = "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT"
45+
otelExporterOTLPLogsEndpointKey = "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT"
4446

4547
// Logging level to set when using the default logger.
4648
otelLogLevelKey = "OTEL_LOG_LEVEL"
@@ -54,6 +56,7 @@ const (
5456
defaultAccessToken = ""
5557
defaultTraceExporter = "otlp"
5658
defaultMetricsExporter = "otlp"
59+
defaultLogsExporter = "none"
5760
defaultLogLevel = "info"
5861

5962
jaegerDefaultEndpoint = "http://127.0.0.1:9080/v1/trace"
@@ -80,6 +83,7 @@ type config struct {
8083
ExportConfig *exporterConfig
8184
TracesExporterFunc traceExporterFunc
8285
MetricsExporterFunc metricsExporterFunc
86+
LogsExporterFunc logsExporterFunc
8387
}
8488

8589
// newConfig returns a validated config with Splunk defaults.
@@ -97,6 +101,7 @@ func newConfig(opts ...Option) *config {
97101
}
98102
c.TracesExporterFunc = tracesExporter(c.Logger)
99103
c.MetricsExporterFunc = metricsExporter(c.Logger)
104+
c.LogsExporterFunc = logsExporter(c.Logger)
100105
return c
101106
}
102107

distro/exporter.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import (
2222

2323
"github.com/go-logr/logr"
2424
"go.opentelemetry.io/otel/exporters/jaeger" //nolint:staticcheck // Jaeger is deprecated, but we still support it to not break existing users.
25+
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
2526
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
2627
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
2728
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
2829
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
30+
"go.opentelemetry.io/otel/sdk/log"
2931
"go.opentelemetry.io/otel/sdk/metric"
3032
"go.opentelemetry.io/otel/sdk/trace"
3133
"google.golang.org/grpc/credentials"
@@ -236,6 +238,51 @@ func newOTLPMetricsExporter(c *exporterConfig) (metric.Exporter, error) {
236238
return otlpmetricgrpc.New(ctx, opts...)
237239
}
238240

241+
type logsExporterFunc func(*exporterConfig) (log.Exporter, error)
242+
243+
// logsExporters maps environment variable values to logs exporter creation
244+
// functions.
245+
var logsExporters = map[string]logsExporterFunc{
246+
// OTLP gRPC exporter.
247+
"otlp": newOTLPlogExporter,
248+
// None, explicitly do not set an exporter.
249+
"none": nil,
250+
}
251+
252+
func logsExporter(log logr.Logger) logsExporterFunc {
253+
key := envOr(otelLogsExporterKey, defaultLogsExporter)
254+
lef, ok := logsExporters[key]
255+
if !ok {
256+
err := fmt.Errorf("invalid %s: %q", otelLogsExporterKey, key)
257+
log.Error(err, "using default %s: %q", otelLogsExporterKey, defaultLogsExporter)
258+
259+
return logsExporters[defaultLogsExporter]
260+
}
261+
return lef
262+
}
263+
264+
func newOTLPlogExporter(c *exporterConfig) (log.Exporter, error) {
265+
ctx := context.Background()
266+
267+
var opts []otlploggrpc.Option
268+
269+
if c.AccessToken != "" {
270+
opts = append(opts, otlploggrpc.WithHeaders(map[string]string{
271+
"X-Sf-Token": c.AccessToken,
272+
}))
273+
}
274+
275+
if c.TLSConfig != nil {
276+
tlsCreds := credentials.NewTLS(c.TLSConfig)
277+
opts = append(opts, otlploggrpc.WithTLSCredentials(tlsCreds))
278+
} else if noneEnvVarSet(otelExporterOTLPEndpointKey, otelExporterOTLPLogsEndpointKey) {
279+
// Assume that the default endpoint (local collector) is non-TLS.
280+
opts = append(opts, otlploggrpc.WithTLSCredentials(insecure.NewCredentials()))
281+
}
282+
283+
return otlploggrpc.New(ctx, opts...)
284+
}
285+
239286
// noneEnvVarSet returns true if none of provided env vars is set.
240287
func noneEnvVarSet(envs ...string) bool {
241288
for _, env := range envs {

distro/go.mod

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@ require (
1111
go.opentelemetry.io/contrib/propagators/autoprop v0.57.0
1212
go.opentelemetry.io/otel v1.32.0
1313
go.opentelemetry.io/otel/exporters/jaeger v1.17.0
14+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0
1415
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0
1516
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0
1617
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0
1718
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0
19+
go.opentelemetry.io/otel/log v0.8.0
1820
go.opentelemetry.io/otel/sdk v1.32.0
21+
go.opentelemetry.io/otel/sdk/log v0.8.0
1922
go.opentelemetry.io/otel/sdk/metric v1.32.0
2023
go.opentelemetry.io/otel/trace v1.32.0
21-
go.opentelemetry.io/proto/otlp v1.3.1
24+
go.opentelemetry.io/proto/otlp v1.4.0
2225
go.uber.org/goleak v1.3.0
2326
go.uber.org/zap v1.27.0
24-
google.golang.org/grpc v1.68.0
27+
google.golang.org/grpc v1.68.1
2528
)
2629

2730
require (
@@ -38,11 +41,11 @@ require (
3841
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect
3942
go.opentelemetry.io/otel/metric v1.32.0 // indirect
4043
go.uber.org/multierr v1.11.0 // indirect
41-
golang.org/x/net v0.31.0 // indirect
42-
golang.org/x/sys v0.27.0 // indirect
43-
golang.org/x/text v0.20.0 // indirect
44-
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
45-
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
44+
golang.org/x/net v0.32.0 // indirect
45+
golang.org/x/sys v0.28.0 // indirect
46+
golang.org/x/text v0.21.0 // indirect
47+
google.golang.org/genproto/googleapis/api v0.0.0-20241206012308-a4fef0638583 // indirect
48+
google.golang.org/genproto/googleapis/rpc v0.0.0-20241206012308-a4fef0638583 // indirect
4649
google.golang.org/protobuf v1.35.2 // indirect
4750
gopkg.in/yaml.v3 v3.0.1 // indirect
4851
)

distro/go.sum

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
4747
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
4848
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
4949
go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI=
50+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls=
51+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs=
52+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8=
53+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50=
5054
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0=
5155
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8=
5256
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU=
@@ -57,34 +61,38 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11
5761
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ=
5862
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 h1:cMyu9O88joYEaI47CnQkxO1XZdpoTF9fEnW2duIddhw=
5963
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0/go.mod h1:6Am3rn7P9TVVeXYG+wtcGE7IE1tsQ+bP3AuWcKt/gOI=
64+
go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk=
65+
go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8=
6066
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
6167
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
6268
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
6369
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
70+
go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs=
71+
go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo=
6472
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
6573
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
6674
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
6775
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
68-
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
69-
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
76+
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
77+
go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
7078
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
7179
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
7280
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
7381
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
7482
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
7583
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
76-
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
77-
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
78-
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
79-
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
80-
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
81-
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
82-
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 h1:pgr/4QbFyktUv9CtQ/Fq4gzEE6/Xs7iCXbktaGzLHbQ=
83-
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697/go.mod h1:+D9ySVjN8nY8YCVjc5O7PZDIdZporIDY3KaGfJunh88=
84-
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA=
85-
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
86-
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
87-
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
84+
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
85+
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
86+
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
87+
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
88+
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
89+
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
90+
google.golang.org/genproto/googleapis/api v0.0.0-20241206012308-a4fef0638583 h1:v+j+5gpj0FopU0KKLDGfDo9ZRRpKdi5UBrCP0f76kuY=
91+
google.golang.org/genproto/googleapis/api v0.0.0-20241206012308-a4fef0638583/go.mod h1:jehYqy3+AhJU9ve55aNOaSml7wUXjF9x6z2LcCfpAhY=
92+
google.golang.org/genproto/googleapis/rpc v0.0.0-20241206012308-a4fef0638583 h1:IfdSdTcLFy4lqUQrQJLkLt1PB+AsqVz6lwkWPzWEz10=
93+
google.golang.org/genproto/googleapis/rpc v0.0.0-20241206012308-a4fef0638583/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
94+
google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
95+
google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
8896
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
8997
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
9098
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

distro/otel.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ import (
2222

2323
"go.opentelemetry.io/contrib/instrumentation/runtime"
2424
"go.opentelemetry.io/otel"
25+
"go.opentelemetry.io/otel/log/global"
2526
"go.opentelemetry.io/otel/attribute"
27+
"go.opentelemetry.io/otel/sdk/log"
2628
"go.opentelemetry.io/otel/sdk/metric"
2729
"go.opentelemetry.io/otel/sdk/resource"
2830
"go.opentelemetry.io/otel/sdk/trace"
@@ -104,6 +106,15 @@ func Run(opts ...Option) (SDK, error) {
104106
sdk.shutdownFuncs = append(sdk.shutdownFuncs, shutdownFn)
105107
}
106108

109+
shutdownFn, err = runLogs(c, res)
110+
if err != nil {
111+
sdk.Shutdown(ctx) //nolint:errcheck // the Shutdown errors are logged
112+
return SDK{}, err
113+
}
114+
if shutdownFn != nil {
115+
sdk.shutdownFuncs = append(sdk.shutdownFuncs, shutdownFn)
116+
}
117+
107118
return sdk, nil
108119
}
109120

@@ -189,6 +200,30 @@ func runMetrics(c *config, res *resource.Resource) (shutdownFunc, error) {
189200
return provider.Shutdown, nil
190201
}
191202

203+
func runLogs(c *config, res *resource.Resource) (shutdownFunc, error) {
204+
if c.LogsExporterFunc == nil {
205+
c.Logger.V(1).Info("OTEL_LOGS_EXPORTER set to none: Logs disabled")
206+
// "none" exporter configured.
207+
return nil, nil
208+
}
209+
210+
exp, err := c.LogsExporterFunc(c.ExportConfig)
211+
if err != nil {
212+
return nil, err
213+
}
214+
215+
o := []log.LoggerProviderOption{
216+
log.WithResource(res),
217+
log.WithProcessor(log.NewBatchProcessor(exp)),
218+
}
219+
220+
provider := log.NewLoggerProvider(o...)
221+
global.SetLoggerProvider(provider)
222+
223+
return provider.Shutdown, nil
224+
}
225+
226+
192227
func serviceNameDefined(r *resource.Resource) bool {
193228
val, ok := r.Set().Value("service.name")
194229
return ok && val.Type() == attribute.STRING && !strings.HasPrefix(val.AsString(), "unknown_service:")

0 commit comments

Comments
 (0)