inspektor-gadget
114 строк · 2.6 Кб
1// Copyright 2023 The Inspektor Gadget authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//go:build !withoutebpf
16
17package tracer
18
19import (
20"bufio"
21"fmt"
22"os"
23"os/exec"
24
25gadgetcontext "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-context"
26"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets"
27"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/script/types"
28)
29
30type Config struct {
31Program string
32}
33
34type Tracer struct {
35eventCallback func(ev *types.Event)
36config Config
37}
38
39func (t *Tracer) Run(gadgetCtx gadgets.GadgetContext) error {
40params := gadgetCtx.GadgetParams()
41t.config.Program = params.Get(ParamProgram).AsString()
42log := gadgetCtx.Logger()
43
44// TODO: Consider using CommandContext() once we support Go 1.20
45cmd := exec.Command("bpftrace", "-e", t.config.Program)
46
47stdout, err := cmd.StdoutPipe()
48if err != nil {
49return fmt.Errorf("getting stdout pipe: %w", err)
50}
51
52stderr, err := cmd.StderrPipe()
53if err != nil {
54return fmt.Errorf("getting stderr pipe: %w", err)
55}
56
57if err := cmd.Start(); err != nil {
58return fmt.Errorf("running bpftrace: %w", err)
59}
60
61// read and send stdout as events
62go func() {
63scanner := bufio.NewScanner(stdout)
64
65for scanner.Scan() {
66t.eventCallback(&types.Event{
67Output: scanner.Text(),
68})
69}
70
71if err := scanner.Err(); err != nil {
72log.Error("error reading bpftrace output: %s", err)
73}
74}()
75
76// print stderr through logger
77go func() {
78scanner := bufio.NewScanner(stderr)
79
80for scanner.Scan() {
81log.Error(scanner.Text())
82}
83
84if err := scanner.Err(); err != nil {
85log.Error("error reading bpftrace output: %s", err)
86}
87}()
88
89gadgetcontext.WaitForTimeoutOrDone(gadgetCtx)
90
91if err := cmd.Process.Signal(os.Interrupt); err != nil {
92log.Errorf("failed to stop process: %s", err)
93return nil
94}
95
96if err := cmd.Wait(); err != nil {
97log.Errorf("failed to wait process: %s", err)
98return nil
99}
100
101return nil
102}
103
104func (t *Tracer) SetEventHandler(handler any) {
105nh, ok := handler.(func(ev *types.Event))
106if !ok {
107panic("event handler invalid")
108}
109t.eventCallback = nh
110}
111
112func (g *GadgetDesc) NewInstance() (gadgets.Gadget, error) {
113return &Tracer{}, nil
114}
115