diff --git a/vendor/go.opentelemetry.io/auto/sdk/span.go b/vendor/go.opentelemetry.io/auto/sdk/span.go
new file mode 100644
index 0000000..6ebea12
--- /dev/null
+++ b/vendor/go.opentelemetry.io/auto/sdk/span.go
@@ -0,0 +1,432 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+package sdk
+
+import (
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"runtime"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"time"
+	"unicode/utf8"
+
+	"go.opentelemetry.io/otel/attribute"
+	"go.opentelemetry.io/otel/codes"
+	semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
+	"go.opentelemetry.io/otel/trace"
+	"go.opentelemetry.io/otel/trace/noop"
+
+	"go.opentelemetry.io/auto/sdk/internal/telemetry"
+)
+
+type span struct {
+	noop.Span
+
+	spanContext trace.SpanContext
+	sampled     atomic.Bool
+
+	mu     sync.Mutex
+	traces *telemetry.Traces
+	span   *telemetry.Span
+}
+
+func (s *span) SpanContext() trace.SpanContext {
+	if s == nil {
+		return trace.SpanContext{}
+	}
+	// s.spanContext is immutable, do not acquire lock s.mu.
+	return s.spanContext
+}
+
+func (s *span) IsRecording() bool {
+	if s == nil {
+		return false
+	}
+
+	return s.sampled.Load()
+}
+
+func (s *span) SetStatus(c codes.Code, msg string) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	if s.span.Status == nil {
+		s.span.Status = new(telemetry.Status)
+	}
+
+	s.span.Status.Message = msg
+
+	switch c {
+	case codes.Unset:
+		s.span.Status.Code = telemetry.StatusCodeUnset
+	case codes.Error:
+		s.span.Status.Code = telemetry.StatusCodeError
+	case codes.Ok:
+		s.span.Status.Code = telemetry.StatusCodeOK
+	}
+}
+
+func (s *span) SetAttributes(attrs ...attribute.KeyValue) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	limit := maxSpan.Attrs
+	if limit == 0 {
+		// No attributes allowed.
+		s.span.DroppedAttrs += uint32(len(attrs))
+		return
+	}
+
+	m := make(map[string]int)
+	for i, a := range s.span.Attrs {
+		m[a.Key] = i
+	}
+
+	for _, a := range attrs {
+		val := convAttrValue(a.Value)
+		if val.Empty() {
+			s.span.DroppedAttrs++
+			continue
+		}
+
+		if idx, ok := m[string(a.Key)]; ok {
+			s.span.Attrs[idx] = telemetry.Attr{
+				Key:   string(a.Key),
+				Value: val,
+			}
+		} else if limit < 0 || len(s.span.Attrs) < limit {
+			s.span.Attrs = append(s.span.Attrs, telemetry.Attr{
+				Key:   string(a.Key),
+				Value: val,
+			})
+			m[string(a.Key)] = len(s.span.Attrs) - 1
+		} else {
+			s.span.DroppedAttrs++
+		}
+	}
+}
+
+// convCappedAttrs converts up to limit attrs into a []telemetry.Attr. The
+// number of dropped attributes is also returned.
+func convCappedAttrs(limit int, attrs []attribute.KeyValue) ([]telemetry.Attr, uint32) {
+	if limit == 0 {
+		return nil, uint32(len(attrs))
+	}
+
+	if limit < 0 {
+		// Unlimited.
+		return convAttrs(attrs), 0
+	}
+
+	limit = min(len(attrs), limit)
+	return convAttrs(attrs[:limit]), uint32(len(attrs) - limit)
+}
+
+func convAttrs(attrs []attribute.KeyValue) []telemetry.Attr {
+	if len(attrs) == 0 {
+		// Avoid allocations if not necessary.
+		return nil
+	}
+
+	out := make([]telemetry.Attr, 0, len(attrs))
+	for _, attr := range attrs {
+		key := string(attr.Key)
+		val := convAttrValue(attr.Value)
+		if val.Empty() {
+			continue
+		}
+		out = append(out, telemetry.Attr{Key: key, Value: val})
+	}
+	return out
+}
+
+func convAttrValue(value attribute.Value) telemetry.Value {
+	switch value.Type() {
+	case attribute.BOOL:
+		return telemetry.BoolValue(value.AsBool())
+	case attribute.INT64:
+		return telemetry.Int64Value(value.AsInt64())
+	case attribute.FLOAT64:
+		return telemetry.Float64Value(value.AsFloat64())
+	case attribute.STRING:
+		v := truncate(maxSpan.AttrValueLen, value.AsString())
+		return telemetry.StringValue(v)
+	case attribute.BOOLSLICE:
+		slice := value.AsBoolSlice()
+		out := make([]telemetry.Value, 0, len(slice))
+		for _, v := range slice {
+			out = append(out, telemetry.BoolValue(v))
+		}
+		return telemetry.SliceValue(out...)
+	case attribute.INT64SLICE:
+		slice := value.AsInt64Slice()
+		out := make([]telemetry.Value, 0, len(slice))
+		for _, v := range slice {
+			out = append(out, telemetry.Int64Value(v))
+		}
+		return telemetry.SliceValue(out...)
+	case attribute.FLOAT64SLICE:
+		slice := value.AsFloat64Slice()
+		out := make([]telemetry.Value, 0, len(slice))
+		for _, v := range slice {
+			out = append(out, telemetry.Float64Value(v))
+		}
+		return telemetry.SliceValue(out...)
+	case attribute.STRINGSLICE:
+		slice := value.AsStringSlice()
+		out := make([]telemetry.Value, 0, len(slice))
+		for _, v := range slice {
+			v = truncate(maxSpan.AttrValueLen, v)
+			out = append(out, telemetry.StringValue(v))
+		}
+		return telemetry.SliceValue(out...)
+	}
+	return telemetry.Value{}
+}
+
+// truncate returns a truncated version of s such that it contains less than
+// the limit number of characters. Truncation is applied by returning the limit
+// number of valid characters contained in s.
+//
+// If limit is negative, it returns the original string.
+//
+// UTF-8 is supported. When truncating, all invalid characters are dropped
+// before applying truncation.
+//
+// If s already contains less than the limit number of bytes, it is returned
+// unchanged. No invalid characters are removed.
+func truncate(limit int, s string) string {
+	// This prioritize performance in the following order based on the most
+	// common expected use-cases.
+	//
+	//  - Short values less than the default limit (128).
+	//  - Strings with valid encodings that exceed the limit.
+	//  - No limit.
+	//  - Strings with invalid encodings that exceed the limit.
+	if limit < 0 || len(s) <= limit {
+		return s
+	}
+
+	// Optimistically, assume all valid UTF-8.
+	var b strings.Builder
+	count := 0
+	for i, c := range s {
+		if c != utf8.RuneError {
+			count++
+			if count > limit {
+				return s[:i]
+			}
+			continue
+		}
+
+		_, size := utf8.DecodeRuneInString(s[i:])
+		if size == 1 {
+			// Invalid encoding.
+			b.Grow(len(s) - 1)
+			_, _ = b.WriteString(s[:i])
+			s = s[i:]
+			break
+		}
+	}
+
+	// Fast-path, no invalid input.
+	if b.Cap() == 0 {
+		return s
+	}
+
+	// Truncate while validating UTF-8.
+	for i := 0; i < len(s) && count < limit; {
+		c := s[i]
+		if c < utf8.RuneSelf {
+			// Optimization for single byte runes (common case).
+			_ = b.WriteByte(c)
+			i++
+			count++
+			continue
+		}
+
+		_, size := utf8.DecodeRuneInString(s[i:])
+		if size == 1 {
+			// We checked for all 1-byte runes above, this is a RuneError.
+			i++
+			continue
+		}
+
+		_, _ = b.WriteString(s[i : i+size])
+		i += size
+		count++
+	}
+
+	return b.String()
+}
+
+func (s *span) End(opts ...trace.SpanEndOption) {
+	if s == nil || !s.sampled.Swap(false) {
+		return
+	}
+
+	// s.end exists so the lock (s.mu) is not held while s.ended is called.
+	s.ended(s.end(opts))
+}
+
+func (s *span) end(opts []trace.SpanEndOption) []byte {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	cfg := trace.NewSpanEndConfig(opts...)
+	if t := cfg.Timestamp(); !t.IsZero() {
+		s.span.EndTime = cfg.Timestamp()
+	} else {
+		s.span.EndTime = time.Now()
+	}
+
+	b, _ := json.Marshal(s.traces) // TODO: do not ignore this error.
+	return b
+}
+
+// Expected to be implemented in eBPF.
+//
+//go:noinline
+func (*span) ended(buf []byte) { ended(buf) }
+
+// ended is used for testing.
+var ended = func([]byte) {}
+
+func (s *span) RecordError(err error, opts ...trace.EventOption) {
+	if s == nil || err == nil || !s.sampled.Load() {
+		return
+	}
+
+	cfg := trace.NewEventConfig(opts...)
+
+	attrs := cfg.Attributes()
+	attrs = append(attrs,
+		semconv.ExceptionType(typeStr(err)),
+		semconv.ExceptionMessage(err.Error()),
+	)
+	if cfg.StackTrace() {
+		buf := make([]byte, 2048)
+		n := runtime.Stack(buf, false)
+		attrs = append(attrs, semconv.ExceptionStacktrace(string(buf[0:n])))
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	s.addEvent(semconv.ExceptionEventName, cfg.Timestamp(), attrs)
+}
+
+func typeStr(i any) string {
+	t := reflect.TypeOf(i)
+	if t.PkgPath() == "" && t.Name() == "" {
+		// Likely a builtin type.
+		return t.String()
+	}
+	return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
+}
+
+func (s *span) AddEvent(name string, opts ...trace.EventOption) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	cfg := trace.NewEventConfig(opts...)
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	s.addEvent(name, cfg.Timestamp(), cfg.Attributes())
+}
+
+// addEvent adds an event with name and attrs at tStamp to the span. The span
+// lock (s.mu) needs to be held by the caller.
+func (s *span) addEvent(name string, tStamp time.Time, attrs []attribute.KeyValue) {
+	limit := maxSpan.Events
+
+	if limit == 0 {
+		s.span.DroppedEvents++
+		return
+	}
+
+	if limit > 0 && len(s.span.Events) == limit {
+		// Drop head while avoiding allocation of more capacity.
+		copy(s.span.Events[:limit-1], s.span.Events[1:])
+		s.span.Events = s.span.Events[:limit-1]
+		s.span.DroppedEvents++
+	}
+
+	e := &telemetry.SpanEvent{Time: tStamp, Name: name}
+	e.Attrs, e.DroppedAttrs = convCappedAttrs(maxSpan.EventAttrs, attrs)
+
+	s.span.Events = append(s.span.Events, e)
+}
+
+func (s *span) AddLink(link trace.Link) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	l := maxSpan.Links
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	if l == 0 {
+		s.span.DroppedLinks++
+		return
+	}
+
+	if l > 0 && len(s.span.Links) == l {
+		// Drop head while avoiding allocation of more capacity.
+		copy(s.span.Links[:l-1], s.span.Links[1:])
+		s.span.Links = s.span.Links[:l-1]
+		s.span.DroppedLinks++
+	}
+
+	s.span.Links = append(s.span.Links, convLink(link))
+}
+
+func convLinks(links []trace.Link) []*telemetry.SpanLink {
+	out := make([]*telemetry.SpanLink, 0, len(links))
+	for _, link := range links {
+		out = append(out, convLink(link))
+	}
+	return out
+}
+
+func convLink(link trace.Link) *telemetry.SpanLink {
+	l := &telemetry.SpanLink{
+		TraceID:    telemetry.TraceID(link.SpanContext.TraceID()),
+		SpanID:     telemetry.SpanID(link.SpanContext.SpanID()),
+		TraceState: link.SpanContext.TraceState().String(),
+		Flags:      uint32(link.SpanContext.TraceFlags()),
+	}
+	l.Attrs, l.DroppedAttrs = convCappedAttrs(maxSpan.LinkAttrs, link.Attributes)
+
+	return l
+}
+
+func (s *span) SetName(name string) {
+	if s == nil || !s.sampled.Load() {
+		return
+	}
+
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	s.span.Name = name
+}
+
+func (*span) TracerProvider() trace.TracerProvider { return TracerProvider() }
