memcached.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package tracing
  2. import (
  3. "bytes"
  4. "github.com/coroot/coroot-node-agent/ebpftracer"
  5. "go.opentelemetry.io/otel/attribute"
  6. "go.opentelemetry.io/otel/codes"
  7. semconv "go.opentelemetry.io/otel/semconv/v1.18.0"
  8. "go.opentelemetry.io/otel/trace"
  9. "strings"
  10. "time"
  11. )
  12. const (
  13. MemcacheDBItemKeyName attribute.Key = "db.memcached.item"
  14. )
  15. func handleMemcachedQuery(start, end time.Time, r *ebpftracer.L7Request, attrs []attribute.KeyValue) {
  16. cmd, items := parseMemcached(r.Payload[:])
  17. if cmd == "" {
  18. return
  19. }
  20. _, span := tracer.Start(nil, cmd, trace.WithTimestamp(start), trace.WithSpanKind(trace.SpanKindClient))
  21. if len(items) == 1 {
  22. attrs = append(attrs, MemcacheDBItemKeyName.String(items[0]))
  23. } else if len(items) > 1 {
  24. attrs = append(attrs, MemcacheDBItemKeyName.StringSlice(items))
  25. }
  26. span.SetAttributes(append(attrs, semconv.DBSystemMemcached, semconv.DBOperation(cmd))...)
  27. if r.Status == 500 {
  28. span.SetStatus(codes.Error, "")
  29. }
  30. span.End(trace.WithTimestamp(end))
  31. }
  32. func parseMemcached(payload []byte) (string, []string) {
  33. cmd, rest, ok := bytes.Cut(payload, space)
  34. if !ok {
  35. return "", nil
  36. }
  37. command := string(cmd)
  38. switch command {
  39. case "set", "add", "cas", "append", "prepend", "replace", "delete", "incr", "decr", "touch":
  40. if key, _, ok := bytes.Cut(rest, space); ok {
  41. return command, []string{string(key)}
  42. }
  43. case "gat", "gats":
  44. _, rest, ok = bytes.Cut(rest, space)
  45. if ok {
  46. keys, _, ok := bytes.Cut(rest, crlf)
  47. if ok {
  48. return command, strings.Split(string(keys), " ")
  49. }
  50. }
  51. case "get", "gets":
  52. keys, _, ok := bytes.Cut(rest, crlf)
  53. if ok {
  54. return command, strings.Split(string(keys), " ")
  55. }
  56. }
  57. return "", nil
  58. }