Skip to content

Commit

Permalink
Merge pull request #12 from chentao-kernel/dev
Browse files Browse the repository at this point in the history
add bootoffsettime
  • Loading branch information
chentao-kernel authored Nov 13, 2024
2 parents 936d471 + 529fbed commit 3ab937d
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 4 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ lint-check:
echo "Linting golang code..."
$(REVIVE) -config .revive.toml ./...

.PHONY: gofmt-check
gofmt-check:
gofmt -s -d .

.PHONY: gofmt-fix
gofmt-fix:
gofmt -s -w .

clean:
find . -name "*.o" | xargs rm -f
make -C $(LIBBPF_SRC) clean
Expand Down
9 changes: 9 additions & 0 deletions build/Dockerfile.arm64
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM --platform=linux/arm64 golang:1.20-alpine3.16

RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories

RUN apk update && apk upgrade && \
apk add cmake --no-cache binutils clang make git zstd gcc g++ libc-dev musl-dev bash zlib-dev elfutils-dev libelf-static zlib-static openssh llvm \
linux-headers

RUN go env -w GOPROXY="https://proxy.golang.com.cn,direct"
2 changes: 2 additions & 0 deletions build/build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/bin/bash

#refrence:https://www.kancloud.cn/woshigrey/docker/935037
# run arm docker on x86 host
# docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

read -r -d '' USAGE << EOF || true
usage: ./build.sh [-h|--help -b|--build -c|--compile -t|--tar -V|--bin_ver -p|--proxy]
Expand Down
12 changes: 8 additions & 4 deletions pkg/component/detector/cpudetector/cpudetector.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/chentao-kernel/spycat/pkg/component/detector/cpudetector/upstream/remote"
"github.com/chentao-kernel/spycat/pkg/core/model"
"github.com/chentao-kernel/spycat/pkg/log"
"github.com/chentao-kernel/spycat/pkg/util"
"github.com/chentao-kernel/spycat/pkg/util/alignedticker"
"github.com/chentao-kernel/spycat/pkg/util/trie"

Expand Down Expand Up @@ -303,17 +304,20 @@ func (c *CpuDetector) formatOffcpuLabels(e *model.SpyEvent) (*model.AttributeMap
userAttributes := e.UserAttributes[i]
switch {
case userAttributes.GetKey() == "t_start_time":
labels.AddIntValue(model.StartTime, int64(userAttributes.GetUintValue()))
startTime := util.BootOffsetToTime(uint64(userAttributes.GetUintValue()))
labels.AddStringValue(model.StartTime, startTime.Format("2006-01-02 15:04:05.000"))
case userAttributes.GetKey() == "cpu":
labels.AddIntValue(model.Cpu, int64(userAttributes.GetUintValue()))
case userAttributes.GetKey() == "prio":
labels.AddIntValue(model.Prio, int64(userAttributes.GetUintValue()))
case userAttributes.GetKey() == "cache_id":
labels.AddIntValue(model.CacheId, int64(userAttributes.GetUintValue()))
case userAttributes.GetKey() == "t_end_time":
labels.AddIntValue(model.EndTime, int64(userAttributes.GetUintValue()))
endTime := util.BootOffsetToTime(uint64(userAttributes.GetUintValue()))
labels.AddStringValue(model.EndTime, endTime.Format("2006-01-02 15:04:05.000"))
case userAttributes.GetKey() == "ts":
labels.AddIntValue(model.TimeStamp, int64(userAttributes.GetUintValue()))
ts := util.BootOffsetToTime(uint64(userAttributes.GetUintValue()))
labels.AddStringValue(model.TimeStamp, ts.Format("2006-01-02 15:04:05.000"))
case userAttributes.GetKey() == "dur_ms":
labels.AddIntValue(model.DurMs, int64(userAttributes.GetUintValue()))
case userAttributes.GetKey() == "rq_dur_ms":
Expand Down Expand Up @@ -368,7 +372,7 @@ func (c *CpuDetector) offcpuHandler(e *model.SpyEvent) (*model.DataBlock, error)
labels, _ := c.formatOffcpuLabels(e)
// util.PrintStructFields(*ev)
// c.PutEventToSegments(e.GetPid(), e.GetTid(), e.GetComm(), ev)
val := e.GetUintUserAttribute("t_offcpu_oncpu")
val := e.GetUintUserAttribute("dur_ms")
metric := model.NewIntMetric(model.OffCpuMetricName, int64(val))
return model.NewDataBlock(model.OffCpu, labels, e.TimeStamp, metric), nil
}
Expand Down
73 changes: 73 additions & 0 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ package util
import (
"bufio"
"fmt"
"math"
"os"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"time"

"golang.org/x/sys/unix"

"github.com/chentao-kernel/spycat/pkg/log"
)
Expand Down Expand Up @@ -172,3 +176,72 @@ func KprobeExists(name string) bool {
}
return checkKallsyms(name)
}

// copy from opentelemetry-go
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).

// There can be an arbitrary amount of time between the execution of
// time.Now() and unix.ClockGettime() below, especially under scheduler
// pressure during program startup. To reduce the error introduced by these
// delays, we pin the current Go routine to its OS thread and measure the
// clocks multiple times, taking only the smallest observed difference
// between the two values (which implies the smallest possible delay
// between the two snapshots).
var minDiff int64 = 1<<63 - 1
estimationRounds := 25
runtime.LockOSThread()
defer runtime.UnlockOSThread()
for round := 0; round < estimationRounds; round++ {
var bootTimespec unix.Timespec

// Ideally we would use __vdso_clock_gettime for both clocks here,
// to have as little overhead as possible.
// time.Now() will actually use VDSO on Go 1.9+, but calling
// unix.ClockGettime to obtain CLOCK_BOOTTIME is a regular system call
// for now.
unixTime := time.Now()
err = unix.ClockGettime(unix.CLOCK_BOOTTIME, &bootTimespec)
if err != nil {
return 0, err
}

offset := unixTime.UnixNano() - bootTimespec.Nano()
diff := offset
if diff < 0 {
diff = -diff
}

if diff < minDiff {
minDiff = diff
bootTimeOffset = offset
}
}

return bootTimeOffset, nil
}

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

func BootOffsetToTime(nsec uint64) time.Time {
if nsec > math.MaxInt64 {
nsec = math.MaxInt64
}
return time.Unix(0, bootTimeOffset()+int64(nsec))
}

func TimeToBootOffset(ts time.Time) uint64 {
nsec := ts.UnixNano() - bootTimeOffset()
if nsec < 0 {
return 0
}
return uint64(nsec)
}

0 comments on commit 3ab937d

Please sign in to comment.