forked from open-telemetry/opentelemetry-go-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample_test.go
More file actions
154 lines (127 loc) · 4.24 KB
/
example_test.go
File metadata and controls
154 lines (127 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package otelecho_test
import (
"errors"
"io"
"log"
"net/http"
"github.com/labstack/echo/v4"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho"
)
func ExampleMiddleware() {
/* curl -v -d "a painting" http://localhost:7777/hello/bob/ross
...
* upload completely sent off: 10 out of 10 bytes
< HTTP/1.1 200 OK
< Traceparent: 00-76ae040ee5753f38edf1c2bd9bd128bd-dd394138cfd7a3dc-01
< Date: Fri, 04 Oct 2019 02:33:08 GMT
< Content-Length: 45
< Content-Type: text/plain; charset=utf-8
<
Hello, bob/ross!
You sent me this:
a painting
*/
// Create a new Echo instance
e := echo.New()
// Use the otelecho middleware with options
e.Use(otelecho.Middleware("server",
otelecho.WithSkipper(func(c echo.Context) bool {
// Skip tracing for health check endpoints
return c.Path() == "/health"
}),
))
// Define a route with a handler that demonstrates tracing
e.POST("/hello/:name", func(c echo.Context) error {
ctx := c.Request().Context()
// Get the current span from context
span := trace.SpanFromContext(ctx)
// Create a child span for processing the name
ctx, nameSpan := span.TracerProvider().Tracer("exampleTracer").Start(ctx, "processName")
// Get the name parameter using Echo's built-in functionality
name := c.Param("name")
// Add the name as a span attribute
nameSpan.SetAttributes(attribute.String("name", name))
nameSpan.End()
// Read the request body
d, err := io.ReadAll(c.Request().Body)
if err != nil {
log.Println("error reading body: ", err)
// Record the error in the span and set its status
span.SetStatus(codes.Error, "failed to read request body")
return c.String(http.StatusBadRequest, "Bad request")
}
// Create another child span for processing the response
_, responseSpan := span.TracerProvider().Tracer("exampleTracer").Start(ctx, "createResponse")
// Create the response
response := "Hello, " + name + "!\nYou sent me this:\n" + string(d)
// Add information about the response size
responseSpan.SetAttributes(attribute.Int("response.size", len(response)))
responseSpan.End()
// Set the status of the main span to OK
span.SetStatus(codes.Ok, "")
return c.String(http.StatusOK, response)
})
// Add a health check endpoint that will be skipped by the tracer
e.GET("/health", func(c echo.Context) error {
return c.String(http.StatusOK, "OK")
})
// Start the server
err := e.Start(":7777")
if !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
func ExampleMiddleware_withMetrics() {
// This example shows how to use the otelecho middleware with custom metrics attributes
// The middleware will automatically collect HTTP server metrics including:
// - http.server.request.duration
// - http.server.request.body.size
// - http.server.response.body.size
// Create a new Echo instance
e := echo.New()
// Use the otelecho middleware with metrics and custom attributes
e.Use(otelecho.Middleware("api-server",
otelecho.WithMetricAttributeFn(func(r *http.Request) []attribute.KeyValue {
// Add custom attributes from HTTP request
return []attribute.KeyValue{
attribute.String("client.ip", r.RemoteAddr),
attribute.String("user.agent", r.UserAgent()),
}
}),
otelecho.WithEchoMetricAttributeFn(func(c echo.Context) []attribute.KeyValue {
// Add custom attributes from Echo context
return []attribute.KeyValue{
attribute.String("handler.path", c.Path()),
attribute.String("handler.method", c.Request().Method),
}
}),
))
// Define routes
e.GET("/api/users/:id", func(c echo.Context) error {
userID := c.Param("id")
return c.JSON(http.StatusOK, map[string]any{
"id": userID,
"name": "User " + userID,
})
})
e.POST("/api/users", func(c echo.Context) error {
var user struct {
Name string `json:"name"`
Email string `json:"email"`
}
if err := c.Bind(&user); err != nil {
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request"})
}
return c.JSON(http.StatusCreated, map[string]any{
"id": "12345",
"name": user.Name,
"email": user.Email,
})
})
// Output:
}