@@ -17,9 +17,11 @@ package othttp
17
17
import (
18
18
"io"
19
19
"net/http"
20
+ "time"
20
21
21
22
"go.opentelemetry.io/otel/api/global"
22
23
"go.opentelemetry.io/otel/api/kv"
24
+ "go.opentelemetry.io/otel/api/metric"
23
25
"go.opentelemetry.io/otel/api/propagation"
24
26
"go.opentelemetry.io/otel/api/standard"
25
27
"go.opentelemetry.io/otel/api/trace"
@@ -36,12 +38,15 @@ type Handler struct {
36
38
handler http.Handler
37
39
38
40
tracer trace.Tracer
41
+ meter metric.Meter
39
42
propagators propagation.Propagators
40
43
spanStartOptions []trace.StartOption
41
44
readEvent bool
42
45
writeEvent bool
43
46
filters []Filter
44
47
spanNameFormatter func (string , * http.Request ) string
48
+ counters map [string ]metric.Int64Counter
49
+ valueRecorders map [string ]metric.Int64ValueRecorder
45
50
}
46
51
47
52
func defaultHandlerFormatter (operation string , _ * http.Request ) string {
@@ -56,21 +61,26 @@ func NewHandler(handler http.Handler, operation string, opts ...Option) http.Han
56
61
operation : operation ,
57
62
}
58
63
64
+ const domain = "go.opentelemetry.io/otel/instrumentation/othttp"
65
+
59
66
defaultOpts := []Option {
60
- WithTracer (global .Tracer ("go.opentelemetry.io/otel/instrumentation/othttp" )),
67
+ WithTracer (global .Tracer (domain )),
68
+ WithMeter (global .Meter (domain )),
61
69
WithPropagators (global .Propagators ()),
62
70
WithSpanOptions (trace .WithSpanKind (trace .SpanKindServer )),
63
71
WithSpanNameFormatter (defaultHandlerFormatter ),
64
72
}
65
73
66
74
c := NewConfig (append (defaultOpts , opts ... )... )
67
75
h .configure (c )
76
+ h .createMeasures ()
68
77
69
78
return & h
70
79
}
71
80
72
81
func (h * Handler ) configure (c * Config ) {
73
82
h .tracer = c .Tracer
83
+ h .meter = c .Meter
74
84
h .propagators = c .Propagators
75
85
h .spanStartOptions = c .SpanStartOptions
76
86
h .readEvent = c .ReadEvent
@@ -79,8 +89,33 @@ func (h *Handler) configure(c *Config) {
79
89
h .spanNameFormatter = c .SpanNameFormatter
80
90
}
81
91
92
+ func handleErr (err error ) {
93
+ if err != nil {
94
+ global .Handle (err )
95
+ }
96
+ }
97
+
98
+ func (h * Handler ) createMeasures () {
99
+ h .counters = make (map [string ]metric.Int64Counter )
100
+ h .valueRecorders = make (map [string ]metric.Int64ValueRecorder )
101
+
102
+ requestBytesCounter , err := h .meter .NewInt64Counter (RequestContentLength )
103
+ handleErr (err )
104
+
105
+ responseBytesCounter , err := h .meter .NewInt64Counter (ResponseContentLength )
106
+ handleErr (err )
107
+
108
+ serverLatencyMeasure , err := h .meter .NewInt64ValueRecorder (ServerLatency )
109
+ handleErr (err )
110
+
111
+ h .counters [RequestContentLength ] = requestBytesCounter
112
+ h .counters [ResponseContentLength ] = responseBytesCounter
113
+ h .valueRecorders [ServerLatency ] = serverLatencyMeasure
114
+ }
115
+
82
116
// ServeHTTP serves HTTP requests (http.Handler)
83
117
func (h * Handler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
118
+ requestStartTime := time .Now ()
84
119
for _ , f := range h .filters {
85
120
if ! f (r ) {
86
121
// Simply pass through to the handler if a filter rejects the request
@@ -121,6 +156,17 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
121
156
122
157
setAfterServeAttributes (span , bw .read , rww .written , rww .statusCode , bw .err , rww .err )
123
158
span .SetStatus (standard .SpanStatusFromHTTPStatusCode (rww .statusCode ))
159
+
160
+ // Add request metrics
161
+
162
+ labels := standard .HTTPServerMetricAttributesFromHTTPRequest (h .operation , r )
163
+
164
+ h .counters [RequestContentLength ].Add (ctx , bw .read , labels ... )
165
+ h .counters [ResponseContentLength ].Add (ctx , rww .written , labels ... )
166
+
167
+ elapsedTime := time .Since (requestStartTime ).Microseconds ()
168
+
169
+ h .valueRecorders [ServerLatency ].Record (ctx , elapsedTime , labels ... )
124
170
}
125
171
126
172
func setAfterServeAttributes (span trace.Span , read , wrote int64 , statusCode int , rerr , werr error ) {
0 commit comments