|
| 1 | +// Copyright 2018, OpenCensus Authors |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +package mongowrapper |
| 16 | + |
| 17 | +import ( |
| 18 | + "context" |
| 19 | + "sync" |
| 20 | + "time" |
| 21 | + |
| 22 | + "go.opencensus.io/stats" |
| 23 | + "go.opencensus.io/stats/view" |
| 24 | + "go.opencensus.io/tag" |
| 25 | + "go.opencensus.io/trace" |
| 26 | +) |
| 27 | + |
| 28 | +var ( |
| 29 | + keyMethod, _ = tag.NewKey("method") |
| 30 | + keyStatus, _ = tag.NewKey("status") |
| 31 | + keyError, _ = tag.NewKey("error") |
| 32 | +) |
| 33 | + |
| 34 | +var mLatencyMs = stats.Float64("latency", "The latency in milliseconds", "ms") |
| 35 | + |
| 36 | +var allViews = []*view.View{ |
| 37 | + { |
| 38 | + Name: "mongo/client/latency", Description: "The latency of the various calls", |
| 39 | + Measure: mLatencyMs, |
| 40 | + // [0ms, 0.001ms, 0.005ms, 0.01ms, 0.05ms, 0.1ms, 0.5ms, 1ms, 1.5ms, 2ms, 2.5ms, 5ms, 10ms, 25ms, 50ms, 100ms, 200ms, |
| 41 | + // 400ms, 600ms, 800ms, 1s, 1.5s, 2s, 2.5s, 5s, 10s, 20s, 40s, 100s, 200s, 500s, 1000s] |
| 42 | + // |
| 43 | + Aggregation: view.Distribution(0, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 1.5, 2, 2.5, 5, 10, 25, 50, 100, 200, |
| 44 | + 400, 600, 800, 1000, 1500, 2000, 2500, 5000, 10000, 20000, 40000, 100000, 200000, 500000, 1000000), |
| 45 | + TagKeys: []tag.Key{keyMethod, keyStatus, keyError}, |
| 46 | + }, |
| 47 | + { |
| 48 | + Name: "mongo/client/calls", Description: "The various calls", |
| 49 | + Measure: mLatencyMs, |
| 50 | + Aggregation: view.Count(), |
| 51 | + TagKeys: []tag.Key{keyMethod, keyStatus, keyError}, |
| 52 | + }, |
| 53 | +} |
| 54 | + |
| 55 | +func RegisterAllViews() error { |
| 56 | + return view.Register(allViews...) |
| 57 | +} |
| 58 | + |
| 59 | +func UnregisterAllViews() { |
| 60 | + view.Unregister(allViews...) |
| 61 | +} |
| 62 | + |
| 63 | +type spanWithMetrics struct { |
| 64 | + startTime time.Time |
| 65 | + method string |
| 66 | + lastErr error |
| 67 | + span *trace.Span |
| 68 | + endOnce sync.Once |
| 69 | +} |
| 70 | + |
| 71 | +func roundtripTrackingSpan(ctx context.Context, methodName string) (context.Context, *spanWithMetrics) { |
| 72 | + ctx, span := trace.StartSpan(ctx, methodName) |
| 73 | + return ctx, &spanWithMetrics{span: span, startTime: time.Now()} |
| 74 | +} |
| 75 | + |
| 76 | +func (swm *spanWithMetrics) setError(err error) { |
| 77 | + if err != nil { |
| 78 | + swm.span.SetStatus(trace.Status{Code: trace.StatusCodeUnknown, Message: err.Error()}) |
| 79 | + } |
| 80 | + swm.lastErr = err |
| 81 | +} |
| 82 | + |
| 83 | +func (swm *spanWithMetrics) end(ctx context.Context) { |
| 84 | + swm.endOnce.Do(func() { |
| 85 | + if err := swm.lastErr; err == nil { |
| 86 | + ctx, _ = tag.New(ctx, tag.Upsert(keyMethod, swm.method), tag.Upsert(keyStatus, "OK")) |
| 87 | + } else { |
| 88 | + ctx, _ = tag.New(ctx, tag.Upsert(keyMethod, swm.method), tag.Upsert(keyError, err.Error())) |
| 89 | + } |
| 90 | + |
| 91 | + latencyMs := float64(time.Now().Sub(swm.startTime)) / 1e6 |
| 92 | + stats.Record(ctx, mLatencyMs.M(latencyMs)) |
| 93 | + swm.span.End() |
| 94 | + }) |
| 95 | +} |
0 commit comments