Skip to content

Commit

Permalink
Sync from upstream (2024-12-03) (#5)
Browse files Browse the repository at this point in the history
* Fix unwinding at syscall on aarch64 (open-telemetry#218)

* Add PID as an attribute in each sample (open-telemetry#212)

* ebpf: increase number of stack delta buckets (open-telemetry#231)

Signed-off-by: Florian Lehner <florian.lehner@elastic.co>

* reporter: use htlhash attribute for profiling specific hash (open-telemetry#236)

Signed-off-by: Florian Lehner <florian.lehner@elastic.co>

* reporter: drop fifo (open-telemetry#239)

Signed-off-by: Florian Lehner <florian.lehner@elastic.co>

* Drop more unused code (open-telemetry#240)

* reporter: do not add empty attributes (open-telemetry#233)

Signed-off-by: Florian Lehner <florian.lehner@elastic.co>

* controller: fix reporter interval mix up with monitor interval (open-telemetry#242)

* Extract reporter runloop (open-telemetry#228)

Co-authored-by: Christos Kalkanis <christos.kalkanis@elastic.co>

* Extract lookupcgroupv2 out of the otlp reporter (open-telemetry#227)

* Add CPU id to trace and trace metadata (open-telemetry#249)

* reporter: don't expire actively used executables (open-telemetry#247)

* Remove legacy code from libpf.UnixTime64 (open-telemetry#252)

* Turn kernel module file parsing errors into warnings (open-telemetry#255)

Co-authored-by: Florian Lehner <florianl@users.noreply.github.com>

* readatbuf: add missing check when reading from tail chunk (open-telemetry#259)

* metrics: Don't send counters with 0 values (open-telemetry#246)

---------

Signed-off-by: Florian Lehner <florian.lehner@elastic.co>
Co-authored-by: umanwizard <brennan@umanwizard.com>
Co-authored-by: Bhavna Jindal <bhavna.jindal@yahoo.com>
Co-authored-by: Florian Lehner <florianl@users.noreply.github.com>
Co-authored-by: Tim Rühsen <tim.ruhsen@elastic.co>
Co-authored-by: Nayef Ghattas <nayef.ghattas@datadoghq.com>
Co-authored-by: Damien Mathieu <42@dmathieu.com>
Co-authored-by: Christos Kalkanis <christos.kalkanis@elastic.co>
Co-authored-by: Tommy Reilly <gnurizen@gmail.com>
Co-authored-by: Joel Höner <joel@elastic.co>
  • Loading branch information
10 people authored Dec 4, 2024
1 parent 0aeda32 commit 0d27b95
Show file tree
Hide file tree
Showing 39 changed files with 362 additions and 632 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ devfiler spins up a local server that listens on `0.0.0.0:11000`.

To run it, simply download and unpack the archive from the following URL:

https://upload.elastic.co/d/87e7697991940ec37f0c6e39ac38d213f65e8dc1ef9dbedff6aab9cba0adfaba
https://upload.elastic.co/d/f8aa0c386baa808a616ca29f86b34c726edb5af36f8840a4cf28468ad534a4b5

Authentication token: `c74dfc4db2212015`
Authentication token: `2635c0750bf8ea69`


The archive contains a build for each of the following platforms:
Expand Down
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ module go.opentelemetry.io/ebpf-profiler
go 1.22.2

require (
github.com/aws/aws-sdk-go-v2 v1.30.5
github.com/aws/aws-sdk-go-v2/config v1.27.35
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.21
github.com/aws/aws-sdk-go-v2/service/s3 v1.62.0
github.com/cespare/xxhash/v2 v2.3.0
github.com/cilium/ebpf v0.16.0
github.com/elastic/go-freelru v0.15.0
github.com/elastic/go-freelru v0.16.0
github.com/elastic/go-perf v0.0.0-20241016160959-1342461adb4a
github.com/google/uuid v1.6.0
github.com/jsimonetti/rtnetlink v1.4.2
Expand All @@ -29,7 +29,6 @@ require (
)

require (
github.com/aws/aws-sdk-go-v2 v1.30.5 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.33 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 // indirect
Expand Down
8 changes: 2 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.33 h1:lBHAQQznENv0gLHAZ73ONiTSkCt
github.com/aws/aws-sdk-go-v2/credentials v1.17.33/go.mod h1:MBuqCUOT3ChfLuxNDGyra67eskx7ge9e3YKYBce7wpI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 h1:pfQ2sqNpMVK6xz2RbqLEL0GH87JOwSxPV2rzm8Zsb74=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13/go.mod h1:NG7RXPUlqfsCLLFfi0+IpKN4sCB9D9fw/qTaSB+xRoU=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.21 h1:sV0doPPsRT7gMP0BnDPwSsysVTV/nKpB/nFmMnz8goE=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.21/go.mod h1:ictvfJWqE2gkUFDRJVp5VU/TrytuzK88DYcpan7UYuA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc=
Expand Down Expand Up @@ -43,10 +41,8 @@ github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEn
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elastic/go-freelru v0.13.0 h1:TKKY6yCfNNNky7Pj9xZAOEpBcdNgZJfihEftOb55omg=
github.com/elastic/go-freelru v0.13.0/go.mod h1:bSdWT4M0lW79K8QbX6XY2heQYSCqD7THoYf82pT/H3I=
github.com/elastic/go-freelru v0.15.0 h1:Jo1aY8JAvpyxbTDJEudrsBfjFDaALpfVv8mxuh9sfvI=
github.com/elastic/go-freelru v0.15.0/go.mod h1:bSdWT4M0lW79K8QbX6XY2heQYSCqD7THoYf82pT/H3I=
github.com/elastic/go-freelru v0.16.0 h1:gG2HJ1WXN2tNl5/p40JS/l59HjvjRhjyAa+oFTRArYs=
github.com/elastic/go-freelru v0.16.0/go.mod h1:bSdWT4M0lW79K8QbX6XY2heQYSCqD7THoYf82pT/H3I=
github.com/elastic/go-perf v0.0.0-20241016160959-1342461adb4a h1:ymmtaN4bVCmKKeu4XEf6JEWNZKRXPMng1zjpKd+8rCU=
github.com/elastic/go-perf v0.0.0-20241016160959-1342461adb4a/go.mod h1:Nt+pnRYvf0POC+7pXsrv8ubsEOSsaipJP0zlz1Ms1RM=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
Expand Down
1 change: 1 addition & 0 deletions host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ type Trace struct {
TID libpf.PID
APMTraceID libpf.APMTraceID
APMTransactionID libpf.APMTransactionID
CPU int
}
4 changes: 2 additions & 2 deletions internal/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func (c *Controller) Start(ctx context.Context) error {
traceHandlerCacheSize :=
traceCacheSize(c.config.MonitorInterval, c.config.SamplesPerSecond, uint16(presentCores))

intervals := times.New(c.config.MonitorInterval,
c.config.ReporterInterval, c.config.ProbabilisticInterval)
intervals := times.New(c.config.ReporterInterval, c.config.MonitorInterval,
c.config.ProbabilisticInterval)

// Start periodic synchronization with the realtime clock
times.StartRealtimeSync(ctx, c.config.ClockSyncInterval)
Expand Down
59 changes: 59 additions & 0 deletions libpf/cgroupv2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package libpf // import "go.opentelemetry.io/ebpf-profiler/libpf"

import (
"bufio"
"fmt"
"os"
"regexp"

lru "github.com/elastic/go-freelru"
log "github.com/sirupsen/logrus"
)

var (
cgroupv2PathPattern = regexp.MustCompile(`0:.*?:(.*)`)
)

// LookupCgroupv2 returns the cgroupv2 ID for pid.
func LookupCgroupv2(cgrouplru *lru.SyncedLRU[PID, string], pid PID) (string, error) {
id, ok := cgrouplru.Get(pid)
if ok {
return id, nil
}

// Slow path
f, err := os.Open(fmt.Sprintf("/proc/%d/cgroup", pid))
if err != nil {
return "", err
}
defer f.Close()

var genericCgroupv2 string
scanner := bufio.NewScanner(f)
buf := make([]byte, 512)
// Providing a predefined buffer overrides the internal buffer that Scanner uses (4096 bytes).
// We can do that and also set a maximum allocation size on the following call.
// With a maximum of 4096 characters path in the kernel, 8192 should be fine here. We don't
// expect lines in /proc/<PID>/cgroup to be longer than that.
scanner.Buffer(buf, 8192)
var pathParts []string
for scanner.Scan() {
line := scanner.Text()
pathParts = cgroupv2PathPattern.FindStringSubmatch(line)
if pathParts == nil {
log.Debugf("Could not extract cgroupv2 path from line: %s", line)
continue
}
genericCgroupv2 = pathParts[1]
break
}

// Cache the cgroupv2 information.
// To avoid busy lookups, also empty cgroupv2 information is cached.
cgrouplru.Add(pid, genericCgroupv2)

return genericCgroupv2, nil
}
20 changes: 0 additions & 20 deletions libpf/convenience.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,14 @@ package libpf // import "go.opentelemetry.io/ebpf-profiler/libpf"

import (
"context"
"fmt"
"math/rand/v2"
"os"
"reflect"
"time"
"unsafe"

log "github.com/sirupsen/logrus"
)

// WriteTempFile writes a data buffer to a temporary file on the filesystem. It
// is the callers responsibility to clean up that file again. The function returns
// the filename if successful.
func WriteTempFile(data []byte, directory, prefix string) (string, error) {
file, err := os.CreateTemp(directory, prefix)
if err != nil {
return "", err
}
defer file.Close()
if _, err := file.Write(data); err != nil {
return "", fmt.Errorf("failed to write data to temporary file: %w", err)
}
if err := file.Sync(); err != nil {
return "", fmt.Errorf("failed to synchronize file data: %w", err)
}
return file.Name(), nil
}

// SleepWithJitter sleeps for baseDuration +/- jitter (jitter is [0..1])
func SleepWithJitter(baseDuration time.Duration, jitter float64) {
time.Sleep(AddJitter(baseDuration, jitter))
Expand Down
31 changes: 1 addition & 30 deletions libpf/libpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ package libpf // import "go.opentelemetry.io/ebpf-profiler/libpf"

import (
"encoding/json"
"fmt"
"math"
"time"
)

Expand All @@ -32,36 +30,9 @@ func NowAsUInt32() uint32 {
return uint32(time.Now().Unix())
}

// UnixTime64 represents nanoseconds or (reduced precision) seconds since epoch.
// UnixTime64 represents nanoseconds since epoch.
type UnixTime64 uint64

func (t UnixTime64) MarshalJSON() ([]byte, error) {
if t > math.MaxUint32 {
// Nanoseconds, ES does not support 'epoch_nanoseconds' so
// we have to pass it a value formatted as 'strict_date_optional_time_nanos'.
out := []byte(fmt.Sprintf("%q",
time.Unix(0, int64(t)).UTC().Format(time.RFC3339Nano)))
return out, nil
}

// Reduced precision seconds-since-the-epoch, ES 'epoch_second' formatter will match these.
out := []byte(fmt.Sprintf("%d", t))
return out, nil
}

// Unix returns the value as seconds since epoch.
func (t UnixTime64) Unix() int64 {
if t > math.MaxUint32 {
// Nanoseconds, convert to seconds-since-the-epoch
return time.Unix(0, int64(t)).Unix()
}

return int64(t)
}

// Compile-time interface checks
var _ json.Marshaler = (*UnixTime64)(nil)

// AddressOrLineno represents a line number in an interpreted file or an offset into
// a native file.
type AddressOrLineno uint64
Expand Down
35 changes: 0 additions & 35 deletions libpf/libpf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
package libpf

import (
"fmt"
"strconv"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestTraceType(t *testing.T) {
Expand Down Expand Up @@ -45,35 +42,3 @@ func TestTraceType(t *testing.T) {
assert.Equal(t, test.str, test.ty.String())
}
}

func TestUnixTime64_MarshalJSON(t *testing.T) {
tests := []struct {
name string
time UnixTime64
want []byte
}{
{
name: "zero",
time: UnixTime64(0),
want: []byte(strconv.Itoa(0)),
},
{
name: "non-zero, seconds since the epoch",
time: UnixTime64(1710349106),
want: []byte(strconv.Itoa(1710349106)),
},
{
name: "non-zero, nanoseconds since the epoch",
time: UnixTime64(1710349106864964685),
want: []byte(fmt.Sprintf("%q", "2024-03-13T16:58:26.864964685Z")),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
b, err := test.time.MarshalJSON()
require.NoError(t, err)
assert.Equal(t, test.want, b)
})
}
}
Loading

0 comments on commit 0d27b95

Please sign in to comment.