Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose OpenTelemetryController as interface option to Instrumentation #1025

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions instrumentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"

"go.opentelemetry.io/auto/config"
"go.opentelemetry.io/auto/internal/pkg/instrumentation"

Check failure on line 32 in instrumentation.go

View workflow job for this annotation

GitHub Actions / lint

could not import go.opentelemetry.io/auto/internal/pkg/instrumentation (-: # go.opentelemetry.io/auto/internal/pkg/instrumentation
"go.opentelemetry.io/auto/internal/pkg/opentelemetry"
"go.opentelemetry.io/auto/internal/pkg/process"
otelauto "go.opentelemetry.io/auto/pkg/opentelemetry"
)

const (
Expand Down Expand Up @@ -126,9 +127,12 @@
return nil, err
}

ctrl, err := opentelemetry.NewController(logger, c.tracerProvider(pa.BuildInfo), Version())
if err != nil {
return nil, err
ctrl := c.otelController
if ctrl == nil {
ctrl, err = opentelemetry.NewController(logger, c.tracerProvider(pa.BuildInfo), Version())

Check failure on line 132 in instrumentation.go

View workflow job for this annotation

GitHub Actions / lint

cannot use opentelemetry.NewController(logger, c.tracerProvider(pa.BuildInfo), Version()) (value of type *"go.opentelemetry.io/auto/internal/pkg/opentelemetry".ControllerImpl) as "go.opentelemetry.io/auto/pkg/opentelemetry".Controller value in assignment: *"go.opentelemetry.io/auto/internal/pkg/opentelemetry".ControllerImpl does not implement "go.opentelemetry.io/auto/pkg/opentelemetry".Controller (wrong type for method Trace)
if err != nil {
return nil, err
}
}

mngr, err := instrumentation.NewManager(logger, ctrl, c.globalImpl, c.loadIndicator, c.cp)
Expand Down Expand Up @@ -223,6 +227,7 @@
loadIndicator chan struct{}
logLevel LogLevel
cp config.Provider
otelController otelauto.Controller
}

func newInstConfig(ctx context.Context, opts []InstrumentationOption) (instConfig, error) {
Expand Down Expand Up @@ -337,6 +342,15 @@

func (o fnOpt) apply(ctx context.Context, c instConfig) (instConfig, error) { return o(ctx, c) }

// WithOpenTelemetryController returns an [InstrumentationOption] defining the
// OpenTelemetryController used by [Instrumentation].
func WithOpenTelemetryController(ctrl otelauto.Controller) InstrumentationOption {
return fnOpt(func(_ context.Context, c instConfig) (instConfig, error) {
c.otelController = ctrl
return c, nil
})
}

// WithTarget returns an [InstrumentationOption] defining the target binary for
// [Instrumentation] that is being executed at the provided path.
//
Expand Down
6 changes: 3 additions & 3 deletions internal/pkg/instrumentation/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
httpServer "go.opentelemetry.io/auto/internal/pkg/instrumentation/bpf/net/http/server"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/bpffs"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/opentelemetry"
"go.opentelemetry.io/auto/internal/pkg/process"
otelauto "go.opentelemetry.io/auto/pkg/opentelemetry"
)

// Function variables overridden in testing.
Expand All @@ -49,7 +49,7 @@
type Manager struct {
logger logr.Logger
probes map[probe.ID]probe.Probe
otelController *opentelemetry.Controller
otelController otelauto.Controller
globalImpl bool
loadedIndicator chan struct{}
cp config.Provider
Expand All @@ -63,7 +63,7 @@
}

// NewManager returns a new [Manager].
func NewManager(logger logr.Logger, otelController *opentelemetry.Controller, globalImpl bool, loadIndicator chan struct{}, cp config.Provider) (*Manager, error) {
func NewManager(logger logr.Logger, otelController otelauto.Controller, globalImpl bool, loadIndicator chan struct{}, cp config.Provider) (*Manager, error) {
logger = logger.WithName("Manager")
m := &Manager{
logger: logger,
Expand Down Expand Up @@ -294,7 +294,7 @@
m.probeMu.Unlock()
return errors.Join(err, ctx.Err())
case e := <-m.eventCh:
m.otelController.Trace(e)

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / generate-and-test-arm64

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / compatibility-test (~1.21.9, ubuntu-latest, amd64)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / compatibility-test (~1.22.2, ubuntu-latest, amd64)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / lint

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace) (typecheck)

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / lint

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (5.10)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (5.10)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (5.4)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (5.4)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (5.15)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (5.15)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / generate-and-test-x86_64

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (6.6)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (6.6)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (stable)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace

Check failure on line 297 in internal/pkg/instrumentation/manager.go

View workflow job for this annotation

GitHub Actions / Run tests (stable)

cannot use e (variable of type *"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe".Event) as *"go.opentelemetry.io/auto/pkg/probe".Event value in argument to m.otelController.Trace
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions internal/pkg/instrumentation/probe/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,42 @@ import (

// Event is a telemetry event that happens within an instrumented package.
type Event struct {
// Package is the name of the instrumented package.
Package string
// Kind is the trace.SpanKind for the event.
Kind trace.SpanKind
// SpanEvents is a list of spans for this event.
SpanEvents []*SpanEvent
}

// Status represents the OpenTelemetry status code and description for a span.
type Status struct {
// Code is the OpenTelemetry status code for a span.
Code codes.Code
// Description is the string for this status.
Description string
}

// SpanEvent represents a probed span.
type SpanEvent struct {
// SpanName is the name of the span.
SpanName string
// Attributes is a list of OpenTelemetry attributes for the span.
Attributes []attribute.KeyValue
// StartTime is the start time for the span.
StartTime int64
// EndTime is the end time for the span.
EndTime int64
// SpanContext is the context for this span.
SpanContext *trace.SpanContext
// ParentSpanContext is the context for this span's parent (if applicable).
ParentSpanContext *trace.SpanContext
// Status is the status of this span.
Status Status
// TracerName is the name of the tracer associated with this span.
TracerName string
// TracerVersion is the version of the tracer associated with this span.
TracerVersion string
// TracerSchema is the schema for the tracer associated with this span.
TracerSchema string
}
18 changes: 9 additions & 9 deletions internal/pkg/opentelemetry/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
)

// Controller handles OpenTelemetry telemetry generation for events.
type Controller struct {
// ControllerImpl handles OpenTelemetry telemetry generation for events.
type ControllerImpl struct {
logger logr.Logger
version string
tracerProvider trace.TracerProvider
Expand All @@ -25,7 +25,7 @@ type Controller struct {

type tracerID struct{ name, version, schema string }

func (c *Controller) getTracer(pkg, tracerName, version, schema string) trace.Tracer {
func (c *ControllerImpl) getTracer(pkg, tracerName, version, schema string) trace.Tracer {
// Default Tracer ID, if the user does not provide one.
tID := tracerID{name: pkg, version: c.version}
if tracerName != "" {
Expand Down Expand Up @@ -54,7 +54,7 @@ func (c *Controller) getTracer(pkg, tracerName, version, schema string) trace.Tr
}

// Trace creates a trace span for event.
func (c *Controller) Trace(event *probe.Event) {
func (c *ControllerImpl) Trace(event *probe.Event) {
for _, se := range event.SpanEvents {
c.logger.V(1).Info("got event", "kind", event.Kind.String(), "pkg", event.Package, "attrs", se.Attributes, "traceID", se.SpanContext.TraceID().String(), "spanID", se.SpanContext.SpanID().String())
ctx := context.Background()
Expand All @@ -81,20 +81,20 @@ func (c *Controller) Trace(event *probe.Event) {
}
}

func (c *Controller) convertTime(t int64) time.Time {
func (c *ControllerImpl) convertTime(t int64) time.Time {
return time.Unix(0, c.bootTime+t)
}

// NewController returns a new initialized [Controller].
func NewController(logger logr.Logger, tracerProvider trace.TracerProvider, ver string) (*Controller, error) {
// NewController returns a new initialized [ControllerImpl].
func NewController(logger logr.Logger, tracerProvider trace.TracerProvider, ver string) (*ControllerImpl, error) {
logger = logger.WithName("Controller")

bt, err := utils.EstimateBootTimeOffset()
if err != nil {
return nil, err
}

return &Controller{
return &ControllerImpl{
logger: logger,
version: ver,
tracerProvider: tracerProvider,
Expand All @@ -106,7 +106,7 @@ func NewController(logger logr.Logger, tracerProvider trace.TracerProvider, ver
// Shutdown shuts down the OpenTelemetry TracerProvider.
//
// Once shut down, calls to Trace will result in no-op spans (i.e. dropped).
func (c *Controller) Shutdown(ctx context.Context) error {
func (c *ControllerImpl) Shutdown(ctx context.Context) error {
if s, ok := c.tracerProvider.(interface {
Shutdown(context.Context) error
}); ok {
Expand Down
21 changes: 21 additions & 0 deletions pkg/opentelemetry/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package opentelemetry

import (
"context"

"go.opentelemetry.io/auto/pkg/probe"
)

// Controller is a controller that converts probe Events to
// OpenTelemetry spans and exports them.
type Controller interface {
// Trace receives a probe.Event and handles conversion to OpenTelemetry
// format and exporting.
Trace(event *probe.Event)

// Shutdown shuts down the OpenTelemetry TracerProvider.
Shutdown(ctx context.Context) error
}
105 changes: 105 additions & 0 deletions pkg/probe/probe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package probe

import (
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)

// Event represents an event from eBPF auto-instrumentation.
type Event struct {
event *probe.Event
}

// Status represents a Span status.
type Status struct {
status *probe.Status
}

// ProbedSpan represents a span as returned from an eBPF event.
type ProbedSpan struct {
span *probe.SpanEvent
}

// GetPackage returns the name of the instrumented package.
func (e *Event) GetPackage() string {
return e.event.Package
}

// GetSpanKind returns the trace.SpanKind for the event.
func (e *Event) GetSpanKind() trace.SpanKind {
return e.event.Kind
}

// GetProbedSpans returns the spans for the event.
func (e *Event) GetProbedSpans() []*ProbedSpan {
spans := make([]*ProbedSpan, len(e.event.SpanEvents))
for _, probedSpan := range e.event.SpanEvents {
spans = append(spans, &ProbedSpan{span: probedSpan})
}
return spans
}

// GetSpanName returns the name of the span.
func (s *ProbedSpan) GetSpanName() string {
return s.span.SpanName
}

// GetAttributes returns the list of OpenTelemetry attributes for the span.
func (s *ProbedSpan) GetAttributes() []attribute.KeyValue {
return s.span.Attributes
}

// GetInstrumentedStartTime returns the start time of the span as instrumented by the probe.
func (s *ProbedSpan) GetInstrumentedStartTime() int64 {
return s.span.StartTime
}

// GetInstrumentedEndTime returns the end time of the span as instrumented by the probe.
func (s *ProbedSpan) GetInstrumentedEndTime() int64 {
return s.span.EndTime
}

// GetSpanContext returns the trace.SpanContext for the span.
func (s *ProbedSpan) GetSpanContext() *trace.SpanContext {
return s.span.SpanContext
}

// GetParentSpanContext returns the trace.SpanContext for the parent span (if any).
func (s *ProbedSpan) GetParentSpanContext() *trace.SpanContext {
return s.span.ParentSpanContext
}

// GetStatus returns the Status of the span.
func (s *ProbedSpan) GetStatus() Status {
return Status{status: &s.span.Status}
}

// GetTracerName returns the name of the tracer associated with this span.
func (s *ProbedSpan) GetTracerName() string {
return s.span.TracerName
}

// GetTracerVersion returns the version of the tracer associated with this span.
func (s *ProbedSpan) GetTracerVersion() string {
return s.span.TracerVersion
}

// GetTracerSchema returns the schema for the tracer associated with this span.
func (s *ProbedSpan) GetTracerSchema() string {
return s.span.TracerSchema
}

// GetCode returns the OpenTelemetry status code for a span.
func (s Status) GetCode() codes.Code {
return s.status.Code
}

// GetDescription returns the string for this status.
func (s Status) GetDescription() string {
return s.status.Description
}
Loading