observe_server_duration.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package metrics
  2. import (
  3. "context"
  4. "go-admin/app/observe/models/query"
  5. "go-admin/common/opentelemetry"
  6. "strings"
  7. "sync"
  8. log "github.com/go-admin-team/go-admin-core/logger"
  9. "github.com/go-admin-team/go-admin-core/sdk/config"
  10. "go.opentelemetry.io/collector/pdata/pcommon"
  11. "go.opentelemetry.io/collector/pdata/ptrace"
  12. conventions "go.opentelemetry.io/collector/semconv/v1.18.0"
  13. "go.opentelemetry.io/otel"
  14. "go.opentelemetry.io/otel/attribute"
  15. "go.opentelemetry.io/otel/metric"
  16. )
  17. type ObserveServerDuration struct{ metric.Float64Histogram }
  18. func NewObserveServerDuration(name string) ObserveServerDuration {
  19. provider := otel.GetMeterProvider()
  20. meter := provider.Meter("observe.consumer.metrics")
  21. if h, err := meter.Float64Histogram(
  22. "observe.server.duration",
  23. metric.WithDescription("observe服务端处理时延统计"),
  24. metric.WithUnit("ms"),
  25. ); err != nil {
  26. panic(err)
  27. } else {
  28. return ObserveServerDuration{h}
  29. }
  30. }
  31. func (h ObserveServerDuration) Record(wg *sync.WaitGroup, ch <-chan struct{}, span ptrace.Span, resource pcommon.Resource) {
  32. defer wg.Done()
  33. defer func() {
  34. <-ch
  35. }()
  36. if span.Kind() != ptrace.SpanKindServer {
  37. return
  38. }
  39. resAttrs := opentelemetry.NewResourceAttributes(&resource)
  40. spanAttrs := opentelemetry.NewSpanAttributesWithRaw(span.Attributes())
  41. appAlias, _ := resAttrs.AppName()
  42. if appAlias == "UNSET" && config.ApplicationConfig.Mode == "prod" { // 为了降低数据量, 客户生产暂时不再捕获未设置AppAlias的数据
  43. return
  44. }
  45. duration := span.EndTimestamp().AsTime().Sub(span.StartTimestamp().AsTime()).Milliseconds()
  46. appId, err := query.NewApp().Alias2ID(appAlias)
  47. if err != nil || appId == 0 {
  48. log.Errorf("获取appId失败: %s %s", appAlias, err)
  49. return
  50. }
  51. serviceName, ok := resource.Attributes().Get(conventions.AttributeServiceName)
  52. if !ok {
  53. log.Errorf("获取service name失败: %s %s", appAlias, span.SpanID().String())
  54. return
  55. }
  56. urlMappingQuery := query.NewUrlMapping()
  57. // kind, err := urlMappingQuery.UrlToKindCache(appId, spanAttrs.HttpRoute())
  58. // if err != nil {
  59. // log.Errorf("获取url kind失败: %s %s", appAlias, err)
  60. // return
  61. // }
  62. t, err := urlMappingQuery.UrlToTypeFast(appId, spanAttrs.HttpRoute())
  63. if err != nil {
  64. log.Errorf("获取url type失败: %s %s", appAlias, err)
  65. return
  66. }
  67. // fmt.Println(appId, appAlias, serviceName.AsString(), kind, t, spanAttrs.HttpRoute(), spanAttrs.StatusCode(), span.Status().Code().String())
  68. arr := strings.Split(spanAttrs.HttpRoute(), "/")
  69. h.Float64Histogram.Record(context.Background(), float64(duration), metric.WithAttributes(
  70. attribute.Int64("app.id", appId),
  71. attribute.String("app.alias", appAlias),
  72. attribute.String("service.name", serviceName.AsString()),
  73. // attribute.String("url.kind", kind),
  74. attribute.Int("url.type", t),
  75. attribute.String("url.method", spanAttrs.HttpMethod()),
  76. attribute.String("url.prefix", spanAttrs.HttpRoute()),
  77. attribute.Int("url.level", len(arr)-1),
  78. attribute.Int("url.is_perfect_match", 1),
  79. attribute.Int("status_code", int(spanAttrs.StatusCode())),
  80. attribute.Bool("error", spanAttrs.StatusCode() >= 400 || span.Status().Code().String() == "Error"),
  81. ))
  82. for len(arr) > 1 {
  83. arr = arr[:len(arr)-1]
  84. subroute := strings.Join(arr, "/")
  85. if subroute == "" {
  86. subroute = "/"
  87. }
  88. h.Float64Histogram.Record(context.Background(), float64(duration), metric.WithAttributes(
  89. attribute.Int64("app.id", appId),
  90. attribute.String("app.alias", appAlias),
  91. attribute.String("service.name", serviceName.AsString()),
  92. // attribute.String("url.kind", kind),
  93. attribute.Int("url.type", t),
  94. attribute.String("url.method", spanAttrs.HttpMethod()),
  95. attribute.String("url.prefix", subroute),
  96. attribute.Int("url.level", len(arr)-1),
  97. attribute.Int("url.is_perfect_match", 0),
  98. attribute.Int("status_code", int(spanAttrs.StatusCode())),
  99. attribute.Bool("error", spanAttrs.StatusCode() >= 400 || span.Status().Code().String() == "Error"),
  100. ))
  101. }
  102. }