tracehandler_test.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. package handler
  2. import (
  3. "context"
  4. "io"
  5. "net/http"
  6. "net/http/httptest"
  7. "strconv"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. ztrace "github.com/wuntsong-org/go-zero-plus/core/trace"
  11. "github.com/wuntsong-org/go-zero-plus/core/trace/tracetest"
  12. "github.com/wuntsong-org/go-zero-plus/rest/chain"
  13. "go.opentelemetry.io/otel"
  14. tcodes "go.opentelemetry.io/otel/codes"
  15. "go.opentelemetry.io/otel/propagation"
  16. sdktrace "go.opentelemetry.io/otel/sdk/trace"
  17. "go.opentelemetry.io/otel/trace"
  18. )
  19. func TestOtelHandler(t *testing.T) {
  20. ztrace.StartAgent(ztrace.Config{
  21. Name: "go-zero-test",
  22. Endpoint: "http://localhost:14268/api/traces",
  23. Batcher: "jaeger",
  24. Sampler: 1.0,
  25. })
  26. defer ztrace.StopAgent()
  27. for _, test := range []string{"", "bar"} {
  28. t.Run(test, func(t *testing.T) {
  29. h := chain.New(TraceHandler("foo", test)).Then(
  30. http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  31. span := trace.SpanFromContext(r.Context())
  32. assert.True(t, span.SpanContext().IsValid())
  33. assert.True(t, span.IsRecording())
  34. }))
  35. ts := httptest.NewServer(h)
  36. defer ts.Close()
  37. client := ts.Client()
  38. err := func(ctx context.Context) error {
  39. ctx, span := otel.Tracer("httptrace/client").Start(ctx, "test")
  40. defer span.End()
  41. req, _ := http.NewRequest("GET", ts.URL, nil)
  42. otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
  43. res, err := client.Do(req)
  44. assert.Nil(t, err)
  45. return res.Body.Close()
  46. }(context.Background())
  47. assert.Nil(t, err)
  48. })
  49. }
  50. }
  51. func TestTraceHandler(t *testing.T) {
  52. me := tracetest.NewInMemoryExporter(t)
  53. h := chain.New(TraceHandler("foo", "/")).Then(
  54. http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
  55. ts := httptest.NewServer(h)
  56. defer ts.Close()
  57. client := ts.Client()
  58. err := func(ctx context.Context) error {
  59. req, _ := http.NewRequest("GET", ts.URL, nil)
  60. res, err := client.Do(req)
  61. assert.Nil(t, err)
  62. return res.Body.Close()
  63. }(context.Background())
  64. assert.NoError(t, err)
  65. assert.Equal(t, 1, len(me.GetSpans()))
  66. span := me.GetSpans()[0].Snapshot()
  67. assert.Equal(t, sdktrace.Status{
  68. Code: tcodes.Unset,
  69. }, span.Status())
  70. assert.Equal(t, 0, len(span.Events()))
  71. assert.Equal(t, 9, len(span.Attributes()))
  72. }
  73. func TestDontTracingSpan(t *testing.T) {
  74. ztrace.StartAgent(ztrace.Config{
  75. Name: "go-zero-test",
  76. Endpoint: "http://localhost:14268/api/traces",
  77. Batcher: "jaeger",
  78. Sampler: 1.0,
  79. })
  80. defer ztrace.StopAgent()
  81. for _, test := range []string{"", "bar", "foo"} {
  82. t.Run(test, func(t *testing.T) {
  83. h := chain.New(TraceHandler("foo", test, WithTraceIgnorePaths([]string{"bar"}))).Then(
  84. http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  85. span := trace.SpanFromContext(r.Context())
  86. spanCtx := span.SpanContext()
  87. if test == "bar" {
  88. assert.False(t, spanCtx.IsValid())
  89. assert.False(t, span.IsRecording())
  90. return
  91. }
  92. assert.True(t, span.IsRecording())
  93. assert.True(t, spanCtx.IsValid())
  94. }))
  95. ts := httptest.NewServer(h)
  96. defer ts.Close()
  97. client := ts.Client()
  98. err := func(ctx context.Context) error {
  99. ctx, span := otel.Tracer("httptrace/client").Start(ctx, "test")
  100. defer span.End()
  101. req, _ := http.NewRequest("GET", ts.URL, nil)
  102. otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
  103. res, err := client.Do(req)
  104. assert.Nil(t, err)
  105. return res.Body.Close()
  106. }(context.Background())
  107. assert.Nil(t, err)
  108. })
  109. }
  110. }
  111. func TestTraceResponseWriter(t *testing.T) {
  112. ztrace.StartAgent(ztrace.Config{
  113. Name: "go-zero-test",
  114. Endpoint: "http://localhost:14268/api/traces",
  115. Batcher: "jaeger",
  116. Sampler: 1.0,
  117. })
  118. defer ztrace.StopAgent()
  119. for _, test := range []int{0, 200, 300, 400, 401, 500, 503} {
  120. t.Run(strconv.Itoa(test), func(t *testing.T) {
  121. h := chain.New(TraceHandler("foo", "bar")).Then(
  122. http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  123. span := trace.SpanFromContext(r.Context())
  124. spanCtx := span.SpanContext()
  125. assert.True(t, span.IsRecording())
  126. assert.True(t, spanCtx.IsValid())
  127. if test != 0 {
  128. w.WriteHeader(test)
  129. }
  130. w.Write([]byte("hello"))
  131. }))
  132. ts := httptest.NewServer(h)
  133. defer ts.Close()
  134. client := ts.Client()
  135. err := func(ctx context.Context) error {
  136. ctx, span := otel.Tracer("httptrace/client").Start(ctx, "test")
  137. defer span.End()
  138. req, _ := http.NewRequest("GET", ts.URL, nil)
  139. otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
  140. res, err := client.Do(req)
  141. assert.Nil(t, err)
  142. resBody := make([]byte, 5)
  143. _, err = res.Body.Read(resBody)
  144. assert.Equal(t, io.EOF, err)
  145. assert.Equal(t, []byte("hello"), resBody, "response body fail")
  146. return res.Body.Close()
  147. }(context.Background())
  148. assert.Nil(t, err)
  149. })
  150. }
  151. }