Skip to content

Commit c214c24

Browse files
committed
feat: Send plugin logs via OTEL
1 parent 14c373f commit c214c24

File tree

4 files changed

+180
-29
lines changed

4 files changed

+180
-29
lines changed

go.mod

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ require (
1818
github.com/spf13/cobra v1.8.1
1919
github.com/stretchr/testify v1.9.0
2020
github.com/thoas/go-funk v0.9.3
21-
go.opentelemetry.io/otel v1.27.0
21+
go.opentelemetry.io/otel v1.28.0
22+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0
2223
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0
2324
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0
2425
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0
25-
go.opentelemetry.io/otel/metric v1.27.0
26-
go.opentelemetry.io/otel/sdk v1.27.0
26+
go.opentelemetry.io/otel/log v0.4.0
27+
go.opentelemetry.io/otel/metric v1.28.0
28+
go.opentelemetry.io/otel/sdk v1.28.0
29+
go.opentelemetry.io/otel/sdk/log v0.4.0
2730
go.opentelemetry.io/otel/sdk/metric v1.27.0
28-
go.opentelemetry.io/otel/trace v1.27.0
31+
go.opentelemetry.io/otel/trace v1.28.0
2932
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
3033
golang.org/x/sync v0.7.0
3134
golang.org/x/text v0.16.0
@@ -42,7 +45,7 @@ require (
4245
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
4346
github.com/davecgh/go-spew v1.1.1 // indirect
4447
github.com/ghodss/yaml v1.0.0 // indirect
45-
github.com/go-logr/logr v1.4.1 // indirect
48+
github.com/go-logr/logr v1.4.2 // indirect
4649
github.com/go-logr/stdr v1.2.2 // indirect
4750
github.com/google/flatbuffers v24.3.25+incompatible // indirect
4851
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
@@ -60,14 +63,14 @@ require (
6063
github.com/spf13/pflag v1.0.5 // indirect
6164
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
6265
github.com/zeebo/xxh3 v1.0.2 // indirect
63-
go.opentelemetry.io/proto/otlp v1.2.0 // indirect
66+
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
6467
golang.org/x/mod v0.18.0 // indirect
6568
golang.org/x/net v0.26.0 // indirect
6669
golang.org/x/sys v0.21.0 // indirect
6770
golang.org/x/tools v0.22.0 // indirect
6871
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
69-
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
70-
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
72+
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
73+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
7174
gopkg.in/yaml.v2 v2.4.0 // indirect
7275
gopkg.in/yaml.v3 v3.0.1 // indirect
7376
)

go.sum

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4Nij
3434
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
3535
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
3636
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
37-
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
38-
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
37+
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
38+
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
3939
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
4040
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
4141
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
@@ -115,24 +115,30 @@ github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
115115
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
116116
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
117117
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
118-
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
119-
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
118+
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
119+
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
120+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0 h1:zBPZAISA9NOc5cE8zydqDiS0itvg/P/0Hn9m72a5gvM=
121+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0/go.mod h1:gcj2fFjEsqpV3fXuzAA+0Ze1p2/4MJ4T7d77AmkvueQ=
120122
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 h1:CIHWikMsN3wO+wq1Tp5VGdVRTcON+DmOJSfDjXypKOc=
121123
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc=
122124
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
123125
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
124126
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s=
125127
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY=
126-
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
127-
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
128-
go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
129-
go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
128+
go.opentelemetry.io/otel/log v0.4.0 h1:/vZ+3Utqh18e8TPjuc3ecg284078KWrR8BRz+PQAj3o=
129+
go.opentelemetry.io/otel/log v0.4.0/go.mod h1:DhGnQvky7pHy82MIRV43iXh3FlKN8UUKftn0KbLOq6I=
130+
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
131+
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
132+
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
133+
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
134+
go.opentelemetry.io/otel/sdk/log v0.4.0 h1:1mMI22L82zLqf6KtkjrRy5BbagOTWdJsqMY/HSqILAA=
135+
go.opentelemetry.io/otel/sdk/log v0.4.0/go.mod h1:AYJ9FVF0hNOgAVzUG/ybg/QttnXhUePWAupmCqtdESo=
130136
go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI=
131137
go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw=
132-
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
133-
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
134-
go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
135-
go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
138+
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
139+
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
140+
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
141+
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
136142
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
137143
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
138144
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
@@ -156,10 +162,10 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm
156162
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
157163
gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ=
158164
gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo=
159-
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
160-
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
161-
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
162-
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
165+
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0=
166+
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw=
167+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
168+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
163169
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
164170
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
165171
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=

serve/opentelemetry.go

Lines changed: 143 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,27 @@ package serve
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
7+
"reflect"
68
"strings"
79
"time"
810

911
"github.com/cloudquery/plugin-sdk/v4/plugin"
1012
"github.com/rs/zerolog"
1113

1214
"go.opentelemetry.io/otel"
15+
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
1316
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
1417
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
1518
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
19+
otellog "go.opentelemetry.io/otel/log"
20+
logglobal "go.opentelemetry.io/otel/log/global"
21+
"go.opentelemetry.io/otel/sdk/log"
1622
"go.opentelemetry.io/otel/sdk/metric"
1723
"go.opentelemetry.io/otel/sdk/resource"
1824
"go.opentelemetry.io/otel/sdk/trace"
19-
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
25+
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
2026
)
2127

2228
// newResource returns a resource describing this application.
@@ -116,9 +122,41 @@ func getMetricReader(ctx context.Context, opts otelConfig) (*metric.PeriodicRead
116122
return reader, nil
117123
}
118124

125+
func getLogsProcessor(ctx context.Context, opts otelConfig) (*log.BatchProcessor, error) {
126+
if opts.endpoint == "" {
127+
return nil, nil
128+
}
129+
130+
logOptions := []otlploghttp.Option{
131+
otlploghttp.WithEndpoint(opts.endpoint),
132+
otlploghttp.WithCompression(otlploghttp.GzipCompression),
133+
}
134+
135+
if opts.insecure {
136+
logOptions = append(logOptions, otlploghttp.WithInsecure())
137+
}
138+
139+
if len(opts.headers) > 0 {
140+
headers := parseOtelHeaders(opts.headers)
141+
logOptions = append(logOptions, otlploghttp.WithHeaders(headers))
142+
}
143+
144+
if opts.urlPath != "" {
145+
logOptions = append(logOptions, otlploghttp.WithURLPath(opts.urlPath))
146+
}
147+
148+
exporter, err := otlploghttp.New(ctx, logOptions...)
149+
if err != nil {
150+
return nil, fmt.Errorf("creating OTLP log exporter: %w", err)
151+
}
152+
153+
processor := log.NewBatchProcessor(exporter)
154+
return processor, nil
155+
}
156+
119157
func setupOtel(ctx context.Context, logger zerolog.Logger, p *plugin.Plugin, otelEndpoint string, otelEndpointInsecure bool, otelEndpointHeaders []string, otelEndpointURLPath string) (shutdown func(), err error) {
120158
if otelEndpoint == "" {
121-
return func() {}, nil
159+
return nil, nil
122160
}
123161
opts := otelConfig{
124162
endpoint: otelEndpoint,
@@ -136,6 +174,11 @@ func setupOtel(ctx context.Context, logger zerolog.Logger, p *plugin.Plugin, ote
136174
return nil, err
137175
}
138176

177+
logsProcessor, err := getLogsProcessor(ctx, opts)
178+
if err != nil {
179+
return nil, err
180+
}
181+
139182
pluginResource := newResource(p)
140183
tp := trace.NewTracerProvider(
141184
trace.WithBatcher(traceExporter),
@@ -146,20 +189,116 @@ func setupOtel(ctx context.Context, logger zerolog.Logger, p *plugin.Plugin, ote
146189
metric.WithReader(metricReader),
147190
metric.WithResource(pluginResource),
148191
)
192+
193+
lp := log.NewLoggerProvider(
194+
log.WithProcessor(logsProcessor),
195+
log.WithResource(newResource(p)),
196+
)
197+
149198
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
150199
logger.Warn().Err(err).Msg("otel error")
151200
}))
152201
otel.SetTracerProvider(tp)
153202
otel.SetMeterProvider(mt)
203+
logglobal.SetLoggerProvider(lp)
154204

155205
shutdown = func() {
156206
if err := tp.Shutdown(context.Background()); err != nil {
157-
logger.Error().Err(err).Msg("failed to shutdown OTLP trace exporter")
207+
logger.Error().Err(err).Msg("failed to shutdown OTLP trace provider")
158208
}
159209
if err := mt.Shutdown(context.Background()); err != nil {
160-
logger.Error().Err(err).Msg("failed to shutdown OTLP metric exporter")
210+
logger.Error().Err(err).Msg("failed to shutdown OTLP metric provider")
211+
}
212+
if err := lp.Shutdown(context.Background()); err != nil {
213+
logger.Error().Err(err).Msg("failed to shutdown OTLP logger provider")
161214
}
162215
}
163216

164217
return shutdown, nil
165218
}
219+
220+
// Similar to https://github.com/AkhigbeEromo/opentelemetry-go-contrib/blob/dedcf91a55a36a5a8589c56f2e43c188eb42f4f2/bridges/otelzerolog/hook.go
221+
// but with `TraceLevel` and attributes support
222+
type otelLoggerHook struct {
223+
otellog.Logger
224+
ctx context.Context
225+
}
226+
227+
func (h *otelLoggerHook) Run(e *zerolog.Event, level zerolog.Level, message string) {
228+
record := otellog.Record{}
229+
record.SetTimestamp(time.Now().UTC())
230+
record.SetSeverity(otellogSeverity(level))
231+
record.SetBody(otellog.StringValue(message))
232+
// See https://github.com/rs/zerolog/issues/493, this is ugly but it works
233+
logData := make(map[string]any)
234+
eventBuffer := fmt.Sprintf("%s}", reflect.ValueOf(e).Elem().FieldByName("buf"))
235+
err := json.Unmarshal([]byte(eventBuffer), &logData)
236+
if err == nil {
237+
recordAttributes := make([]otellog.KeyValue, 0, len(logData))
238+
for k, v := range logData {
239+
if k == "level" {
240+
continue
241+
}
242+
if k == "time" {
243+
eventTimestamp, ok := v.(string)
244+
if !ok {
245+
continue
246+
}
247+
t, err := time.Parse(time.RFC3339Nano, eventTimestamp)
248+
if err == nil {
249+
record.SetTimestamp(t)
250+
continue
251+
}
252+
}
253+
var attributeValue otellog.Value
254+
switch v := v.(type) {
255+
case string:
256+
attributeValue = otellog.StringValue(v)
257+
case int:
258+
attributeValue = otellog.IntValue(v)
259+
case int64:
260+
attributeValue = otellog.Int64Value(v)
261+
case float64:
262+
attributeValue = otellog.Float64Value(v)
263+
case bool:
264+
attributeValue = otellog.BoolValue(v)
265+
case []byte:
266+
attributeValue = otellog.BytesValue(v)
267+
default:
268+
attributeValue = otellog.StringValue(fmt.Sprintf("%v", v))
269+
}
270+
recordAttributes = append(recordAttributes, otellog.KeyValue{
271+
Key: k,
272+
Value: attributeValue,
273+
})
274+
}
275+
record.AddAttributes(recordAttributes...)
276+
}
277+
278+
h.Emit(h.ctx, record)
279+
}
280+
281+
func otellogSeverity(level zerolog.Level) otellog.Severity {
282+
switch level {
283+
case zerolog.DebugLevel:
284+
return otellog.SeverityDebug
285+
case zerolog.InfoLevel:
286+
return otellog.SeverityInfo
287+
case zerolog.WarnLevel:
288+
return otellog.SeverityWarn
289+
case zerolog.ErrorLevel:
290+
return otellog.SeverityError
291+
case zerolog.FatalLevel:
292+
return otellog.SeverityFatal2
293+
case zerolog.PanicLevel:
294+
return otellog.SeverityFatal1
295+
case zerolog.TraceLevel:
296+
return otellog.SeverityTrace
297+
default:
298+
return otellog.SeverityUndefined
299+
}
300+
}
301+
302+
func newOTELLoggerHook() zerolog.Hook {
303+
return &otelLoggerHook{logglobal.GetLoggerProvider().Logger("cloudquery"), context.Background()}
304+
}

serve/plugin.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,10 @@ func (s *PluginServe) newCmdPluginServe() *cobra.Command {
140140
if err != nil {
141141
return fmt.Errorf("failed to setup OpenTelemetry: %w", err)
142142
}
143-
defer shutdown()
143+
if shutdown != nil {
144+
logger = logger.Hook(newOTELLoggerHook())
145+
defer shutdown()
146+
}
144147

145148
if licenseFile != "" {
146149
switch err := premium.ValidateLicense(logger, s.plugin.Meta(), licenseFile); err {

0 commit comments

Comments
 (0)