Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

discovery.process and pyroscope.java #5858

Merged
merged 81 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
d2f8d79
fix
korniltsev Nov 27, 2023
c760564
process discovery draft
korniltsev Nov 27, 2023
6ecfc15
fix test
korniltsev Nov 27, 2023
79a397d
tmp
korniltsev Dec 13, 2023
a33542d
loop seem work
korniltsev Dec 14, 2023
9b2f532
fix
korniltsev Dec 15, 2023
bbd6b7a
use shirou/gopsutil
korniltsev Jan 3, 2024
16fd32f
Merge branch 'discovery_process' into pyroscope-java
korniltsev Jan 3, 2024
9faeb23
add darwin
korniltsev Jan 4, 2024
eee5677
add proper extraction
korniltsev Jan 4, 2024
3cd66ad
java loop fixes
korniltsev Jan 5, 2024
4423b73
fix
korniltsev Jan 5, 2024
2e5ad13
fix
korniltsev Jan 5, 2024
ce7ab63
fixes
korniltsev Jan 5, 2024
0857f45
lbic detection fix
korniltsev Jan 5, 2024
0ea88fb
use jfr-parser lib
korniltsev Jan 8, 2024
2b05b04
handle marshall error
korniltsev Jan 8, 2024
8d0b6eb
fix jfr parsing for asprof 3.0
korniltsev Jan 8, 2024
b11aaf3
rm darwin, use 2.9 instead of 3.0-ea
korniltsev Jan 8, 2024
57f7fcb
switch back to 3.0 ea
korniltsev Jan 9, 2024
59b86f7
fix process alive check
korniltsev Jan 9, 2024
6a91e26
tmp dir arg
korniltsev Jan 9, 2024
d9a5ab8
discover config
korniltsev Jan 9, 2024
074acc1
improve logging
korniltsev Jan 9, 2024
3c5e922
improve logging
korniltsev Jan 9, 2024
2df98d5
fix shutdodown
korniltsev Jan 9, 2024
da58272
improve extract
korniltsev Jan 9, 2024
80c719a
stub
korniltsev Jan 9, 2024
a76ab8c
fix bug
korniltsev Jan 9, 2024
5245429
Merge remote-tracking branch 'origin/main' into discovery_process
korniltsev Jan 9, 2024
1dc6796
fix arm64
korniltsev Jan 9, 2024
7d8b1b5
fix stub
korniltsev Jan 9, 2024
21ff759
fix bild
korniltsev Jan 9, 2024
33cfdf4
fixbuild
korniltsev Jan 9, 2024
ed6a795
fix lib copying
korniltsev Jan 10, 2024
8cd3ca3
Update component/discovery/process/discover.go
korniltsev Jan 11, 2024
2fe0aba
Update component/pyroscope/java/java_stub.go
korniltsev Jan 11, 2024
60d96cd
Update component/pyroscope/java/loop.go
korniltsev Jan 11, 2024
cba6d8e
Update component/pyroscope/java/asprof/asprof_test.go
korniltsev Jan 11, 2024
0e369dc
review fixes
korniltsev Jan 11, 2024
d7a0054
handle discoverConfig and refreshinterval updates in discover.process…
korniltsev Jan 11, 2024
021ea45
add discovery.process.md
korniltsev Jan 11, 2024
28ab763
doc notes
korniltsev Jan 11, 2024
09869e6
cleanup
korniltsev Jan 11, 2024
80e430e
add pyroscope.java.md
korniltsev Jan 11, 2024
09f58c1
go gen
korniltsev Jan 11, 2024
67e5dd5
Merge remote-tracking branch 'origin/main' into discovery_process
korniltsev Jan 11, 2024
026ae31
fix windows build
korniltsev Jan 11, 2024
d1823b7
Update component/pyroscope/java/loop.go
korniltsev Jan 11, 2024
46a4748
Update component/discovery/process/process.go
korniltsev Jan 11, 2024
36e567b
rm incomplete tests
korniltsev Jan 11, 2024
ea65839
update loop target and profiling config
korniltsev Jan 11, 2024
0cfb9d2
link to async-profiler
korniltsev Jan 11, 2024
1a2b02a
more docs
korniltsev Jan 11, 2024
cdeb7e7
fix
korniltsev Jan 11, 2024
682b352
lint
korniltsev Jan 11, 2024
1ba2c8f
fix stub build
korniltsev Jan 11, 2024
283c341
lint
korniltsev Jan 11, 2024
ddaa3aa
restart
korniltsev Jan 11, 2024
8b66b30
fix
korniltsev Jan 11, 2024
a0dfedf
fix
korniltsev Jan 11, 2024
e312379
fix
korniltsev Jan 11, 2024
300ce7f
Update docs/sources/flow/reference/components/discovery.process.md
korniltsev Jan 12, 2024
e888cd4
Update docs/sources/flow/reference/components/discovery.process.md
korniltsev Jan 12, 2024
68dcf16
Update docs/sources/flow/reference/components/discovery.process.md
korniltsev Jan 12, 2024
5de7ed1
Update docs/sources/flow/reference/components/discovery.process.md
korniltsev Jan 12, 2024
9df7b7c
Update docs/sources/flow/reference/components/discovery.process.md
korniltsev Jan 12, 2024
e215947
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 12, 2024
08c5f45
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 12, 2024
e53b0dc
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 12, 2024
4835d23
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 12, 2024
d022e85
Update docs/sources/flow/reference/components/discovery.process.md
korniltsev Jan 12, 2024
166a42c
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 12, 2024
17764d3
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 12, 2024
2186950
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 12, 2024
fedd6dc
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 12, 2024
c18dae0
Apply suggestions from code review
korniltsev Jan 12, 2024
2c4b03b
Merge branch 'main' into discovery_process
korniltsev Jan 12, 2024
eadcad1
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 13, 2024
8d0def3
Update docs/sources/flow/reference/components/pyroscope.java.md
korniltsev Jan 13, 2024
887b9ed
Merge remote-tracking branch 'origin/main' into discovery_process
korniltsev Jan 16, 2024
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
1 change: 1 addition & 0 deletions component/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
_ "github.com/grafana/agent/component/discovery/nerve" // Import discovery.nerve
_ "github.com/grafana/agent/component/discovery/nomad" // Import discovery.nomad
_ "github.com/grafana/agent/component/discovery/openstack" // Import discovery.openstack
_ "github.com/grafana/agent/component/discovery/process" // Import discovery.process
_ "github.com/grafana/agent/component/discovery/puppetdb" // Import discovery.puppetdb
_ "github.com/grafana/agent/component/discovery/relabel" // Import discovery.relabel
_ "github.com/grafana/agent/component/discovery/scaleway" // Import discovery.scaleway
Expand Down
56 changes: 56 additions & 0 deletions component/discovery/process/container.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package process

import (
"bufio"
"io"
"regexp"
"strings"

"github.com/grafana/agent/component/discovery"
)

var (
// cgroupContainerIDRe matches a container ID from a /proc/{pid}}/cgroup
cgroupContainerIDRe = regexp.MustCompile(`^.*/(?:.*-)?([0-9a-f]{64})(?:\.|\s*$)`)
)

func getContainerIDFromCGroup(cgroup io.Reader) string {
scanner := bufio.NewScanner(cgroup)
for scanner.Scan() {
line := scanner.Bytes()
matches := cgroupContainerIDRe.FindSubmatch(line)
if len(matches) <= 1 {
continue
}
return string(matches[1])
}
return ""
}

var knownContainerIDPrefixes = []string{"docker://", "containerd://", "cri-o://"}

// get container id from __meta_kubernetes_pod_container_id label
func getContainerIDFromK8S(k8sContainerID string) string {
for _, p := range knownContainerIDPrefixes {
if strings.HasPrefix(k8sContainerID, p) {
return strings.TrimPrefix(k8sContainerID, p)
}
}
return ""
}

func getContainerIDFromTarget(target discovery.Target) string {
cid, ok := target[labelProcessContainerID]
if ok && cid != "" {
return cid
}
cid, ok = target["__meta_kubernetes_pod_container_id"]
if ok && cid != "" {
return getContainerIDFromK8S(cid)
}
cid, ok = target["__meta_docker_container_id"]
if ok && cid != "" {
return cid
}
return ""
}
64 changes: 64 additions & 0 deletions component/discovery/process/container_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package process

import (
"bytes"
"fmt"
"testing"

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

func TestCGroupMatching(t *testing.T) {
type testcase = struct {
containerID, cgroup, expectedID string
}
testcases := []testcase{
{
containerID: "containerd://a534eb629135e43beb13213976e37bb2ab95cba4c0d1d0b4e27c6bc4d8091b83",
cgroup: "12:cpuset:/kubepods.slice/kubepods-burstable.slice/" +
"kubepods-burstable-pod471203d1_984f_477e_9c35_db96487ffe5e.slice/" +
"cri-containerd-a534eb629135e43beb13213976e37bb2ab95cba4c0d1d0b4e27c6bc4d8091b83.scope",
expectedID: "a534eb629135e43beb13213976e37bb2ab95cba4c0d1d0b4e27c6bc4d8091b83",
},
{
containerID: "cri-o://0ecc7949cbaf17e883264ea1055f60b184a7cb264fd759c4a692e1155086fe2d",
cgroup: "0::/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podb57320a0_e7eb_4ac8_a791_4c4472796867.slice/" +
"crio-0ecc7949cbaf17e883264ea1055f60b184a7cb264fd759c4a692e1155086fe2d.scope",
expectedID: "0ecc7949cbaf17e883264ea1055f60b184a7cb264fd759c4a692e1155086fe2d",
},
{

containerID: "docker://656959d9ee87a0b131c601ce9d9f8f76b1dda60e8608c503b5979d849cbdc714",
cgroup: "0::/../../kubepods-besteffort-pod88f6f4e3_59c0_4ce8_9ecf_391c8b5a60ad.slice/" +
"docker-656959d9ee87a0b131c601ce9d9f8f76b1dda60e8608c503b5979d849cbdc714.scope",
expectedID: "656959d9ee87a0b131c601ce9d9f8f76b1dda60e8608c503b5979d849cbdc714",
},
{
containerID: "containerd://47e320f795efcec1ecf2001c3a09c95e3701ed87de8256837b70b10e23818251",
cgroup: "0::/kubepods.slice/kubepods-burstable.slice/" +
"kubepods-burstable-podf9a04ecc_1875_491b_926c_d2f64757704e.slice/" +
"cri-containerd-47e320f795efcec1ecf2001c3a09c95e3701ed87de8256837b70b10e23818251.scope",
expectedID: "47e320f795efcec1ecf2001c3a09c95e3701ed87de8256837b70b10e23818251",
},
{
containerID: "docker://7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
cgroup: "11:devices:/kubepods/besteffort/pod85adbef3-622f-4ef2-8f60-a8bdf3eb6c72/" +
"7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
expectedID: "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
},
{
containerID: "",
cgroup: "0::/../../user.slice/user-501.slice/session-3.scope",
expectedID: "",
},
}
for i, tc := range testcases {
t.Run(fmt.Sprintf("testcase %d %s", i, tc.cgroup), func(t *testing.T) {
cid := getContainerIDFromCGroup(bytes.NewReader([]byte(tc.cgroup)))
expected := tc.expectedID
require.Equal(t, expected, cid)
cid = getContainerIDFromK8S(tc.containerID)
require.Equal(t, expected, cid)
})
}
}
105 changes: 105 additions & 0 deletions component/discovery/process/discover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package process

import (
"errors"
"fmt"
"os"
"path"
"strconv"

"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/agent/component/discovery"
)

const (
labelProcessID = "__process_pid__"
labelProcessExe = "__meta_process_exe"
labelProcessCwd = "__meta_process_cwd"
labelProcessContainerID = "__container_id__"
)

type process struct {
pid string
exe string
cwd string
containerID string
}

func discover(l log.Logger, procFS string) ([]process, error) {
var (
err error
ps []process
)
pids, err := os.ReadDir(procFS)
if err != nil {
return nil, fmt.Errorf("discovery.process: failed to read /proc: %w", err)
}
for _, entry := range pids {
var (
exe string
cwd string
cgroup *os.File
)
if !entry.IsDir() {
continue
}
pidDir := entry
pid := pidDir.Name()
_, err = strconv.Atoi(pid)
if err != nil {
continue
}
exe, err = os.Readlink(path.Join(procFS, pid, "exe"))
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
_ = level.Error(l).Log("msg", "failed to read /proc/{pid}/exe", "err", err)
}
continue
}
cwd, err = os.Readlink(path.Join(procFS, pid, "cwd"))
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
_ = level.Error(l).Log("msg", "failed to read /proc/{pid}/cwd", "err", err)
}
continue
}
cgroup, err = os.Open(path.Join(procFS, pid, "cgroup"))
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
_ = level.Error(l).Log("msg", "failed to read /proc/{pid}/cgroup", "err", err)
}
continue
}
cid := getContainerIDFromCGroup(cgroup)
ps = append(ps, process{
pid: pid,
exe: exe,
cwd: cwd,
containerID: cid,
})
_ = cgroup.Close()
}
return ps, nil
}

func convertProcesses(ps []process) []discovery.Target {
var res []discovery.Target
for _, p := range ps {
t := convertProcess(p)
res = append(res, t)
}
return res
}

func convertProcess(p process) discovery.Target {
t := discovery.Target{
labelProcessID: p.pid,
labelProcessExe: p.exe,
labelProcessCwd: p.cwd,
}
if p.containerID != "" {
t[labelProcessContainerID] = p.containerID
}
return t
}
40 changes: 40 additions & 0 deletions component/discovery/process/join.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package process

import "github.com/grafana/agent/component/discovery"

func join(processes, containers []discovery.Target) []discovery.Target {
res := make([]discovery.Target, 0, len(processes)+len(containers))

cid2container := make(map[string]discovery.Target, len(containers))
for _, container := range containers {
cid := getContainerIDFromTarget(container)
if cid != "" {
cid2container[cid] = container
} else {
res = append(res, container)
}
}
for _, p := range processes {
cid := getContainerIDFromTarget(p)
if cid == "" {
res = append(res, p)
continue
}
container, ok := cid2container[cid]
if !ok {
continue
}
mergedTarget := make(discovery.Target, len(p)+len(container))
for k, v := range p {
mergedTarget[k] = v
}
for k, v := range container {
mergedTarget[k] = v
}
res = append(res, mergedTarget)
}
for _, target := range cid2container {
res = append(res, target)
}
return res
}
94 changes: 94 additions & 0 deletions component/discovery/process/join_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package process

import (
"fmt"
"testing"

"github.com/grafana/agent/component/discovery"
"github.com/stretchr/testify/assert"
)

func TestJoin(t *testing.T) {
testdata := []struct {
processes []discovery.Target
containers []discovery.Target
res []discovery.Target
}{
{
[]discovery.Target{
convertProcess(process{
pid: "239",
exe: "/bin/foo",
cwd: "/",
containerID: "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
}),
convertProcess(process{
pid: "240",
exe: "/bin/bar",
cwd: "/tmp",
containerID: "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
}),
convertProcess(process{
pid: "241",
exe: "/bin/bash",
cwd: "/opt",
containerID: "",
}),
}, []discovery.Target{
{
"__meta_docker_container_id": "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
"foo": "bar",
},
{
"__meta_kubernetes_pod_container_id": "docker://47e320f795efcec1ecf2001c3a09c95e3701ed87de8256837b70b10e23818251",
"qwe": "asd",
},
{
"lol": "lol",
},
}, []discovery.Target{
{
"__process_pid__": "239",
"__meta_process_exe": "/bin/foo",
"__meta_process_cwd": "/",
"__container_id__": "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
"__meta_docker_container_id": "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
"foo": "bar",
},
{
"__process_pid__": "240",
"__meta_process_exe": "/bin/bar",
"__meta_process_cwd": "/tmp",
"__container_id__": "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
"__meta_docker_container_id": "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
"foo": "bar",
},
{
"__meta_docker_container_id": "7edda1de1e0d1d366351e478359cf5fa16bb8ab53063a99bb119e56971bfb7e2",
"foo": "bar",
},
{
"__process_pid__": "241",
"__meta_process_exe": "/bin/bash",
"__meta_process_cwd": "/opt",
},
{
"__meta_kubernetes_pod_container_id": "docker://47e320f795efcec1ecf2001c3a09c95e3701ed87de8256837b70b10e23818251",
"qwe": "asd",
},
{
"lol": "lol",
},
},
},
}
for i, testdatum := range testdata {
t.Run(fmt.Sprintf("test %d", i), func(t *testing.T) {
res := join(testdatum.processes, testdatum.containers)
assert.Len(t, res, len(testdatum.res))
for _, re := range testdatum.res {
assert.Contains(t, res, re)
}
})
}
}
Loading