Go driver
- Introduction
- Pre-requisites
- Using it
- Instrumentation
- Metrics
- Instrumentation matrix
- End-to-end example
- References
Introduction
A wrapper for the official MongoDB Go driver has been instrumented with OpenCensus for Tracing and metrics at https://github.com/opencensus-integrations/gomongowrapper
Pre-requisites
- Go
- MongoDB server
- Stackdriver Tracing and Monitoring which we are using only because it provides both tracing and metrics
Using it
To install the wrapper, please run this command
go get -u -v github.com/opencensus-integrations/gomongowrapper/...
and then in your code, just exactly like you would when using the original driver (except now with the new import)
import (
"context"
"log"
"github.com/opencensus-integrations/gomongowrapper"
)
func main() {
client, err := mongowrapper.NewClient(MONGO_URL)
if err != nil {
log.Fatalf("Failed to create the new client: %v", err)
}
ctx := context.Background()
if err := client.Connect(ctx); err != nil {
log.Fatalf("Failed to open client connection: %v", err)
}
defer client.Disconnect(ctx)
}
Instrumentation
The designers of the official MongoDB Go driver ensured that each method takes in a context.Context.
Fortunately for us, this permits context propagation, which is the mechanism with which observability signals are propagated across RPCs and over the wire.
Enabling tracing
To enable trace continuity, just use the same context that contains your traces and at some point, to consume the produced traces, please enable a Trace exporter
For example
// Start a span like your application would start one.
ctx, span := trace.StartSpan(context.Background(), "Fetch")
defer span.End()
// Now for the mongo connections, using the context
// with the span in it for continuity.
client, err := mongowrapper.NewClient("mongodb://localhost:27017")
if err != nil {
log.Fatalf("Failed to create the new client: %v", err)
}
if err := client.Connect(ctx); err != nil {
log.Fatalf("Failed to open client connection: %v", err)
}
defer client.Disconnect(ctx)
coll := client.Database("the_db").Collection("music")
Enabling metrics
To enable metrics, just use the same context that contains your metrics or tags and at some point, to consume the produced metrics, please enable a Metrics exporter
However, most importantly, please make sure to invoke gomongowrapper.RegisterAllViews
import (
"log"
"github.com/opencensus-integrations/gomongowrapper"
)
if err := gomongowrapper.RegisterAllViews(); err != nil {
log.Fatalf("Failed to register MongoDB views: %v", err)
}
Enabling exporters
Please select your target Go trace and metrics exporters from Go exporters
Metrics
Metric | Query Suffix | Description | Aggregation | Tags |
---|---|---|---|---|
Latency | “mongo/client/latency” | The latencies of the various calls in milliseconds | Distribution | “method”, “status”, “error” |
Calls | “mongo/client/calls” | The various calls | Count | “method”, “status”, “error” |
Tags
As per Metrics, we have a couple of tags applied to some measurements to provide metrics
method
The tag key “method” will have a fully qualified name such as
"github.com/mongodb/mongo-go-driver.Client.EndSession"
to distinguish between the various calls as per Instrumentation matrix
status
The tag key “status” will be either one of the following values
- OK – if set indicates that the call was successful
- ERROR – if set indicates that the error will be set in the tag key “error”
error
The tag key “error” will contain a description of the encountered error.
Instrumentation matrix
This is the full list of methods that have been instrumented with tracing and metrics
Method | Method Name |
---|---|
Client.Connect | “github.com/mongodb/mongo-go-driver.Client.Connect” |
Client.Disconnect | github.com/mongodb/mongo-go-driver.Client.Disconnect |
Client.ListDatabaseNames | “github.com/mongodb/mongo-go-driver.Client.ListDatabaseNames” |
Client.ListDatabases | “github.com/mongodb/mongo-go-driver.Client.ListDatabases” |
Client.Ping | “github.com/mongodb/mongo-go-driver.Client.Ping” |
Collection.Aggregate | “github.com/mongodb/mongo-go-driver.Collection.Aggregate” |
Collection.BulkWrite | “github.com/mongodb/mongo-go-driver.Collection.BulkWrite” |
Collection.Count | “github.com/mongodb/mongo-go-driver.Collection.Count” |
Collection.CountDocuments | “github.com/mongodb/mongo-go-driver.Collection.CountDocuments” |
Collection.DeleteMany | “github.com/mongodb/mongo-go-driver.Collection.DeleteMany” |
Collection.DeleteOne | “github.com/mongodb/mongo-go-driver.Collection.DeleteOne” |
Collection.Distinct | “github.com/mongodb/mongo-go-driver.Collection.Distinct” |
Collection.Drop | “github.com/mongodb/mongo-go-driver.Collection.Drop” |
Collection.EstimatedDocumentCount | “github.com/mongodb/mongo-go-driver.Collection.EstimatedDocumentCount” |
Collection.Find | “github.com/mongodb/mongo-go-driver.Collection.Find” |
Collection.FindOne | “github.com/mongodb/mongo-go-driver.Collection.FindOne” |
Collection.FindOneAndDelete | “github.com/mongodb/mongo-go-driver.Collection.FindOneAndDelete” |
Collection.FindOneAndReplace | “github.com/mongodb/mongo-go-driver.Collection.FindOneAndReplace” |
Collection.FindOneAndUpdate | “github.com/mongodb/mongo-go-driver.Collection.FindOneAndUpdate” |
Collection.InsertMany | “github.com/mongodb/mongo-go-driver.Collection.InsertMany” |
Collection.InsertOne | “github.com/mongodb/mongo-go-driver.Collection.InsertOne” |
Collection.ReplaceOne | “github.com/mongodb/mongo-go-driver.Collection.ReplaceOne” |
Collection.UpdateMany | “github.com/mongodb/mongo-go-driver.Collection.UpdateMany” |
Collection.UpdateOne | “github.com/mongodb/mongo-go-driver.Collection.UpdateOne” |
Collection.Watch | “github.com/mongodb/mongo-go-driver.Collection.Watch” |
Database.Drop | “github.com/mongodb/mongo-go-driver.Database.Drop” |
Database.ListCollections | “github.com/mongodb/mongo-go-driver.Database.ListCollections” |
Database.RunCommand | “github.com/mongodb/mongo-go-driver.Database.RunCommand” |
Session.AbortTransaction | “github.com/mongodb/mongo-go-driver.Session.AbortTransaction” |
Session.CommitTransaction | “github.com/mongodb/mongo-go-driver.Session.CommitTransaction” |
Session.EndSession | “github.com/mongodb/mongo-go-driver.Client.EndSession” |
End to end example
Assuming that you already have a MongoDB server running at “localhost:27017”
package main
import (
"context"
"log"
"time"
"github.com/mongodb/mongo-go-driver/bson"
"github.com/opencensus-integrations/gomongowrapper"
"contrib.go.opencensus.io/exporter/stackdriver"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
)
func main() {
// Enabling the OpenCensus exporter.
// Just using Stackdriver since it has both Tracing and Metrics
// and is easy to whip up. Add your desired one here.
sde, err := stackdriver.NewExporter(stackdriver.Options{
ProjectID: "census-demos",
MetricPrefix: "mongosample",
})
if err != nil {
log.Fatalf("Failed to create Stackdriver exporter: %v", err)
}
sde.StartMetricsExporter()
defer sde.StopMetricsExporter()
trace.RegisterExporter(sde)
if err := mongowrapper.RegisterAllViews(); err != nil {
log.Fatalf("Failed to register all views: %v\n", err)
}
defer func() {
<-time.After(2 * time.Minute)
}()
// Start a span like your application would start one.
ctx, span := trace.StartSpan(context.Background(), "Fetch", trace.WithSampler(trace.AlwaysSample()))
defer span.End()
// Now for the mongo connections, using the context
// with the span in it for continuity.
client, err := mongowrapper.NewClient("mongodb://localhost:27017")
if err != nil {
log.Fatalf("Failed to create the new client: %v", err)
}
if err := client.Connect(ctx); err != nil {
log.Fatalf("Failed to open client connection: %v", err)
}
defer client.Disconnect(ctx)
coll := client.Database("the_db").Collection("music")
q := bson.M{"name": "Examples"}
cur, err := coll.Find(ctx, q)
if err != nil {
log.Fatalf("Find error: %v", err)
}
for cur.Next(ctx) {
elem := make(map[string]int)
if err := cur.Decode(elem); err != nil {
log.Printf("Decode error: %v", err)
continue
}
log.Printf("Got result: %v\n", elem)
}
log.Print("Done iterating")
_, err = coll.DeleteMany(ctx, q)
if err != nil {
log.Fatalf("Failed to delete: %v", err)
}
}
Results
After running the above sample, and examining the results by visiting
Resource | URL |
---|---|
Traces on Stackdriver | https://console.cloud.google.com/traces/traces |
Metrics on Stackdriver | https://console.cloud.google.com/traces/monitoring |
Traces screenshots
Metrics screenshots
All metrics
Latency heatmap
Latency rate
Calls rate
References
Resource | URL |
---|---|
MongoDB website | https://www.mongodb.com/ |
Official MongoDB Go driver | https://godoc.org/github.com/mongodb/mongo-go-driver/mongo |
OpenCensus wrapper for MongoDB Go driver | https://godoc.org/github.com/opencensus-integrations/gomongowrapper |