Skip to content

Commit

Permalink
Switch SpanEvent times to use time.Time
Browse files Browse the repository at this point in the history
Use `time.Time`, a timestamp, to identify the start and end time of the
`SpanEvent` instead of representing them as nanoseconds since boot time
in a built-in `int64`.

This is motivate by the need to support things that report timestamps
for start/end times directly. Things like the custom SDK (see #1045).

To support the conversion for probes, the `utils.BootOffsetToTime`
function is added. This converts between the measured nanoseconds since
boot-time that an eBPF program measures, and a timestamp.
  • Loading branch information
MrAlias committed Sep 12, 2024
1 parent 8f33bc4 commit 3b14c98
Show file tree
Hide file tree
Showing 21 changed files with 140 additions and 87 deletions.
5 changes: 3 additions & 2 deletions internal/pkg/instrumentation/bpf/database/sql/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"go.opentelemetry.io/auto/internal/pkg/instrumentation/context"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
)

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c
Expand Down Expand Up @@ -96,8 +97,8 @@ func convertEvent(e *event) []*probe.SpanEvent {
return []*probe.SpanEvent{
{
SpanName: "DB",
StartTime: int64(e.StartTime),
EndTime: int64(e.EndTime),
StartTime: utils.BootOffsetToTime(e.StartTime),
EndTime: utils.BootOffsetToTime(e.EndTime),
SpanContext: &sc,
Attributes: []attribute.KeyValue{
semconv.DBQueryText(query),
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/instrumentation/bpf/database/sql/probe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ func TestProbeConvertEvent(t *testing.T) {
})
want := &probe.SpanEvent{
SpanName: "DB",
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc,
Attributes: []attribute.KeyValue{
semconv.DBQueryText("SELECT * FROM foo"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"go.opentelemetry.io/auto/internal/pkg/instrumentation/context"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
"go.opentelemetry.io/auto/internal/pkg/structfield"
)

Expand Down Expand Up @@ -122,8 +123,8 @@ func convertEvent(e *event) []*probe.SpanEvent {
return []*probe.SpanEvent{
{
SpanName: kafkaConsumerSpanName(topic),
StartTime: int64(e.StartTime),
EndTime: int64(e.EndTime),
StartTime: utils.BootOffsetToTime(e.StartTime),
EndTime: utils.BootOffsetToTime(e.EndTime),
SpanContext: &sc,
ParentSpanContext: pscPtr,
Attributes: attributes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ func TestProbeConvertEvent(t *testing.T) {
})
want := &probe.SpanEvent{
SpanName: kafkaConsumerSpanName("topic1"),
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc,
Attributes: []attribute.KeyValue{
semconv.MessagingSystemKafka,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"go.opentelemetry.io/auto/internal/pkg/instrumentation/context"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
"go.opentelemetry.io/auto/internal/pkg/structfield"
)

Expand Down Expand Up @@ -138,8 +139,8 @@ func convertEvent(e *event) []*probe.SpanEvent {

res = append(res, &probe.SpanEvent{
SpanName: kafkaProducerSpanName(msgTopic),
StartTime: int64(e.StartTime),
EndTime: int64(e.EndTime),
StartTime: utils.BootOffsetToTime(e.StartTime),
EndTime: utils.BootOffsetToTime(e.EndTime),
SpanContext: &sc,
Attributes: msgAttrs,
ParentSpanContext: pscPtr,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func TestProbeConvertEvent(t *testing.T) {
})
want1 := &probe.SpanEvent{
SpanName: kafkaProducerSpanName("topic1"),
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc1,
Attributes: []attribute.KeyValue{
semconv.MessagingKafkaMessageKey("key1"),
Expand All @@ -78,8 +78,8 @@ func TestProbeConvertEvent(t *testing.T) {

want2 := &probe.SpanEvent{
SpanName: kafkaProducerSpanName("topic2"),
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc2,
Attributes: []attribute.KeyValue{
semconv.MessagingKafkaMessageKey("key2"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"go.opentelemetry.io/auto/internal/pkg/inject"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
"go.opentelemetry.io/auto/internal/pkg/process"
"go.opentelemetry.io/auto/internal/pkg/structfield"

Expand Down Expand Up @@ -207,8 +208,8 @@ func convertEvent(e *event) []*probe.SpanEvent {
return []*probe.SpanEvent{
{
SpanName: spanName,
StartTime: int64(e.StartTime),
EndTime: int64(e.EndTime),
StartTime: utils.BootOffsetToTime(e.StartTime),
EndTime: utils.BootOffsetToTime(e.EndTime),
Attributes: convertAttributes(e.Attributes),
SpanContext: &sc,
ParentSpanContext: pscPtr,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ func TestProbeConvertEvent(t *testing.T) {
})
want := &probe.SpanEvent{
SpanName: "Foo",
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc,
Attributes: []attribute.KeyValue{
attribute.Bool("bool_key", true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ func convertEvent(e *event) []*probe.SpanEvent {

event := &probe.SpanEvent{
SpanName: method,
StartTime: int64(e.StartTime),
EndTime: int64(e.EndTime),
StartTime: utils.BootOffsetToTime(e.StartTime),
EndTime: utils.BootOffsetToTime(e.EndTime),
Attributes: attrs,
SpanContext: &sc,
ParentSpanContext: pscPtr,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"go.opentelemetry.io/auto/internal/pkg/inject"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/context"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
"go.opentelemetry.io/auto/internal/pkg/process"
"go.opentelemetry.io/auto/internal/pkg/structfield"
)
Expand Down Expand Up @@ -127,8 +128,8 @@ func convertEvent(e *event) []*probe.SpanEvent {
return []*probe.SpanEvent{
{
SpanName: method,
StartTime: int64(e.StartTime),
EndTime: int64(e.EndTime),
StartTime: utils.BootOffsetToTime(e.StartTime),
EndTime: utils.BootOffsetToTime(e.EndTime),
Attributes: []attribute.KeyValue{
semconv.RPCSystemKey.String("grpc"),
semconv.RPCServiceKey.String(method),
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/instrumentation/bpf/net/http/client/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ func convertEvent(e *event) []*probe.SpanEvent {

spanEvent := &probe.SpanEvent{
SpanName: method,
StartTime: int64(e.StartTime),
EndTime: int64(e.EndTime),
StartTime: utils.BootOffsetToTime(e.StartTime),
EndTime: utils.BootOffsetToTime(e.EndTime),
SpanContext: &sc,
Attributes: attrs,
ParentSpanContext: pscPtr,
Expand Down
24 changes: 12 additions & 12 deletions internal/pkg/instrumentation/bpf/net/http/client/probe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ func TestConvertEvent(t *testing.T) {
{
SpanName: methodString,
SpanContext: &spanContext,
StartTime: startTime.Unix(),
EndTime: endTime.Unix(),
StartTime: startTime,
EndTime: endTime,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String(methodString),
semconv.HTTPResponseStatusCodeKey.Int(200),
Expand Down Expand Up @@ -129,8 +129,8 @@ func TestConvertEvent(t *testing.T) {
{
SpanName: methodString,
SpanContext: &spanContext,
StartTime: startTime.Unix(),
EndTime: endTime.Unix(),
StartTime: startTime,
EndTime: endTime,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String(methodString),
semconv.HTTPResponseStatusCodeKey.Int(400),
Expand Down Expand Up @@ -163,8 +163,8 @@ func TestConvertEvent(t *testing.T) {
{
SpanName: methodString,
SpanContext: &spanContext,
StartTime: startTime.Unix(),
EndTime: endTime.Unix(),
StartTime: startTime,
EndTime: endTime,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String(methodString),
semconv.HTTPResponseStatusCodeKey.Int(500),
Expand Down Expand Up @@ -197,8 +197,8 @@ func TestConvertEvent(t *testing.T) {
{
SpanName: methodString,
SpanContext: &spanContext,
StartTime: startTime.Unix(),
EndTime: endTime.Unix(),
StartTime: startTime,
EndTime: endTime,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String(methodString),
semconv.HTTPResponseStatusCodeKey.Int(200),
Expand Down Expand Up @@ -234,8 +234,8 @@ func TestConvertEvent(t *testing.T) {
{
SpanName: methodString,
SpanContext: &spanContext,
StartTime: startTime.Unix(),
EndTime: endTime.Unix(),
StartTime: startTime,
EndTime: endTime,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String(methodString),
semconv.HTTPResponseStatusCodeKey.Int(200),
Expand Down Expand Up @@ -271,8 +271,8 @@ func TestConvertEvent(t *testing.T) {
{
SpanName: methodString,
SpanContext: &spanContext,
StartTime: startTime.Unix(),
EndTime: endTime.Unix(),
StartTime: startTime,
EndTime: endTime,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String(methodString),
semconv.HTTPResponseStatusCodeKey.Int(200),
Expand Down
5 changes: 3 additions & 2 deletions internal/pkg/instrumentation/bpf/net/http/server/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"go.opentelemetry.io/auto/internal/pkg/instrumentation/bpf/net/http"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/context"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
"go.opentelemetry.io/auto/internal/pkg/process"
"go.opentelemetry.io/auto/internal/pkg/structfield"
)
Expand Down Expand Up @@ -211,8 +212,8 @@ func convertEvent(e *event) []*probe.SpanEvent {

spanEvent := &probe.SpanEvent{
SpanName: spanName,
StartTime: int64(e.StartTime),
EndTime: int64(e.EndTime),
StartTime: utils.BootOffsetToTime(e.StartTime),
EndTime: utils.BootOffsetToTime(e.EndTime),
SpanContext: &sc,
ParentSpanContext: pscPtr,
Attributes: attributes,
Expand Down
23 changes: 12 additions & 11 deletions internal/pkg/instrumentation/bpf/net/http/server/probe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import (

"go.opentelemetry.io/auto/internal/pkg/instrumentation/context"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/probe"
"go.opentelemetry.io/auto/internal/pkg/instrumentation/utils"
)

func TestProbeConvertEvent(t *testing.T) {
start := time.Now()
start := time.Unix(0, 1)
end := start.Add(1 * time.Second)

traceID := trace.TraceID{1}
Expand Down Expand Up @@ -58,8 +59,8 @@ func TestProbeConvertEvent(t *testing.T) {
expected: []*probe.SpanEvent{
{
SpanName: "GET",
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
Expand Down Expand Up @@ -98,8 +99,8 @@ func TestProbeConvertEvent(t *testing.T) {
expected: []*probe.SpanEvent{
{
SpanName: "GET",
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
Expand Down Expand Up @@ -139,8 +140,8 @@ func TestProbeConvertEvent(t *testing.T) {
expected: []*probe.SpanEvent{
{
SpanName: "GET",
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
Expand All @@ -160,8 +161,8 @@ func TestProbeConvertEvent(t *testing.T) {
name: "server statuscode 500 sets span.Status",
event: &event{
BaseSpanProperties: context.BaseSpanProperties{
StartTime: uint64(start.UnixNano()),
EndTime: uint64(end.UnixNano()),
StartTime: utils.TimeToBootOffset(start),
EndTime: utils.TimeToBootOffset(end),
SpanContext: context.EBPFSpanContext{TraceID: traceID, SpanID: spanID},
},
StatusCode: 500,
Expand All @@ -179,8 +180,8 @@ func TestProbeConvertEvent(t *testing.T) {
expected: []*probe.SpanEvent{
{
SpanName: "GET",
StartTime: int64(start.UnixNano()),
EndTime: int64(end.UnixNano()),
StartTime: start,
EndTime: end,
SpanContext: &sc,
Attributes: []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
Expand Down
6 changes: 4 additions & 2 deletions internal/pkg/instrumentation/probe/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
package probe

import (
"time"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
Expand All @@ -24,8 +26,8 @@ type Status struct {
type SpanEvent struct {
SpanName string
Attributes []attribute.KeyValue
StartTime int64
EndTime int64
StartTime time.Time
EndTime time.Time
SpanContext *trace.SpanContext
ParentSpanContext *trace.SpanContext
Status Status
Expand Down
36 changes: 36 additions & 0 deletions internal/pkg/instrumentation/utils/kernel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package utils

import (
"math"
"time"
)

var bootTimeOffset = func() int64 {
o, err := estimateBootTimeOffset()
if err != nil {
panic(err)
}
return o
}()

// BootOffsetToTime returns the timestamp that is nsec number of nanoseconds
// after the estimated boot time of the process.
func BootOffsetToTime(nsec uint64) time.Time {
if nsec > math.MaxInt64 {
nsec = math.MaxInt64
}
return time.Unix(0, bootTimeOffset+int64(nsec))
}

// TimeToBootOffset returns the number of nanoseconds after the estimated boot
// time of the process that the timestamp represent.
func TimeToBootOffset(timestamp time.Time) uint64 {
nsec := timestamp.UnixNano() - bootTimeOffset
if nsec < 0 {
return 0
}
return uint64(nsec)
}
2 changes: 1 addition & 1 deletion internal/pkg/instrumentation/utils/kernel_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func GetCPUCount() (int, error) {
return 0, err
}

func EstimateBootTimeOffset() (bootTimeOffset int64, err error) {
func estimateBootTimeOffset() (bootTimeOffset int64, err error) {
// The datapath is currently using ktime_get_boot_ns for the pcap timestamp,
// which corresponds to CLOCK_BOOTTIME. To be able to convert the the
// CLOCK_BOOTTIME to CLOCK_REALTIME (i.e. a unix timestamp).
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/instrumentation/utils/kernel_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func GetCPUCount() (int, error) {
return 0, nil
}

func EstimateBootTimeOffset() (bootTimeOffset int64, err error) {
func estimateBootTimeOffset() (bootTimeOffset int64, err error) {
return 0, nil
}
Loading

0 comments on commit 3b14c98

Please sign in to comment.