Skip to content
Merged
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
34 changes: 25 additions & 9 deletions interpreter/apmint/apmint.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
package apmint // import "go.opentelemetry.io/ebpf-profiler/interpreter/apmint"

import (
"encoding/hex"
"errors"
"fmt"
"hash/fnv"
"regexp"
"strconv"
"unsafe"

log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -144,31 +145,46 @@ type Instance struct {

var _ interpreter.Instance = &Instance{}

// hashTrace calculates the hash of a trace and returns it.
// Be aware that changes to this calculation will break the ability to
// look backwards for the same TraceHash in our backend.
func hashTrace(trace *libpf.Trace) (hash [16]byte) {
var buf [24]byte
h := fnv.New128a()
for _, uniqueFrame := range trace.Frames {
frame := uniqueFrame.Value()
_, _ = h.Write(frame.FileID.Bytes())
// Using FormatUint() or putting AppendUint() into a function leads
// to escaping to heap (allocation).
_, _ = h.Write(strconv.AppendUint(buf[:0], uint64(frame.AddressOrLineno), 10))
}
h.Sum(hash[:0])
return
}

// Detach implements the interpreter.Instance interface.
func (i *Instance) Detach(ebpf interpreter.EbpfHandler, pid libpf.PID) error {
return ebpf.DeleteProcData(libpf.APMInt, pid)
}

// NotifyAPMAgent sends out collected traces to the connected APM agent.
func (i *Instance) NotifyAPMAgent(
pid libpf.PID, rawTrace *host.Trace, umTraceHash libpf.TraceHash, count uint16) {
func (i *Instance) NotifyAPMAgent(pid libpf.PID, rawTrace *host.Trace, umTrace *libpf.Trace) {
if rawTrace.APMTransactionID == libpf.InvalidAPMSpanID || i.socket == nil {
return
}

log.Debugf("Reporting %dx trace hash %s -> TX %s for PID %d",
count, umTraceHash.StringNoQuotes(),
hex.EncodeToString(rawTrace.APMTransactionID[:]), pid)

msg := traceCorrMsg{
MessageType: 1,
MinorVersion: 1,
APMTraceID: rawTrace.APMTraceID,
APMTransactionID: rawTrace.APMTransactionID,
StackTraceID: umTraceHash,
Count: count,
StackTraceID: hashTrace(umTrace),
Count: 1,
}

log.Debugf("Reporting a trace hash %x -> TX %x for PID %d",
msg.StackTraceID[:], rawTrace.APMTransactionID[:], pid)

if err := i.socket.SendMessage(msg.Serialize()); err != nil {
log.Debugf("Failed to send trace mappings to APM agent: %v", err)
}
Expand Down
18 changes: 11 additions & 7 deletions traceutil/traceutil_test.go → interpreter/apmint/hash_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package traceutil
package apmint // import "go.opentelemetry.io/ebpf-profiler/interpreter/apmint"

import (
"testing"
Expand Down Expand Up @@ -30,19 +30,23 @@ func newPythonTrace() *libpf.Trace {
func TestHashTrace(t *testing.T) {
tests := map[string]struct {
trace *libpf.Trace
result libpf.TraceHash
result [16]byte
}{
"empty trace": {
trace: &libpf.Trace{},
result: libpf.NewTraceHash(0x6c62272e07bb0142, 0x62b821756295c58d)},
trace: &libpf.Trace{},
result: [16]uint8{0x6c, 0x62, 0x27, 0x2e, 0x7, 0xbb, 0x1, 0x42,
0x62, 0xb8, 0x21, 0x75, 0x62, 0x95, 0xc5, 0x8d},
},
"python trace": {
trace: newPythonTrace(),
result: libpf.NewTraceHash(0x21c6fe4c62868856, 0xcf510596eab68dc8)},
trace: newPythonTrace(),
result: [16]byte{0x21, 0xc6, 0xfe, 0x4c, 0x62, 0x86, 0x88, 0x56,
0xcf, 0x51, 0x5, 0x96, 0xea, 0xb6, 0x8d, 0xc8},
},
}

for name, testcase := range tests {
t.Run(name, func(t *testing.T) {
assert.Equal(t, testcase.result, HashTrace(testcase.trace))
assert.Equal(t, testcase.result, hashTrace(testcase.trace))
})
}
}
4 changes: 2 additions & 2 deletions interpreter/apmint/socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ type traceCorrMsg struct {
MinorVersion uint16
APMTraceID libpf.APMTraceID
APMTransactionID libpf.APMTransactionID
StackTraceID libpf.TraceHash
StackTraceID [16]byte
Count uint16
}

Expand All @@ -113,7 +113,7 @@ func (m *traceCorrMsg) Serialize() []byte {
_ = binary.Write(&buf, binary.LittleEndian, m.MinorVersion)
_, _ = buf.Write(m.APMTraceID[:])
_, _ = buf.Write(m.APMTransactionID[:])
_, _ = buf.Write(m.StackTraceID.Bytes())
_, _ = buf.Write(m.StackTraceID[:])
_ = binary.Write(&buf, binary.LittleEndian, m.Count)
return buf.Bytes()
}
Expand Down
1 change: 0 additions & 1 deletion libpf/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ func (frames *Frames) Append(frame *Frame) {
// Trace represents a stack trace.
type Trace struct {
Frames Frames
Hash TraceHash
CustomLabels map[string]string
}

Expand Down
60 changes: 0 additions & 60 deletions libpf/tracehash.go

This file was deleted.

83 changes: 0 additions & 83 deletions libpf/tracehash_test.go

This file was deleted.

7 changes: 2 additions & 5 deletions processmanager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"go.opentelemetry.io/ebpf-profiler/reporter"
"go.opentelemetry.io/ebpf-profiler/times"
"go.opentelemetry.io/ebpf-profiler/tracer/types"
"go.opentelemetry.io/ebpf-profiler/traceutil"
"go.opentelemetry.io/ebpf-profiler/util"
)

Expand Down Expand Up @@ -298,12 +297,10 @@ func (pm *ProcessManager) ConvertTrace(trace *host.Trace) (newTrace *libpf.Trace
}
}
}
newTrace.Hash = traceutil.HashTrace(newTrace)
return newTrace
}

func (pm *ProcessManager) MaybeNotifyAPMAgent(
rawTrace *host.Trace, umTraceHash libpf.TraceHash, count uint16) string {
func (pm *ProcessManager) MaybeNotifyAPMAgent(rawTrace *host.Trace, umTrace *libpf.Trace) string {
pm.mu.RLock()
pidInterp, ok := pm.interpreters[rawTrace.PID]
pm.mu.RUnlock()
Expand All @@ -314,7 +311,7 @@ func (pm *ProcessManager) MaybeNotifyAPMAgent(
var serviceName string
for _, mapping := range pidInterp {
if apm, ok := mapping.(*apmint.Instance); ok {
apm.NotifyAPMAgent(rawTrace.PID, rawTrace, umTraceHash, count)
apm.NotifyAPMAgent(rawTrace.PID, rawTrace, umTrace)

if serviceName != "" {
log.Warnf("Overwriting APM service name from '%s' to '%s' for PID %d",
Expand Down
Loading
Loading