This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-rover.git
The following commit(s) were added to refs/heads/main by this push:
new a11d119 Support OFF CPU Profiling (#34)
a11d119 is described below
commit a11d119de35944f3bd17103efb69263a18b7c6e2
Author: mrproliu <[email protected]>
AuthorDate: Wed May 18 23:35:06 2022 +0800
Support OFF CPU Profiling (#34)
---
CHANGES.md | 11 ++
bpf/include/api.h | 27 ++-
bpf/profiling/offcpu.c | 82 ++++++++
.../task/base/target.go => bpf/profiling/offcpu.h | 52 +++---
docker/Dockerfile.base | 6 +-
go.mod | 2 +-
go.sum | 4 +-
pkg/profiling/task/base/runner.go | 65 +++++++
pkg/profiling/task/base/target.go | 5 +-
pkg/profiling/task/offcpu/runner.go | 206 +++++++++++++++++++++
pkg/profiling/task/oncpu/runner.go | 51 ++---
pkg/profiling/task/registion.go | 2 +
12 files changed, 431 insertions(+), 82 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index c545b0e..a6812cc 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,17 @@ Changes by Version
==================
Release Notes.
+0.2.0
+------------------
+#### Features
+* Support `OFF_CPU` Profiling.
+
+#### Bug Fixes
+
+#### Issues and PR
+- All issues are
[here](https://github.com/apache/skywalking/milestone/134?closed=1)
+- All and pull requests are
[here](https://github.com/apache/skywalking-rover/milestone/2?closed=1)
+
0.1.0
------------------
#### Features
diff --git a/bpf/include/api.h b/bpf/include/api.h
index f058e20..a136dc7 100644
--- a/bpf/include/api.h
+++ b/bpf/include/api.h
@@ -19,22 +19,19 @@
#define __BPF_API__
// include linux relate bpf
+#include <stddef.h>
+#include <linux/sched.h>
#include <linux/bpf.h>
+#include <linux/ptrace.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
-#define __uint(name, val) int (*name)[val]
-#define __type(name, val) typeof(val) *name
-#define __array(name, val) typeof(val) *name[]
-
-// Method Selection
-#define SEC(name) \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wignored-attributes\"") \
- __attribute__((section(name), used)) \
- _Pragma("GCC diagnostic pop") \
-
-// which reference what we need
-struct pt_regs;
-static long (*bpf_perf_event_output)(void *ctx, void *map, __u64 flags, void
*data, __u64 size) = (void *) 25;
-static long (*bpf_get_stackid)(void *ctx, void *map, __u64 flags) = (void *)
27;
+#define _(P)
\
+ ({ \
+ typeof(P) val; \
+ bpf_probe_read_kernel(&val, sizeof(val), &(P)); \
+ val; \
+ })
#endif
\ No newline at end of file
diff --git a/bpf/profiling/offcpu.c b/bpf/profiling/offcpu.c
new file mode 100644
index 0000000..b1a7ff1
--- /dev/null
+++ b/bpf/profiling/offcpu.c
@@ -0,0 +1,82 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "api.h"
+#include "offcpu.h"
+
+char __license[] SEC("license") = "Dual MIT/GPL";
+
+SEC("kprobe/finish_task_switch")
+int do_finish_task_switch(struct pt_regs *ctx) {
+ int monitor_pid;
+ asm("%0 = MONITOR_PID ll" : "=r"(monitor_pid));
+
+ __u32 pid, tgid;
+ __u64 ts, *tsp;
+
+ struct task_struct *prev = (void *) PT_REGS_PARM1(ctx);
+ pid = _(prev->pid);
+ tgid = _(prev->tgid);
+
+ // in kernel, tgid means the process id
+ // monitor_pid is the same concept with process id
+ // only the monitor pid is same with previous process id could record the
start time
+ if (tgid == monitor_pid) {
+ ts = bpf_ktime_get_ns();
+ bpf_map_update_elem(&starts, &pid, &ts, BPF_ANY);
+ }
+
+ // if current process have record start time in the map
+ // means the monitored process switch to the on-cpu
+ struct task_struct *current = (void *)bpf_get_current_task();
+ pid = _(current->pid);
+ tgid = _(current->tgid);
+ if (tgid != monitor_pid) {
+ return 0;
+ }
+ tsp = bpf_map_lookup_elem(&starts, &pid);
+ if (tsp == 0) {
+ return 0; // missed start or filtered
+ }
+
+ // calculate the duration(on->off to off->on)
+ __u64 t_start = *tsp;
+ __u64 t_end = bpf_ktime_get_ns();
+ bpf_map_delete_elem(&starts, &pid);
+ if (t_start > t_end) {
+ return 0;
+ }
+
+ // create map key
+ struct key_t key = {};
+ key.kernel_stack_id = bpf_get_stackid(ctx, &stacks, 0);
+ key.user_stack_id = bpf_get_stackid(ctx, &stacks, (1ULL << 8));
+
+ // add counters
+ struct value_t *val;
+ val = bpf_map_lookup_elem(&counts, &key);
+ if (!val) {
+ struct value_t value = {};
+ bpf_map_update_elem(&counts, &key, &value, BPF_NOEXIST);
+ val = bpf_map_lookup_elem(&counts, &key);
+ if (!val)
+ return 0;
+ }
+ (*val).counts += 1;
+ (*val).deltas += t_end - t_start;
+ return 0;
+}
\ No newline at end of file
diff --git a/pkg/profiling/task/base/target.go b/bpf/profiling/offcpu.h
similarity index 53%
copy from pkg/profiling/task/base/target.go
copy to bpf/profiling/offcpu.h
index 849729b..cc5a73b 100644
--- a/pkg/profiling/task/base/target.go
+++ b/bpf/profiling/offcpu.h
@@ -15,30 +15,38 @@
// specific language governing permissions and limitations
// under the License.
-package base
+struct key_t {
+ int user_stack_id;
+ int kernel_stack_id;
+};
-import (
- "fmt"
+struct value_t {
+ __u64 counts;
+ __u64 deltas;
+};
- v3 "skywalking.apache.org/repo/goapi/collect/common/v3"
-)
+struct {
+ __uint(type, BPF_MAP_TYPE_STACK_TRACE);
+ __uint(key_size, sizeof(__u32));
+ __uint(value_size, 100 * sizeof(__u64));
+ __uint(max_entries, 10000);
+} stacks SEC(".maps");
-type TargetType string
+struct {
+ __uint(type, BPF_MAP_TYPE_LRU_HASH);
+ __uint(key_size, sizeof(__u32));
+ __uint(value_size, sizeof(__u64));
+ __uint(max_entries, 10000);
+} starts SEC(".maps");
-const (
- TargetTypeOnCPU TargetType = "ON_CPU"
-)
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __type(key, struct key_t);
+ __type(value, struct value_t);
+ __uint(max_entries, 10000);
+} counts SEC(".maps");
-func ParseTargetType(err error, val string) (TargetType, error) {
- if err != nil {
- return "", err
- }
- if TargetType(val) == TargetTypeOnCPU {
- return TargetTypeOnCPU, nil
- }
- return "", fmt.Errorf("could not found target type: %s", val)
-}
-
-func (t TargetType) InitTask(task *ProfilingTask, command *v3.Command) error {
- return nil
-}
+struct task_struct {
+ __u32 pid;
+ __u32 tgid;
+} __attribute__((preserve_access_index));
\ No newline at end of file
diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base
index b938223..dfb031f 100644
--- a/docker/Dockerfile.base
+++ b/docker/Dockerfile.base
@@ -18,8 +18,10 @@ FROM golang:1.17
RUN apt update && \
apt install -y libbpf-dev lsb-release wget software-properties-common && \
- mkdir /usr/include/asm && \
- cp /usr/include/asm-generic/* /usr/include/asm && \
+ mkdir -p /usr/include/asm /usr/include/bits /usr/include/sys && \
+ cp -r /usr/include/$(uname -m)*/asm/* /usr/include/asm && \
+ cp -r /usr/include/$(uname -m)*/bits/* /usr/include/bits && \
+ cp -r /usr/include/asm-generic/* /usr/include/asm && \
wget https://apt.llvm.org/llvm.sh && \
chmod +x llvm.sh && \
./llvm.sh 13
diff --git a/go.mod b/go.mod
index 242a8d1..f77d120 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
k8s.io/api v0.23.5
k8s.io/apimachinery v0.23.5
k8s.io/client-go v0.23.5
- skywalking.apache.org/repo/goapi v0.0.0-20220513074115-4af2c2d37d2f
+ skywalking.apache.org/repo/goapi v0.0.0-20220518063910-af3e2df60bce
)
require (
diff --git a/go.sum b/go.sum
index 576eee9..6e64dd0 100644
--- a/go.sum
+++ b/go.sum
@@ -940,5 +940,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.2.1
h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLz
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod
h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-skywalking.apache.org/repo/goapi v0.0.0-20220513074115-4af2c2d37d2f
h1:InBru/3MVpcVoGPGRjY+A5LpAi992E37j6dCvvNqF/w=
-skywalking.apache.org/repo/goapi v0.0.0-20220513074115-4af2c2d37d2f/go.mod
h1:uWwwvhcwe2MD/nJCg0c1EE/eL6KzaBosLHDfMFoEJ30=
+skywalking.apache.org/repo/goapi v0.0.0-20220518063910-af3e2df60bce
h1:3wCiFWEEREdxe0T/PJM1S6DDqDsKETYVNtfaJ4zWmdQ=
+skywalking.apache.org/repo/goapi v0.0.0-20220518063910-af3e2df60bce/go.mod
h1:uWwwvhcwe2MD/nJCg0c1EE/eL6KzaBosLHDfMFoEJ30=
diff --git a/pkg/profiling/task/base/runner.go
b/pkg/profiling/task/base/runner.go
new file mode 100644
index 0000000..a874893
--- /dev/null
+++ b/pkg/profiling/task/base/runner.go
@@ -0,0 +1,65 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package base
+
+import (
+ "math"
+ "sync"
+
+ "github.com/cilium/ebpf"
+
+ "github.com/apache/skywalking-rover/pkg/logger"
+ "github.com/apache/skywalking-rover/pkg/tools/profiling"
+
+ v3 "skywalking.apache.org/repo/goapi/collect/ebpf/profiling/v3"
+)
+
+var log = logger.GetLogger("profiling", "task", "base")
+
+type Runner struct {
+ StackNotFoundCache map[uint32]bool
+ ShutdownOnce sync.Once
+}
+
+func NewBaseRunner() *Runner {
+ return &Runner{StackNotFoundCache: make(map[uint32]bool)}
+}
+
+func (r *Runner) GenerateProfilingData(profilingInfo *profiling.Info, stackID
uint32, stackMap *ebpf.Map,
+ stackType v3.EBPFProfilingStackType, symbolArray []uint64)
*v3.EBPFProfilingStackMetadata {
+ if profilingInfo == nil || stackID <= 0 || stackID == math.MaxUint32 {
+ return nil
+ }
+ if err := stackMap.Lookup(stackID, symbolArray); err != nil {
+ if r.StackNotFoundCache[stackID] {
+ return nil
+ }
+ r.StackNotFoundCache[stackID] = true
+ log.Warnf("error to lookup %v stack: %d, error: %v", stackType,
stackID, err)
+ return nil
+ }
+ symbols := profilingInfo.FindSymbols(symbolArray, MissingSymbol)
+ if len(symbols) == 0 {
+ return nil
+ }
+ return &v3.EBPFProfilingStackMetadata{
+ StackType: stackType,
+ StackId: int32(stackID),
+ StackSymbols: symbols,
+ }
+}
diff --git a/pkg/profiling/task/base/target.go
b/pkg/profiling/task/base/target.go
index 849729b..25054f0 100644
--- a/pkg/profiling/task/base/target.go
+++ b/pkg/profiling/task/base/target.go
@@ -26,7 +26,8 @@ import (
type TargetType string
const (
- TargetTypeOnCPU TargetType = "ON_CPU"
+ TargetTypeOnCPU TargetType = "ON_CPU"
+ TargetTypeOffCPU TargetType = "OFF_CPU"
)
func ParseTargetType(err error, val string) (TargetType, error) {
@@ -35,6 +36,8 @@ func ParseTargetType(err error, val string) (TargetType,
error) {
}
if TargetType(val) == TargetTypeOnCPU {
return TargetTypeOnCPU, nil
+ } else if TargetType(val) == TargetTypeOffCPU {
+ return TargetTypeOffCPU, nil
}
return "", fmt.Errorf("could not found target type: %s", val)
}
diff --git a/pkg/profiling/task/offcpu/runner.go
b/pkg/profiling/task/offcpu/runner.go
new file mode 100644
index 0000000..85fea37
--- /dev/null
+++ b/pkg/profiling/task/offcpu/runner.go
@@ -0,0 +1,206 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build linux
+
+package offcpu
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/hashicorp/go-multierror"
+
+ "github.com/cilium/ebpf/link"
+
+ "github.com/apache/skywalking-rover/pkg/logger"
+ "github.com/apache/skywalking-rover/pkg/process/api"
+ "github.com/apache/skywalking-rover/pkg/profiling/task/base"
+ "github.com/apache/skywalking-rover/pkg/tools"
+ "github.com/apache/skywalking-rover/pkg/tools/profiling"
+
+ v3 "skywalking.apache.org/repo/goapi/collect/ebpf/profiling/v3"
+)
+
+// $BPF_CLANG and $BPF_CFLAGS are set by the Makefile.
+// nolint
+//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -cflags
$BPF_CFLAGS bpf $REPO_ROOT/bpf/profiling/offcpu.c -- -I$REPO_ROOT/bpf/include
-D__TARGET_ARCH_x86
+
+var log = logger.GetLogger("profiling", "task", "offcpu")
+
+type ProcessStack struct {
+ UserStackID uint32
+ KernelStackID uint32
+}
+
+type StackCounter struct {
+ Times uint64 // total execute count
+ Deltas uint64 // total execute delta duration(nanoseconds)
+}
+
+type Runner struct {
+ base *base.Runner
+ pid int32
+ processProfiling *profiling.Info
+ kernelProfiling *profiling.Info
+
+ // runtime
+ previousStacks map[ProcessStack]*StackCounter
+ bpf *bpfObjects
+ kprobe link.Link
+ stopChan chan bool
+ flushDataNotify context.CancelFunc
+}
+
+func NewRunner(config *base.TaskConfig) (base.ProfileTaskRunner, error) {
+ return &Runner{
+ base: base.NewBaseRunner(),
+ }, nil
+}
+
+func (r *Runner) Init(task *base.ProfilingTask, process api.ProcessInterface)
error {
+ r.pid = process.Pid()
+ r.processProfiling = process.ProfilingStat()
+ kernelProfiling, err := tools.KernelFileProfilingStat()
+ if err != nil {
+ log.Warnf("could not analyze kernel profiling stats: %v", err)
+ }
+ r.kernelProfiling = kernelProfiling
+ r.previousStacks = make(map[ProcessStack]*StackCounter)
+ r.stopChan = make(chan bool, 1)
+ return nil
+}
+
+func (r *Runner) Run(ctx context.Context, notify
base.ProfilingRunningSuccessNotify) error {
+ objs := bpfObjects{}
+ spec, err := loadBpf()
+ if err != nil {
+ return err
+ }
+ // update the monitor pid
+ funcName := "do_finish_task_switch"
+ replacedPid := false
+ for i, ins := range spec.Programs[funcName].Instructions {
+ if ins.Reference == "MONITOR_PID" {
+ spec.Programs[funcName].Instructions[i].Constant =
int64(r.pid)
+ spec.Programs[funcName].Instructions[i].Offset = 0
+ replacedPid = true
+ }
+ }
+ if !replacedPid {
+ return fmt.Errorf("replace the monitor pid failure")
+ }
+ if err1 := spec.LoadAndAssign(&objs, nil); err1 != nil {
+ return err1
+ }
+ r.bpf = &objs
+
+ kprobe, err := link.Kprobe("finish_task_switch",
objs.DoFinishTaskSwitch)
+ if err != nil {
+ log.Fatalf("link to finish task swtich failure: %v", err)
+ }
+ r.kprobe = kprobe
+
+ notify()
+ <-r.stopChan
+ return nil
+}
+
+func (r *Runner) Stop() error {
+ var err error
+ r.base.ShutdownOnce.Do(func() {
+ // wait for all profiling data been consumed finished
+ cancel, cancelFunc := context.WithCancel(context.Background())
+ r.flushDataNotify = cancelFunc
+ select {
+ case <-cancel.Done():
+ case <-time.After(10 * time.Second):
+ }
+
+ if r.bpf != nil {
+ if err1 := r.bpf.Close(); err1 != nil {
+ err = multierror.Append(err, err1)
+ }
+ r.bpf = nil
+ }
+ if r.kprobe != nil {
+ if err1 := r.kprobe.Close(); err1 != nil {
+ err = multierror.Append(err, err1)
+ }
+ }
+ close(r.stopChan)
+ })
+ return err
+}
+
+func (r *Runner) FlushData() ([]*v3.EBPFProfilingData, error) {
+ if r.bpf == nil {
+ return nil, nil
+ }
+ if r.flushDataNotify == nil {
+ return nil, nil
+ }
+ var stack ProcessStack
+ var counter StackCounter
+ iterate := r.bpf.Counts.Iterate()
+ stacks := r.bpf.Stacks
+ result := make([]*v3.EBPFProfilingData, 0)
+ stackSymbols := make([]uint64, 100)
+ for iterate.Next(&stack, &counter) {
+ metadatas := make([]*v3.EBPFProfilingStackMetadata, 0)
+ // kernel stack
+ if d := r.base.GenerateProfilingData(r.kernelProfiling,
stack.KernelStackID, stacks,
+ v3.EBPFProfilingStackType_PROCESS_KERNEL_SPACE,
stackSymbols); d != nil {
+ metadatas = append(metadatas, d)
+ }
+ // user stack
+ if d := r.base.GenerateProfilingData(r.processProfiling,
stack.UserStackID, stacks,
+ v3.EBPFProfilingStackType_PROCESS_USER_SPACE,
stackSymbols); d != nil {
+ metadatas = append(metadatas, d)
+ }
+
+ if len(metadatas) == 0 {
+ continue
+ }
+
+ // update the counters in memory
+ switchCount := int32(counter.Times)
+ duration := int64(counter.Deltas)
+ existCounter := r.previousStacks[stack]
+ if existCounter != nil {
+ switchCount -= int32(existCounter.Times)
+ duration -= int64(existCounter.Deltas)
+ }
+ r.previousStacks[stack] = &counter
+
+ result = append(result, &v3.EBPFProfilingData{
+ Profiling: &v3.EBPFProfilingData_OffCPU{
+ OffCPU: &v3.EBPFOffCPUProfiling{
+ Stacks: metadatas,
+ SwitchCount: switchCount,
+ Duration: duration,
+ },
+ },
+ })
+ }
+
+ if r.flushDataNotify != nil {
+ r.flushDataNotify()
+ }
+ return result, nil
+}
diff --git a/pkg/profiling/task/oncpu/runner.go
b/pkg/profiling/task/oncpu/runner.go
index a929a90..6ea9f47 100644
--- a/pkg/profiling/task/oncpu/runner.go
+++ b/pkg/profiling/task/oncpu/runner.go
@@ -25,10 +25,8 @@ import (
"encoding/binary"
"errors"
"fmt"
- "math"
"os"
"runtime"
- "sync"
"time"
"github.com/cilium/ebpf"
@@ -59,19 +57,18 @@ type Event struct {
}
type Runner struct {
+ base *base.Runner
pid int32
processProfiling *profiling.Info
kernelProfiling *profiling.Info
dumpPeriod time.Duration
// runtime
- perfEventFds []int
- countReader *perf.Reader
- stackCounter map[Event]int
- stackMap *ebpf.Map
- stackNotFoundCache map[uint32]bool
- shutdownOnce sync.Once
- flushDataNotify context.CancelFunc
+ perfEventFds []int
+ countReader *perf.Reader
+ stackCounter map[Event]int
+ stackMap *ebpf.Map
+ flushDataNotify context.CancelFunc
}
func NewRunner(config *base.TaskConfig) (base.ProfileTaskRunner, error) {
@@ -86,9 +83,9 @@ func NewRunner(config *base.TaskConfig)
(base.ProfileTaskRunner, error) {
return nil, fmt.Errorf("the ON_CPU dump period could not be
smaller than 1ms")
}
return &Runner{
- dumpPeriod: dumpPeriod,
- stackNotFoundCache: make(map[uint32]bool),
- stackCounter: make(map[Event]int),
+ base: base.NewBaseRunner(),
+ dumpPeriod: dumpPeriod,
+ stackCounter: make(map[Event]int),
}, nil
}
@@ -201,7 +198,7 @@ func (r *Runner) openPerfEvent(perfFd int) ([]int, error) {
func (r *Runner) Stop() error {
var result error
- r.shutdownOnce.Do(func() {
+ r.base.ShutdownOnce.Do(func() {
for _, fd := range r.perfEventFds {
if err := r.closePerfEvent(fd); err != nil {
result = multierror.Append(result, err)
@@ -233,13 +230,13 @@ func (r *Runner) FlushData() ([]*v3.EBPFProfilingData,
error) {
for event, count := range existsCounters {
metadatas := make([]*v3.EBPFProfilingStackMetadata, 0)
// kernel stack
- if d := r.generateProfilingData(r.kernelProfiling,
event.KernelStackID,
+ if d := r.base.GenerateProfilingData(r.kernelProfiling,
event.KernelStackID, r.stackMap,
v3.EBPFProfilingStackType_PROCESS_KERNEL_SPACE,
stackSymbols); d != nil {
metadatas = append(metadatas, d)
}
// user stack
- if d := r.generateProfilingData(r.processProfiling,
event.UserStackID,
+ if d := r.base.GenerateProfilingData(r.processProfiling,
event.UserStackID, r.stackMap,
v3.EBPFProfilingStackType_PROCESS_USER_SPACE,
stackSymbols); d != nil {
metadatas = append(metadatas, d)
}
@@ -266,30 +263,6 @@ func (r *Runner) FlushData() ([]*v3.EBPFProfilingData,
error) {
return result, nil
}
-func (r *Runner) generateProfilingData(profilingInfo *profiling.Info, stackID
uint32,
- stackType v3.EBPFProfilingStackType, symbolArray []uint64)
*v3.EBPFProfilingStackMetadata {
- if profilingInfo == nil || stackID <= 0 || stackID == math.MaxUint32 {
- return nil
- }
- if err := r.stackMap.Lookup(stackID, symbolArray); err != nil {
- if r.stackNotFoundCache[stackID] {
- return nil
- }
- r.stackNotFoundCache[stackID] = true
- log.Warnf("error to lookup %v stack: %d, error: %v", stackType,
stackID, err)
- return nil
- }
- symbols := profilingInfo.FindSymbols(symbolArray, base.MissingSymbol)
- if len(symbols) == 0 {
- return nil
- }
- return &v3.EBPFProfilingStackMetadata{
- StackType: stackType,
- StackId: int32(stackID),
- StackSymbols: symbols,
- }
-}
-
func (r *Runner) flushStackCounter() map[Event]int {
updateTo := make(map[Event]int)
updateToP := &updateTo
diff --git a/pkg/profiling/task/registion.go b/pkg/profiling/task/registion.go
index 2e9271b..f88d161 100644
--- a/pkg/profiling/task/registion.go
+++ b/pkg/profiling/task/registion.go
@@ -23,6 +23,7 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/apache/skywalking-rover/pkg/profiling/task/base"
+ "github.com/apache/skywalking-rover/pkg/profiling/task/offcpu"
"github.com/apache/skywalking-rover/pkg/profiling/task/oncpu"
)
@@ -30,6 +31,7 @@ var profilingRunners = make(map[base.TargetType]func(config
*base.TaskConfig) (b
func init() {
profilingRunners[base.TargetTypeOnCPU] = oncpu.NewRunner
+ profilingRunners[base.TargetTypeOffCPU] = offcpu.NewRunner
}
func NewProfilingRunner(taskType base.TargetType, taskConfig *base.TaskConfig)
(base.ProfileTaskRunner, error) {