shipping: Add prometheus instrumentation
Marcus Olsson
7 years ago
0 | package booking | |
1 | ||
2 | import ( | |
3 | "time" | |
4 | ||
5 | stdprometheus "github.com/prometheus/client_golang/prometheus" | |
6 | ||
7 | "github.com/go-kit/kit/metrics" | |
8 | kitprometheus "github.com/go-kit/kit/metrics/prometheus" | |
9 | ||
10 | "github.com/go-kit/kit/examples/shipping/cargo" | |
11 | "github.com/go-kit/kit/examples/shipping/location" | |
12 | ) | |
13 | ||
14 | type instrumentingService struct { | |
15 | requestCount metrics.Counter | |
16 | requestLatency metrics.TimeHistogram | |
17 | Service | |
18 | } | |
19 | ||
20 | // NewInstrumentingService returns an instance of an instrumenting Service. | |
21 | func NewInstrumentingService(s Service) Service { | |
22 | fieldKeys := []string{"method"} | |
23 | ||
24 | requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{ | |
25 | Namespace: "api", | |
26 | Subsystem: "booking_service", | |
27 | Name: "request_count", | |
28 | Help: "Number of requests received.", | |
29 | }, fieldKeys) | |
30 | ||
31 | requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{ | |
32 | Namespace: "api", | |
33 | Subsystem: "booking_service", | |
34 | Name: "request_latency_microseconds", | |
35 | Help: "Total duration of requests in microseconds.", | |
36 | }, fieldKeys)) | |
37 | ||
38 | return &instrumentingService{ | |
39 | requestCount: requestCount, | |
40 | requestLatency: requestLatency, | |
41 | Service: s, | |
42 | } | |
43 | } | |
44 | ||
45 | func (s *instrumentingService) BookNewCargo(origin, destination location.UNLocode, arrivalDeadline time.Time) (cargo.TrackingID, error) { | |
46 | defer func(begin time.Time) { | |
47 | methodField := metrics.Field{Key: "method", Value: "book"} | |
48 | s.requestCount.With(methodField).Add(1) | |
49 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
50 | }(time.Now()) | |
51 | ||
52 | return s.Service.BookNewCargo(origin, destination, arrivalDeadline) | |
53 | } | |
54 | ||
55 | func (s *instrumentingService) LoadCargo(id cargo.TrackingID) (c Cargo, err error) { | |
56 | defer func(begin time.Time) { | |
57 | methodField := metrics.Field{Key: "method", Value: "load"} | |
58 | s.requestCount.With(methodField).Add(1) | |
59 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
60 | }(time.Now()) | |
61 | ||
62 | return s.Service.LoadCargo(id) | |
63 | } | |
64 | ||
65 | func (s *instrumentingService) RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary { | |
66 | defer func(begin time.Time) { | |
67 | methodField := metrics.Field{Key: "method", Value: "request_routes"} | |
68 | s.requestCount.With(methodField).Add(1) | |
69 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
70 | }(time.Now()) | |
71 | ||
72 | return s.Service.RequestPossibleRoutesForCargo(id) | |
73 | } | |
74 | ||
75 | func (s *instrumentingService) AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) (err error) { | |
76 | defer func(begin time.Time) { | |
77 | methodField := metrics.Field{Key: "method", Value: "assign_to_route"} | |
78 | s.requestCount.With(methodField).Add(1) | |
79 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
80 | }(time.Now()) | |
81 | ||
82 | return s.Service.AssignCargoToRoute(id, itinerary) | |
83 | } | |
84 | ||
85 | func (s *instrumentingService) ChangeDestination(id cargo.TrackingID, l location.UNLocode) (err error) { | |
86 | defer func(begin time.Time) { | |
87 | methodField := metrics.Field{Key: "method", Value: "change_destination"} | |
88 | s.requestCount.With(methodField).Add(1) | |
89 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
90 | }(time.Now()) | |
91 | ||
92 | return s.Service.ChangeDestination(id, l) | |
93 | } | |
94 | ||
95 | func (s *instrumentingService) Cargos() []Cargo { | |
96 | defer func(begin time.Time) { | |
97 | methodField := metrics.Field{Key: "method", Value: "list_cargos"} | |
98 | s.requestCount.With(methodField).Add(1) | |
99 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
100 | }(time.Now()) | |
101 | ||
102 | return s.Service.Cargos() | |
103 | } | |
104 | ||
105 | func (s *instrumentingService) Locations() []Location { | |
106 | defer func(begin time.Time) { | |
107 | methodField := metrics.Field{Key: "method", Value: "list_locations"} | |
108 | s.requestCount.With(methodField).Add(1) | |
109 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
110 | }(time.Now()) | |
111 | ||
112 | return s.Service.Locations() | |
113 | } |
0 | package handling | |
1 | ||
2 | import ( | |
3 | "time" | |
4 | ||
5 | "github.com/go-kit/kit/metrics" | |
6 | kitprometheus "github.com/go-kit/kit/metrics/prometheus" | |
7 | stdprometheus "github.com/prometheus/client_golang/prometheus" | |
8 | ||
9 | "github.com/go-kit/kit/examples/shipping/cargo" | |
10 | "github.com/go-kit/kit/examples/shipping/location" | |
11 | "github.com/go-kit/kit/examples/shipping/voyage" | |
12 | ) | |
13 | ||
14 | type instrumentingService struct { | |
15 | requestCount metrics.Counter | |
16 | requestLatency metrics.TimeHistogram | |
17 | Service | |
18 | } | |
19 | ||
20 | // NewInstrumentingService returns an instance of an instrumenting Service. | |
21 | func NewInstrumentingService(s Service) Service { | |
22 | fieldKeys := []string{"method"} | |
23 | ||
24 | requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{ | |
25 | Namespace: "api", | |
26 | Subsystem: "handling_service", | |
27 | Name: "request_count", | |
28 | Help: "Number of requests received.", | |
29 | }, fieldKeys) | |
30 | ||
31 | requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{ | |
32 | Namespace: "api", | |
33 | Subsystem: "handling_service", | |
34 | Name: "request_latency_microseconds", | |
35 | Help: "Total duration of requests in microseconds.", | |
36 | }, fieldKeys)) | |
37 | ||
38 | return &instrumentingService{ | |
39 | requestCount: requestCount, | |
40 | requestLatency: requestLatency, | |
41 | Service: s, | |
42 | } | |
43 | } | |
44 | ||
45 | func (s *instrumentingService) RegisterHandlingEvent(completionTime time.Time, trackingID cargo.TrackingID, voyage voyage.Number, | |
46 | loc location.UNLocode, eventType cargo.HandlingEventType) error { | |
47 | ||
48 | defer func(begin time.Time) { | |
49 | methodField := metrics.Field{Key: "method", Value: "register_incident"} | |
50 | s.requestCount.With(methodField).Add(1) | |
51 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
52 | }(time.Now()) | |
53 | ||
54 | return s.Service.RegisterHandlingEvent(completionTime, trackingID, voyage, loc, eventType) | |
55 | } |
10 | 10 | "time" |
11 | 11 | |
12 | 12 | "github.com/go-kit/kit/log" |
13 | stdprometheus "github.com/prometheus/client_golang/prometheus" | |
13 | 14 | "golang.org/x/net/context" |
14 | 15 | |
15 | 16 | "github.com/go-kit/kit/examples/shipping/booking" |
73 | 74 | var bs booking.Service |
74 | 75 | bs = booking.NewService(cargos, locations, handlingEvents, rs) |
75 | 76 | bs = booking.NewLoggingService(log.NewContext(logger).With("component", "booking"), bs) |
77 | bs = booking.NewInstrumentingService(bs) | |
76 | 78 | |
77 | 79 | var ts tracking.Service |
78 | 80 | ts = tracking.NewService(cargos, handlingEvents) |
79 | 81 | ts = tracking.NewLoggingService(log.NewContext(logger).With("component", "tracking"), ts) |
82 | ts = tracking.NewInstrumentingService(ts) | |
80 | 83 | |
81 | 84 | var hs handling.Service |
82 | 85 | hs = handling.NewService(handlingEvents, handlingEventFactory, handlingEventHandler) |
83 | 86 | hs = handling.NewLoggingService(log.NewContext(logger).With("component", "handling"), hs) |
87 | hs = handling.NewInstrumentingService(hs) | |
84 | 88 | |
85 | 89 | httpLogger := log.NewContext(logger).With("component", "http") |
86 | 90 | |
91 | 95 | mux.Handle("/handling/v1/", handling.MakeHandler(ctx, hs, httpLogger)) |
92 | 96 | |
93 | 97 | http.Handle("/", accessControl(mux)) |
98 | http.Handle("/metrics", stdprometheus.Handler()) | |
94 | 99 | |
95 | 100 | errs := make(chan error, 2) |
96 | 101 | go func() { |
0 | package tracking | |
1 | ||
2 | import ( | |
3 | "time" | |
4 | ||
5 | stdprometheus "github.com/prometheus/client_golang/prometheus" | |
6 | ||
7 | "github.com/go-kit/kit/metrics" | |
8 | kitprometheus "github.com/go-kit/kit/metrics/prometheus" | |
9 | ) | |
10 | ||
11 | type instrumentingService struct { | |
12 | requestCount metrics.Counter | |
13 | requestLatency metrics.TimeHistogram | |
14 | Service | |
15 | } | |
16 | ||
17 | // NewInstrumentingService returns an instance of an instrumenting Service. | |
18 | func NewInstrumentingService(s Service) Service { | |
19 | fieldKeys := []string{"method"} | |
20 | ||
21 | requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{ | |
22 | Namespace: "api", | |
23 | Subsystem: "tracking_service", | |
24 | Name: "request_count", | |
25 | Help: "Number of requests received.", | |
26 | }, fieldKeys) | |
27 | ||
28 | requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{ | |
29 | Namespace: "api", | |
30 | Subsystem: "tracking_service", | |
31 | Name: "request_latency_microseconds", | |
32 | Help: "Total duration of requests in microseconds.", | |
33 | }, fieldKeys)) | |
34 | ||
35 | return &instrumentingService{ | |
36 | requestCount: requestCount, | |
37 | requestLatency: requestLatency, | |
38 | Service: s, | |
39 | } | |
40 | } | |
41 | ||
42 | func (s *instrumentingService) Track(id string) (Cargo, error) { | |
43 | defer func(begin time.Time) { | |
44 | methodField := metrics.Field{Key: "method", Value: "track"} | |
45 | s.requestCount.With(methodField).Add(1) | |
46 | s.requestLatency.With(methodField).Observe(time.Since(begin)) | |
47 | }(time.Now()) | |
48 | ||
49 | return s.Service.Track(id) | |
50 | } |