process.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package containers
  2. import (
  3. "context"
  4. "os"
  5. "time"
  6. "github.com/jpillora/backoff"
  7. "github.com/cilium/ebpf/link"
  8. "github.com/coroot/coroot-node-agent/proc"
  9. "github.com/mdlayher/taskstats"
  10. )
  11. type Process struct {
  12. Pid uint32
  13. StartedAt time.Time
  14. NetNsId string
  15. ctx context.Context
  16. cancelFunc context.CancelFunc
  17. dotNetMonitor *DotNetMonitor
  18. uprobes []link.Link
  19. goTlsUprobesChecked bool
  20. openSslUprobesChecked bool
  21. jvmUprobesChecked bool
  22. }
  23. func NewProcess(pid uint32, stats *taskstats.Stats) *Process {
  24. ns, err := proc.GetNetNs(pid)
  25. if err != nil {
  26. return nil
  27. }
  28. defer ns.Close()
  29. p := &Process{Pid: pid, StartedAt: stats.BeginTime, NetNsId: ns.UniqueId()}
  30. p.ctx, p.cancelFunc = context.WithCancel(context.Background())
  31. go p.instrument()
  32. return p
  33. }
  34. func (p *Process) isHostNs() bool {
  35. return p.NetNsId == hostNetNsId
  36. }
  37. func (p *Process) instrument() {
  38. b := backoff.Backoff{Factor: 2, Min: time.Second, Max: time.Minute}
  39. for {
  40. select {
  41. case <-p.ctx.Done():
  42. return
  43. default:
  44. dest, err := os.Readlink(proc.Path(p.Pid, "exe"))
  45. if err != nil {
  46. return
  47. }
  48. if dest != "/" {
  49. if dotNetAppName, err := dotNetApp(p.Pid); err == nil {
  50. if dotNetAppName != "" {
  51. p.dotNetMonitor = NewDotNetMonitor(p.ctx, p.Pid, dotNetAppName)
  52. }
  53. return
  54. }
  55. }
  56. time.Sleep(b.Duration())
  57. }
  58. }
  59. }
  60. func (p *Process) Close() {
  61. p.cancelFunc()
  62. for _, u := range p.uprobes {
  63. _ = u.Close()
  64. }
  65. }