| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- package containers
- import (
- "bytes"
- "context"
- "fmt"
- "github.com/coroot/coroot-node-agent/ebpftracer/tracer/jattach"
- "github.com/coroot/coroot-node-agent/utils"
- . "github.com/coroot/coroot-node-agent/utils/modelse"
- "os"
- "path/filepath"
- "strings"
- "time"
- "github.com/cilium/ebpf/link"
- "github.com/coroot/coroot-node-agent/ebpftracer"
- "github.com/coroot/coroot-node-agent/proc"
- "github.com/jpillora/backoff"
- "github.com/mdlayher/taskstats"
- )
- type Process struct {
- Pid uint32
- StartedAt time.Time
- netNsId string
- ctx context.Context
- cancelFunc context.CancelFunc
- dotNetMonitor *DotNetMonitor
- isGolangApp bool
- uprobes []link.Link
- stackUprobes []link.Link
- goTlsUprobesChecked bool
- openSslUprobesChecked bool
- jvmAttachOnce bool
- stackAttachOnce bool
- stackStatus StackStatus
- versionFailed bool
- codeType CodeType
- cmdline string
- pythonGilChecked bool
- }
- func NewProcess(pid uint32, stats *taskstats.Stats, tracer *ebpftracer.Tracer) *Process {
- p := &Process{Pid: pid, StartedAt: stats.BeginTime}
- p.ctx, p.cancelFunc = context.WithCancel(context.Background())
- go p.instrument(tracer)
- return p
- }
- func (p *Process) NetNsId() string {
- if p.netNsId == "" {
- ns, err := proc.GetNetNs(p.Pid)
- if err != nil {
- return ""
- }
- p.netNsId = ns.UniqueId()
- _ = ns.Close()
- }
- return p.netNsId
- }
- func (p *Process) isHostNs() bool {
- return p.NetNsId() == hostNetNsId
- }
- func (p *Process) instrument(tracer *ebpftracer.Tracer) {
- b := backoff.Backoff{Factor: 2, Min: time.Second, Max: time.Minute}
- for {
- select {
- case <-p.ctx.Done():
- return
- default:
- dest, err := os.Readlink(proc.Path(p.Pid, "exe"))
- if err != nil {
- return
- }
- if dest != "/" {
- p.instrumentPython(tracer)
- if dotNetAppName, err := dotNetApp(p.Pid); err == nil {
- if dotNetAppName != "" {
- p.dotNetMonitor = NewDotNetMonitor(p.ctx, p.Pid, dotNetAppName)
- }
- }
- return
- }
- time.Sleep(b.Duration())
- }
- }
- }
- func (p *Process) instrumentPython(tracer *ebpftracer.Tracer) {
- if p.pythonGilChecked {
- return
- }
- p.pythonGilChecked = true
- cmdline := proc.GetCmdline(p.Pid)
- if len(cmdline) == 0 {
- return
- }
- parts := bytes.Split(cmdline, []byte{0})
- cmd := parts[0]
- if len(cmd) == 0 {
- return
- }
- cmd = bytes.TrimSuffix(bytes.Fields(cmd)[0], []byte{':'})
- if !pythonCmd.Match(cmd) {
- return
- }
- p.uprobes = append(p.uprobes, tracer.AttachPythonThreadLockProbes(p.Pid)...)
- }
- func (p *Process) Close() {
- p.cancelFunc()
- for _, u := range p.uprobes {
- _ = u.Close()
- }
- }
- func (p *Process) closeStackUprobes() error {
- for _, u := range p.stackUprobes {
- err := u.Close()
- if err != nil {
- return err
- }
- }
- p.stackUprobes = []link.Link{}
- p.stackStatus.StackUprobesClose()
- return nil
- }
- func (p *Process) DynamicClose(closeType int) {
- for _, u := range p.uprobes {
- _ = u.Close()
- }
- //p.goTlsUprobesChecked = false
- //p.openSslUprobesChecked = false
- //p.jvmUprobesChecked = false
- //if p.codeType.IsJvmCode() && p.stackUprobesChecked {
- // nativeBasePath := utils.GetDefaultAgentsPath("NativeAgent")
- // kvPairs := []string{
- // fmt.Sprintf("%s=%s", filepath.Join(nativeBasePath, "lib", "apmAgent.jar"), nativeBasePath),
- // "UNINSTALL",
- // }
- // argkv := strings.Join(kvPairs, ",")
- // args := []string{"load", "instrument", "false", argkv}
- // jattacher := jattach.JvmJattacher{
- // Pid: p.Pid,
- // Args: args,
- // PrintOutput: 1,
- // }
- // _, err := jattacher.JDetach()
- // if err == nil {
- // //p.stackUprobesChecked = false
- // }
- //}
- p.uprobes = []link.Link{}
- }
- func (p *Process) uninstallJavaAgent() error {
- if p.codeType.IsJvmCode() && p.stackAttachOnce {
- nativeBasePath := utils.GetDefaultAgentsPath("NativeAgent")
- kvPairs := []string{
- fmt.Sprintf("%s=%s", filepath.Join(nativeBasePath, "lib", "apmAgent.jar"), nativeBasePath),
- "UNINSTALL",
- }
- argkv := strings.Join(kvPairs, ",")
- args := []string{"load", "instrument", "false", argkv}
- jattacher := jattach.JvmJattacher{
- Pid: p.Pid,
- Args: args,
- PrintOutput: 1,
- }
- _, err := jattacher.JDetach()
- if err != nil {
- return err
- }
- p.stackStatus.JattachClose()
- return nil
- }
- return nil
- }
- func (p *Process) GetCmdline() string {
- return p.cmdline
- }
|