Skip to content

Commit

Permalink
feat: add WithSpan helper
Browse files Browse the repository at this point in the history
  • Loading branch information
alnr authored and aeneasr committed Dec 20, 2022
1 parent 940234f commit 716ad47
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
41 changes: 41 additions & 0 deletions otelx/withspan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright © 2022 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package otelx

import (
"context"

"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)

// WithSpan wraps execution of f in a span identified by name.
//
// If f returns an error or panics, the span status will be set to the error
// state. The error (or panic) will be propagated unmodified.
//
// f will be wrapped in a child span by default. To make a new root span
// instead, pass the trace.WithNewRoot() option.
func WithSpan(ctx context.Context, name string, f func(context.Context) error, opts ...trace.SpanStartOption) (err error) {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer("").Start(ctx, name, opts...)
defer func() {
defer span.End()
if err != nil {
span.SetStatus(codes.Error, err.Error())
} else if r := recover(); r != nil {
switch e := r.(type) {
case error:
span.SetStatus(codes.Error, "panic: "+e.Error())
case interface{ String() string }:
span.SetStatus(codes.Error, "panic: "+e.String())
case string:
span.SetStatus(codes.Error, "panic: "+e)
default:
span.SetStatus(codes.Error, "panic")
}
panic(r)
}
}()
return f(ctx)
}
39 changes: 39 additions & 0 deletions otelx/withspan_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright © 2022 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package otelx

import (
"context"
"errors"
"testing"

"github.com/instana/testify/assert"
"go.opentelemetry.io/otel/trace"
)

func TestWithSpan(t *testing.T) {
tracer := trace.NewNoopTracerProvider().Tracer("test")
ctx, span := tracer.Start(context.Background(), "parent")
defer span.End()

assert.NoError(t, WithSpan(ctx, "no-error", func(ctx context.Context) error { return nil }))
assert.Error(t, WithSpan(ctx, "error", func(ctx context.Context) error { return errors.New("some-error") }))
assert.PanicsWithError(t, errPanic.Error(), func() {
WithSpan(ctx, "panic", func(ctx context.Context) error {
panic(errPanic)
})
})
assert.PanicsWithValue(t, errPanic, func() {
WithSpan(ctx, "panic", func(ctx context.Context) error {
panic(errPanic)
})
})
assert.PanicsWithValue(t, "panic-string", func() {
WithSpan(ctx, "panic", func(ctx context.Context) error {
panic("panic-string")
})
})
}

var errPanic = errors.New("panic-error")

0 comments on commit 716ad47

Please sign in to comment.