Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/mocks/metrics/Recorder.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions internal/mocks/middleware/Reporter.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
// HTTPReqProperties are the metric properties for the metrics based
// on client request.
type HTTPReqProperties struct {
URI []byte
// Service is the service that has served the request.
Service string
// ID is the id of the request handler.
Expand All @@ -30,6 +31,7 @@ type HTTPProperties struct {
// Interface has the required methods to be used with the HTTP
// middlewares.
type Recorder interface {
ObserveHTTPRequestSize(ctx context.Context, props HTTPReqProperties, sizeBytes int64)
// ObserveHTTPRequestDuration measures the duration of an HTTP request.
ObserveHTTPRequestDuration(ctx context.Context, props HTTPReqProperties, duration time.Duration)
// ObserveHTTPResponseSize measures the size of an HTTP response in bytes.
Expand All @@ -44,6 +46,7 @@ const Dummy = dummy(0)

type dummy int

func (dummy) ObserveHTTPRequestSize(context.Context, HTTPReqProperties, int64) {} // end ObserveHTTPRequestSize()
func (dummy) ObserveHTTPRequestDuration(_ context.Context, _ HTTPReqProperties, _ time.Duration) {}
func (dummy) ObserveHTTPResponseSize(_ context.Context, _ HTTPReqProperties, _ int64) {}
func (dummy) AddInflightRequests(_ context.Context, _ HTTPProperties, _ int) {}
Expand Down
32 changes: 23 additions & 9 deletions metrics/opencensus/opencensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ type recorder struct {
serviceKey tag.Key

// Measures.
latencySecs *stats.Float64Measure
sizeBytes *stats.Int64Measure
inflightCount *stats.Int64Measure
latencySecs *stats.Float64Measure
requestSizeBytes *stats.Int64Measure
responseSizeBytes *stats.Int64Measure
inflightCount *stats.Int64Measure
}

// NewRecorder returns a new Recorder that uses OpenCensus stats
Expand Down Expand Up @@ -133,7 +134,8 @@ func (r *recorder) createMeasurements() {
"http_request_duration_seconds",
"The latency of the HTTP requests",
"s")
r.sizeBytes = stats.Int64(
r.requestSizeBytes = stats.Int64("http_request_size_bytes", "The size of the HTTP requests", stats.UnitBytes)
r.responseSizeBytes = stats.Int64(
"http_response_size_bytes",
"The size of the HTTP responses",
stats.UnitBytes)
Expand All @@ -153,11 +155,18 @@ func (r recorder) registerViews(cfg Config) error {
Measure: r.latencySecs,
Aggregation: view.Distribution(cfg.DurationBuckets...),
}
sizeView := &view.View{
reqSizeView := &view.View{
Name: r.requestSizeBytes.Name(),
Description: r.requestSizeBytes.Description(),
TagKeys: []tag.Key{r.serviceKey, r.handlerKey, r.methodKey, r.codeKey},
Measure: r.requestSizeBytes,
Aggregation: view.Distribution(cfg.SizeBuckets...),
}
repSizeView := &view.View{
Name: "http_response_size_bytes",
Description: "The size of the HTTP responses",
TagKeys: []tag.Key{r.serviceKey, r.handlerKey, r.methodKey, r.codeKey},
Measure: r.sizeBytes,
Measure: r.responseSizeBytes,
Aggregation: view.Distribution(cfg.SizeBuckets...),
}
inflightView := &view.View{
Expand All @@ -170,25 +179,30 @@ func (r recorder) registerViews(cfg Config) error {

// Do we need to unregister the same views before registering.
if cfg.UnregisterViewsBeforeRegister {
view.Unregister(durationView, sizeView, inflightView)
view.Unregister(durationView, reqSizeView, repSizeView, inflightView)
}

err := view.Register(durationView, sizeView, inflightView)
err := view.Register(durationView, reqSizeView, repSizeView, inflightView)
if err != nil {
return err
}

return nil
}

func (r recorder) ObserveHTTPRequestSize(ctx context.Context, p metrics.HTTPReqProperties, sizeBytes int64) {
ctx = r.ctxWithTagFromHTTPReqProperties(ctx, p)
stats.Record(ctx, r.requestSizeBytes.M(sizeBytes))
} // end ObserveHTTPRequestSize()

func (r recorder) ObserveHTTPRequestDuration(ctx context.Context, p metrics.HTTPReqProperties, duration time.Duration) {
ctx = r.ctxWithTagFromHTTPReqProperties(ctx, p)
stats.Record(ctx, r.latencySecs.M(duration.Seconds()))
}

func (r recorder) ObserveHTTPResponseSize(ctx context.Context, p metrics.HTTPReqProperties, sizeBytes int64) {
ctx = r.ctxWithTagFromHTTPReqProperties(ctx, p)
stats.Record(ctx, r.sizeBytes.M(sizeBytes))
stats.Record(ctx, r.responseSizeBytes.M(sizeBytes))
}

func (r recorder) AddInflightRequests(ctx context.Context, p metrics.HTTPProperties, quantity int) {
Expand Down
14 changes: 14 additions & 0 deletions metrics/prometheus/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func (c *Config) defaults() {

type recorder struct {
httpRequestDurHistogram *prometheus.HistogramVec
httpRequestSizeHistogram *prometheus.HistogramVec
httpResponseSizeHistogram *prometheus.HistogramVec
httpRequestsInflight *prometheus.GaugeVec
}
Expand All @@ -82,6 +83,14 @@ func NewRecorder(cfg Config) metrics.Recorder {
Buckets: cfg.DurationBuckets,
}, []string{cfg.ServiceLabel, cfg.HandlerIDLabel, cfg.MethodLabel, cfg.StatusCodeLabel}),

httpRequestSizeHistogram: prometheus.NewHistogramVec(prometheus.HistogramOpts{
Namespace: cfg.Prefix,
Subsystem: "http",
Name: "request_size_bytes",
Help: "The size of the HTTP requests.",
Buckets: cfg.SizeBuckets,
}, []string{cfg.ServiceLabel, cfg.HandlerIDLabel, cfg.MethodLabel, cfg.StatusCodeLabel}),

httpResponseSizeHistogram: prometheus.NewHistogramVec(prometheus.HistogramOpts{
Namespace: cfg.Prefix,
Subsystem: "http",
Expand All @@ -99,6 +108,7 @@ func NewRecorder(cfg Config) metrics.Recorder {
}

cfg.Registry.MustRegister(
r.httpRequestSizeHistogram,
r.httpRequestDurHistogram,
r.httpResponseSizeHistogram,
r.httpRequestsInflight,
Expand All @@ -107,6 +117,10 @@ func NewRecorder(cfg Config) metrics.Recorder {
return r
}

func (r recorder) ObserveHTTPRequestSize(_ context.Context, p metrics.HTTPReqProperties, sizeBytes int64) {
r.httpRequestSizeHistogram.WithLabelValues(p.Service, p.ID, p.Method, p.Code).Observe(float64(sizeBytes))
} // end ObserveHTTPRequestSize()

func (r recorder) ObserveHTTPRequestDuration(_ context.Context, p metrics.HTTPReqProperties, duration time.Duration) {
r.httpRequestDurHistogram.WithLabelValues(p.Service, p.ID, p.Method, p.Code).Observe(duration.Seconds())
}
Expand Down
11 changes: 11 additions & 0 deletions middleware/echo/echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ type reporter struct {
c echo.Context
}

func (r *reporter) URI() []byte {
u := r.c.Request().URL
if u != nil {
b, _ := u.MarshalBinary()
return b
} // end if
return nil
} // end URI()

func (r *reporter) BytesReceived() int64 { return r.c.Request().ContentLength } // end BytesReceived()

func (r *reporter) Method() string { return r.c.Request().Method }

func (r *reporter) Context() context.Context { return r.c.Request().Context() }
Expand Down
12 changes: 12 additions & 0 deletions middleware/fasthttp/fasthttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ type reporter struct {
c *fasthttp.RequestCtx
}

func (r reporter) URI() []byte {
uri := r.c.Request.URI()
if uri != nil {
return uri.FullURI()
} // end if
return nil
} // end URI()

func (r reporter) BytesReceived() int64 {
return int64(len(r.c.Request.Body()))
} // end BytesReceived()

func (r reporter) Method() string {
return string(r.c.Method())
}
Expand Down
10 changes: 10 additions & 0 deletions middleware/gin/gin.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ type reporter struct {
c *gin.Context
}

func (r *reporter) URI() []byte {
if r.c.Request.URL != nil {
b, _ := r.c.Request.URL.MarshalBinary()
return b
} // end if
return nil
} // end URI()

func (r *reporter) BytesReceived() int64 { return r.c.Request.ContentLength } // end BytesReceived()

func (r *reporter) Method() string { return r.c.Request.Method }

func (r *reporter) Context() context.Context { return r.c.Request.Context() }
Expand Down
10 changes: 10 additions & 0 deletions middleware/gorestful/gorestful.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ type reporter struct {
resp *gorestful.Response
}

func (r *reporter) URI() []byte {
if r.req.Request.URL != nil {
b, _ := r.req.Request.URL.MarshalBinary()
return b
} // end if
return nil
} // end URI()

func (r *reporter) BytesReceived() int64 { return r.req.Request.ContentLength } // end BytesReceived()

func (r *reporter) Method() string { return r.req.Request.Method }

func (r *reporter) Context() context.Context { return r.req.Request.Context() }
Expand Down
11 changes: 11 additions & 0 deletions middleware/iris/iris.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ type reporter struct {
ctx iris.Context
}

func (r *reporter) URI() []byte {
u := r.ctx.Request().URL
if u != nil {
b, _ := u.MarshalBinary()
return b
} // end if
return nil
} // end URI()

func (r *reporter) BytesReceived() int64 { return r.ctx.Request().ContentLength } // end BytesReceived()

func (r *reporter) Method() string { return r.ctx.Method() }

func (r *reporter) Context() context.Context { return r.ctx.Request().Context() }
Expand Down
17 changes: 10 additions & 7 deletions middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ func (m Middleware) Measure(handlerID string, reporter Reporter, next func()) {

// Start the timer and when finishing measure the duration.
start := time.Now()
props := metrics.HTTPReqProperties{
URI: reporter.URI(),
Service: m.service,
ID: hid,
Method: reporter.Method(),
}
defer func() {
_, shouldIgnore := m.ignoredPaths[reporter.URLPath()]
if shouldIgnore {
Expand All @@ -123,20 +129,15 @@ func (m Middleware) Measure(handlerID string, reporter Reporter, next func()) {
} else {
code = strconv.Itoa(reporter.StatusCode())
}

props := metrics.HTTPReqProperties{
Service: m.service,
ID: hid,
Method: reporter.Method(),
Code: code,
}
props.Code = code
m.recorder.ObserveHTTPRequestDuration(ctx, props, duration)

// Measure size of response if required.
if !m.disableMeasureSize {
m.recorder.ObserveHTTPResponseSize(ctx, props, reporter.BytesWritten())
}
}()
m.recorder.ObserveHTTPRequestSize(ctx, props, reporter.BytesReceived())

// Call the wrapped logic.
next()
Expand All @@ -145,9 +146,11 @@ func (m Middleware) Measure(handlerID string, reporter Reporter, next func()) {
// Reporter knows how to report the data to the Middleware so it can measure the
// different framework/libraries.
type Reporter interface {
URI() []byte
Method() string
Context() context.Context
URLPath() string
StatusCode() int
BytesReceived() int64
BytesWritten() int64
}
10 changes: 10 additions & 0 deletions middleware/std/std.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ type stdReporter struct {
r *http.Request
}

func (s *stdReporter) URI() []byte {
if s.r.URL != nil {
b, _ := s.r.URL.MarshalBinary()
return b
} // end if
return nil
} // end URI()

func (s *stdReporter) BytesReceived() int64 { return s.r.ContentLength } // end BytesReceived()

func (s *stdReporter) Method() string { return s.r.Method }

func (s *stdReporter) Context() context.Context { return s.r.Context() }
Expand Down