diff --git a/examples/shipping/booking/instrumenting.go b/examples/shipping/booking/instrumenting.go new file mode 100644 index 0000000..3b95d7a --- /dev/null +++ b/examples/shipping/booking/instrumenting.go @@ -0,0 +1,114 @@ +package booking + +import ( + "time" + + stdprometheus "github.com/prometheus/client_golang/prometheus" + + "github.com/go-kit/kit/metrics" + kitprometheus "github.com/go-kit/kit/metrics/prometheus" + + "github.com/go-kit/kit/examples/shipping/cargo" + "github.com/go-kit/kit/examples/shipping/location" +) + +type instrumentingService struct { + requestCount metrics.Counter + requestLatency metrics.TimeHistogram + Service +} + +// NewInstrumentingService returns an instance of an instrumenting Service. +func NewInstrumentingService(s Service) Service { + fieldKeys := []string{"method"} + + requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{ + Namespace: "api", + Subsystem: "booking_service", + Name: "request_count", + Help: "Number of requests received.", + }, fieldKeys) + + requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{ + Namespace: "api", + Subsystem: "booking_service", + Name: "request_latency_microseconds", + Help: "Total duration of requests in microseconds.", + }, fieldKeys)) + + return &instrumentingService{ + requestCount: requestCount, + requestLatency: requestLatency, + Service: s, + } +} + +func (s *instrumentingService) BookNewCargo(origin, destination location.UNLocode, arrivalDeadline time.Time) (cargo.TrackingID, error) { + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "book"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.BookNewCargo(origin, destination, arrivalDeadline) +} + +func (s *instrumentingService) LoadCargo(id cargo.TrackingID) (c Cargo, err error) { + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "load"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.LoadCargo(id) +} + +func (s *instrumentingService) RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary { + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "request_routes"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.RequestPossibleRoutesForCargo(id) +} + +func (s *instrumentingService) AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) (err error) { + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "assign_to_route"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.AssignCargoToRoute(id, itinerary) +} + +func (s *instrumentingService) ChangeDestination(id cargo.TrackingID, l location.UNLocode) (err error) { + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "change_destination"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.ChangeDestination(id, l) +} + +func (s *instrumentingService) Cargos() []Cargo { + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "list_cargos"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.Cargos() +} + +func (s *instrumentingService) Locations() []Location { + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "list_locations"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.Locations() +} diff --git a/examples/shipping/handling/instrumenting.go b/examples/shipping/handling/instrumenting.go new file mode 100644 index 0000000..1f99904 --- /dev/null +++ b/examples/shipping/handling/instrumenting.go @@ -0,0 +1,56 @@ +package handling + +import ( + "time" + + "github.com/go-kit/kit/metrics" + kitprometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" + + "github.com/go-kit/kit/examples/shipping/cargo" + "github.com/go-kit/kit/examples/shipping/location" + "github.com/go-kit/kit/examples/shipping/voyage" +) + +type instrumentingService struct { + requestCount metrics.Counter + requestLatency metrics.TimeHistogram + Service +} + +// NewInstrumentingService returns an instance of an instrumenting Service. +func NewInstrumentingService(s Service) Service { + fieldKeys := []string{"method"} + + requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{ + Namespace: "api", + Subsystem: "handling_service", + Name: "request_count", + Help: "Number of requests received.", + }, fieldKeys) + + requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{ + Namespace: "api", + Subsystem: "handling_service", + Name: "request_latency_microseconds", + Help: "Total duration of requests in microseconds.", + }, fieldKeys)) + + return &instrumentingService{ + requestCount: requestCount, + requestLatency: requestLatency, + Service: s, + } +} + +func (s *instrumentingService) RegisterHandlingEvent(completionTime time.Time, trackingID cargo.TrackingID, voyage voyage.Number, + loc location.UNLocode, eventType cargo.HandlingEventType) error { + + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "register_incident"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.RegisterHandlingEvent(completionTime, trackingID, voyage, loc, eventType) +} diff --git a/examples/shipping/main.go b/examples/shipping/main.go index cd4e624..5d8807f 100644 --- a/examples/shipping/main.go +++ b/examples/shipping/main.go @@ -11,6 +11,7 @@ import ( "time" "github.com/go-kit/kit/log" + stdprometheus "github.com/prometheus/client_golang/prometheus" "golang.org/x/net/context" "github.com/go-kit/kit/examples/shipping/booking" @@ -74,14 +75,17 @@ func main() { var bs booking.Service bs = booking.NewService(cargos, locations, handlingEvents, rs) bs = booking.NewLoggingService(log.NewContext(logger).With("component", "booking"), bs) + bs = booking.NewInstrumentingService(bs) var ts tracking.Service ts = tracking.NewService(cargos, handlingEvents) ts = tracking.NewLoggingService(log.NewContext(logger).With("component", "tracking"), ts) + ts = tracking.NewInstrumentingService(ts) var hs handling.Service hs = handling.NewService(handlingEvents, handlingEventFactory, handlingEventHandler) hs = handling.NewLoggingService(log.NewContext(logger).With("component", "handling"), hs) + hs = handling.NewInstrumentingService(hs) httpLogger := log.NewContext(logger).With("component", "http") @@ -92,6 +96,7 @@ func main() { mux.Handle("/handling/v1/", handling.MakeHandler(ctx, hs, httpLogger)) http.Handle("/", accessControl(mux)) + http.Handle("/metrics", stdprometheus.Handler()) errs := make(chan error, 2) go func() { diff --git a/examples/shipping/tracking/instrumenting.go b/examples/shipping/tracking/instrumenting.go new file mode 100644 index 0000000..a5f4db2 --- /dev/null +++ b/examples/shipping/tracking/instrumenting.go @@ -0,0 +1,51 @@ +package tracking + +import ( + "time" + + stdprometheus "github.com/prometheus/client_golang/prometheus" + + "github.com/go-kit/kit/metrics" + kitprometheus "github.com/go-kit/kit/metrics/prometheus" +) + +type instrumentingService struct { + requestCount metrics.Counter + requestLatency metrics.TimeHistogram + Service +} + +// NewInstrumentingService returns an instance of an instrumenting Service. +func NewInstrumentingService(s Service) Service { + fieldKeys := []string{"method"} + + requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{ + Namespace: "api", + Subsystem: "tracking_service", + Name: "request_count", + Help: "Number of requests received.", + }, fieldKeys) + + requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{ + Namespace: "api", + Subsystem: "tracking_service", + Name: "request_latency_microseconds", + Help: "Total duration of requests in microseconds.", + }, fieldKeys)) + + return &instrumentingService{ + requestCount: requestCount, + requestLatency: requestLatency, + Service: s, + } +} + +func (s *instrumentingService) Track(id string) (Cargo, error) { + defer func(begin time.Time) { + methodField := metrics.Field{Key: "method", Value: "track"} + s.requestCount.With(methodField).Add(1) + s.requestLatency.With(methodField).Observe(time.Since(begin)) + }(time.Now()) + + return s.Service.Track(id) +}