Skip to content

Commit

Permalink
Merge pull request #234 from klihub/fixes/otel-tracing
Browse files Browse the repository at this point in the history
instrumentation: allow proper reconfiguration of tracing.
  • Loading branch information
fmuyassarov authored Jan 16, 2024
2 parents bec36f7 + b1696f2 commit 30863c5
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 94 deletions.
8 changes: 7 additions & 1 deletion pkg/instrumentation/instrumentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ func Restart() error {
defer lock.Unlock()

stop()
return start()

err := start()
if err != nil {
log.Error("failed to start tracing: %v", err)
}

return err
}

// Reconfigure our instrumentation services.
Expand Down
122 changes: 122 additions & 0 deletions pkg/instrumentation/tracing/exporter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright The NRI Plugins Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tracing

import (
"context"
"fmt"
"net/url"
"sync"

"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

var (
_ sdktrace.SpanExporter = (*spanExporter)(nil)
)

type spanExporter struct {
sync.RWMutex
exporter sdktrace.SpanExporter
}

func (e *spanExporter) ExportSpans(ctx context.Context, spans []sdktrace.ReadOnlySpan) error {
e.RLock()
defer e.RUnlock()

if e.exporter == nil {
return nil
}
return e.exporter.ExportSpans(ctx, spans)
}

func (e *spanExporter) Shutdown(ctx context.Context) error {
e.Lock()
defer e.Unlock()

if e.exporter == nil {
return nil
}

err := e.exporter.Shutdown(ctx)
e.exporter = nil

return err
}

func (e *spanExporter) setEndpoint(endpoint string) error {
e.shutdown()

if endpoint == "" {
return nil
}

e.Lock()
defer e.Unlock()

var (
u *url.URL
exp sdktrace.SpanExporter
err error
)

// Notes:
// We allow collector endpoint URLs to be given as a plain scheme-prefix,
// IOW, without a host, port, and path. If only a prefix is given, the
// exporters use defaults defined by the OTLP library. These are:
// - otlp-http, http: localhost:4318
// - otlp-grpc, grpc: localhost:4317
//

switch endpoint {
case "otlp-http", "http", "otlp-grpc", "grpc":
u = &url.URL{Scheme: endpoint}
default:
u, err = url.Parse(endpoint)
if err != nil {
return fmt.Errorf("invalid tracing endpoint %q: %w", endpoint, err)
}
}

switch u.Scheme {
case "otlp-http", "http":
opts := []otlptracehttp.Option{otlptracehttp.WithInsecure()}
if u.Host != "" {
opts = append(opts, otlptracehttp.WithEndpoint(u.Host))
}
exp, err = otlptracehttp.New(context.Background(), opts...)
e.exporter = exp
return err
case "otlp-grpc", "grpc":
opts := []otlptracegrpc.Option{otlptracegrpc.WithInsecure()}
if u.Host != "" {
opts = append(opts, otlptracegrpc.WithEndpoint(u.Host))
}
exp, err = otlptracegrpc.New(context.Background(), opts...)
e.exporter = exp
return err
}

return fmt.Errorf("unsupported tracing endpoint %q", endpoint)
}

func (e *spanExporter) shutdown() error {
ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
defer cancel()

return e.Shutdown(ctx)
}
65 changes: 65 additions & 0 deletions pkg/instrumentation/tracing/sampler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright The NRI Plugins Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tracing

import (
"sync"

sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/trace"
)

var (
drop = sdktrace.SamplingResult{
Decision: sdktrace.Drop,
Tracestate: trace.TraceState{},
}

_ sdktrace.Sampler = (*sampler)(nil)
)

type sampler struct {
sync.RWMutex
sampler sdktrace.Sampler
}

func (s *sampler) ShouldSample(p sdktrace.SamplingParameters) sdktrace.SamplingResult {
s.RLock()
defer s.RUnlock()

if s.sampler == nil {
return drop
}

return s.sampler.ShouldSample(p)
}

func (s *sampler) Description() string {
s.RLock()
defer s.RUnlock()

if s.sampler == nil {
return ""
}

return s.sampler.Description()
}

func (s *sampler) setSampler(sampler sdktrace.Sampler) {
s.Lock()
defer s.Unlock()

s.sampler = sampler
}
Loading

0 comments on commit 30863c5

Please sign in to comment.