Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
95dcf65
feat: adding instrumentation support for mongo-driver/v2
AlaricWhitney Dec 27, 2024
24b5f1e
Update LInting
AlaricWhitney Jan 13, 2025
b3cbb84
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Feb 15, 2025
a0f083b
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Feb 15, 2025
f83a9ab
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Feb 15, 2025
8e90ad0
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Feb 15, 2025
9590887
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Feb 15, 2025
71da688
Merge branch 'main' into main
AlaricWhitney Feb 15, 2025
6d22da1
chore: Updating version
AlaricWhitney Feb 15, 2025
37c8729
chore: removing version unit test
AlaricWhitney Feb 15, 2025
4e44c3e
Update code reference source
AlaricWhitney Feb 15, 2025
f6ec856
Merge branch 'main' into main
AlaricWhitney Feb 17, 2025
d38d115
lint: fix extra empty comment line
AlaricWhitney Feb 17, 2025
0403896
Merge branch 'main' into main
AlaricWhitney Feb 20, 2025
e97fcde
fix: fixed lint issue
AlaricWhitney Feb 20, 2025
bd3c9c5
feat: adding changelog entry for #6539 adding instrumentation for go.…
AlaricWhitney Feb 20, 2025
407eea4
Merge branch 'main' into main
AlaricWhitney Feb 20, 2025
c0d2e16
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
6ab56e1
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
dd6d736
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
7b9fc3e
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
c40e17c
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
7675b51
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
afa32f5
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
ee21b89
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
80b0e88
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Mar 18, 2025
3cabc4a
Merge branch 'main' into main
AlaricWhitney Mar 18, 2025
f2cd406
fix: updated as per PR fedback
AlaricWhitney Mar 18, 2025
9cf350b
Merge branch 'main' into main
AlaricWhitney Mar 24, 2025
d9dbc54
chore: removed go.mongodb.org/mongo-driver/v2/mongo/otelmongo and adj…
AlaricWhitney Mar 24, 2025
7c76a06
Merge branch 'main' into main
AlaricWhitney Mar 31, 2025
199af6e
feat: adding go.opentelemetry.io/contrib/instrumentation/go.mongodb.o…
AlaricWhitney Mar 31, 2025
6104456
Update versions.yaml
AlaricWhitney Apr 2, 2025
ed3c88f
Merge branch 'main' into main
AlaricWhitney Apr 2, 2025
ccdf40b
Merge branch 'main' into main
AlaricWhitney Apr 3, 2025
44ce2e3
Merge branch 'main' into main
AlaricWhitney Apr 14, 2025
71e37cc
Merge branch 'main' into main
AlaricWhitney Apr 21, 2025
ef0cecb
Update CODEOWNERS
AlaricWhitney Apr 22, 2025
83cf6a7
Merge branch 'main' into main
AlaricWhitney Apr 22, 2025
d996ffa
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney Apr 28, 2025
fbec035
Merge branch 'main' into main
AlaricWhitney Apr 28, 2025
008b27e
chore: update imports
AlaricWhitney Apr 28, 2025
11147fc
Update instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo…
AlaricWhitney May 2, 2025
a5981a9
fix: added unit test for peerInfo and fixed logic issue
AlaricWhitney May 2, 2025
e67c9dc
switch logic to use net.SplitHostPort
AlaricWhitney May 2, 2025
bbd29fb
Merge branch 'main' into main
AlaricWhitney May 2, 2025
56fad4e
chore: linting
AlaricWhitney May 2, 2025
2c6ae99
Update CHANGELOG.md
dmathieu May 7, 2025
229c628
Merge branch 'main' into main
dmathieu May 7, 2025
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The next release will require at least [Go 1.23].

### Added

- Add instrumentation support for `go.mongodb.org/mongo-driver/v2` in `go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo`(#6539)
- Add support for configuring `ClientCertificate` and `ClientKey` field for OTLP exporters in `go.opentelemetry.io/contrib/config`. (#6378)
- Add `WithAttributeBuilder`, `AttributeBuilder`, `DefaultAttributeBuilder`, `DynamoDBAttributeBuilder`, `SNSAttributeBuilder` to support adding attributes based on SDK input and output in `go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws`. (#6543)
- Support for the OTEL_HTTP_CLIENT_COMPATIBILITY_MODE=http/dup environment variable in `go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux` to emit attributes for both the v1.20.0 and v1.26.0 semantic conventions. (#6652)
Expand Down
1 change: 1 addition & 0 deletions instrumentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ The following instrumentation packages are provided for popular Go packages and
| [github.com/gorilla/mux](./github.com/gorilla/mux/otelmux) | | ✓ |
| [github.com/labstack/echo](./github.com/labstack/echo/otelecho) | | ✓ |
| [go.mongodb.org/mongo-driver](./go.mongodb.org/mongo-driver/mongo/otelmongo) | | ✓ |
| [go.mongodb.org/mongo-driver/v2](./go.mongodb.org/mongo-driver/v2/mongo/otelmongo) | | ✓ |
| [google.golang.org/grpc](./google.golang.org/grpc/otelgrpc) | ✓ | ✓ |
| [host](./host) | ✓ | |
| [net/http](./net/http/otelhttp) | ✓ | ✓ |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package otelmongo // import "go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo"

import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
)

// ScopeName is the instrumentation scope name.
const ScopeName = "go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo"

// config is used to configure the mongo tracer.
type config struct {
TracerProvider trace.TracerProvider

Tracer trace.Tracer

CommandAttributeDisabled bool
}

// newConfig returns a config with all Options set.
func newConfig(opts ...Option) config {
cfg := config{
TracerProvider: otel.GetTracerProvider(),
CommandAttributeDisabled: true,
}
for _, opt := range opts {
opt.apply(&cfg)
}

cfg.Tracer = cfg.TracerProvider.Tracer(
ScopeName,
trace.WithInstrumentationVersion(Version()),
)
return cfg
}

// Option specifies instrumentation configuration options.
type Option interface {
apply(*config)
}

type optionFunc func(*config)

func (o optionFunc) apply(c *config) {
o(c)
}

// WithTracerProvider specifies a tracer provider to use for creating a tracer.
// If none is specified, the global provider is used.
func WithTracerProvider(provider trace.TracerProvider) Option {
return optionFunc(func(cfg *config) {
if provider != nil {
cfg.TracerProvider = provider
}
})
}

// WithCommandAttributeDisabled specifies if the MongoDB command is added as an attribute to Spans or not.
// This is disabled by default and the MongoDB command will not be added as an attribute
// to Spans if this option is not provided.
func WithCommandAttributeDisabled(disabled bool) Option {
return optionFunc(func(cfg *config) {
cfg.CommandAttributeDisabled = disabled
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

// Package otelmongo instruments go.mongodb.org/mongo-driver/v2/mongo.
//
// `NewMonitor` will return an event.CommandMonitor which is used to trace
// requests.
//
// This code was originally based on the following:
// - https://github.com/open-telemetry/opentelemetry-go-contrib/tree/323e373a6c15ae310bdd0617e3ed52d8cb8e4e6f/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo
package otelmongo // import "go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo"
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package otelmongo_test

import (
"context"

"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"

"go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo"
)

func Example() {
// connect to MongoDB
opts := options.Client()
opts.Monitor = otelmongo.NewMonitor()
opts.ApplyURI("mongodb://localhost:27017")
client, err := mongo.Connect(opts)
if err != nil {
panic(err)
}
db := client.Database("example")
inventory := db.Collection("inventory")

_, err = inventory.InsertOne(context.Background(), bson.D{
{Key: "item", Value: "canvas"},
{Key: "qty", Value: 100},
{Key: "attributes", Value: bson.A{"cotton"}},
{Key: "size", Value: bson.D{
{Key: "h", Value: 28},
{Key: "w", Value: 35.5},
{Key: "uom", Value: "cm"},
}},
})
if err != nil {
panic(err)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo

go 1.22.0

require (
go.mongodb.org/mongo-driver/v2 v2.0.0
go.opentelemetry.io/otel v1.33.0
go.opentelemetry.io/otel/trace v1.33.0
)

require (
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/metric v1.33.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/text v0.21.0 // indirect
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver/v2 v2.0.0 h1:Jfd7XpdZa9yk3eY774bO7SWVb30noLSirL9nKTpavhI=
go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package otelmongo // import "go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo"

import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"sync"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a new package, we should rely on the latest semantic conventions (1.30.0) right away, let's not make things harder by forcing a migration right away :)

Copy link
Contributor Author

@AlaricWhitney AlaricWhitney Mar 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's some breaking changes between v1.21.0 and v1.30.0. Most are simple name changes when comparing the semconv key names in the docs, but db.statement was renamed in open-telemetry/opentelemetry-go#5476. I'll update it to db.query.text.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's exactly why we should rely on the latest. If we ship with the old version, we'll have to migrate in a forward PR.

"go.opentelemetry.io/otel/trace"

"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/event"
)

type spanKey struct {
ConnectionID string
RequestID int64
}

type monitor struct {
sync.Mutex
spans map[spanKey]trace.Span
cfg config
}

func (m *monitor) Started(ctx context.Context, evt *event.CommandStartedEvent) {
var spanName string

hostname, port := peerInfo(evt)

attrs := []attribute.KeyValue{
semconv.DBSystemMongoDB,
semconv.DBOperation(evt.CommandName),
semconv.DBName(evt.DatabaseName),
semconv.NetPeerName(hostname),
semconv.NetPeerPort(port),
semconv.NetTransportTCP,
}
if !m.cfg.CommandAttributeDisabled {
attrs = append(attrs, semconv.DBStatement(sanitizeCommand(evt.Command)))
}
if collection, err := extractCollection(evt); err == nil && collection != "" {
spanName = collection + "."
attrs = append(attrs, semconv.DBMongoDBCollection(collection))
}
spanName += evt.CommandName
opts := []trace.SpanStartOption{
trace.WithSpanKind(trace.SpanKindClient),
trace.WithAttributes(attrs...),
}
_, span := m.cfg.Tracer.Start(ctx, spanName, opts...)
key := spanKey{
ConnectionID: evt.ConnectionID,
RequestID: evt.RequestID,
}
m.Lock()
m.spans[key] = span
m.Unlock()
}

func (m *monitor) Succeeded(ctx context.Context, evt *event.CommandSucceededEvent) {
m.Finished(&evt.CommandFinishedEvent, nil)
}

func (m *monitor) Failed(ctx context.Context, evt *event.CommandFailedEvent) {
m.Finished(&evt.CommandFinishedEvent, fmt.Errorf("%w", evt.Failure))

Check warning on line 74 in instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go#L73-L74

Added lines #L73 - L74 were not covered by tests
}

func (m *monitor) Finished(evt *event.CommandFinishedEvent, err error) {
key := spanKey{
ConnectionID: evt.ConnectionID,
RequestID: evt.RequestID,
}
m.Lock()
span, ok := m.spans[key]
if ok {
delete(m.spans, key)
}
m.Unlock()
if !ok {
return
}

Check warning on line 90 in instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go#L89-L90

Added lines #L89 - L90 were not covered by tests

if err != nil {
span.SetStatus(codes.Error, err.Error())
}

Check warning on line 94 in instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go#L93-L94

Added lines #L93 - L94 were not covered by tests

span.End()
}

// TODO sanitize values where possible, then re-enable `db.statement` span attributes default.
// TODO limit maximum size.
func sanitizeCommand(command bson.Raw) string {
b, _ := bson.MarshalExtJSON(command, false, false)
return string(b)
}

// extractCollection extracts the collection for the given mongodb command event.
// For CRUD operations, this is the first key/value string pair in the bson
// document where key == "<operation>" (e.g. key == "insert").
// For database meta-level operations, such a key may not exist.
func extractCollection(evt *event.CommandStartedEvent) (string, error) {
elt, err := evt.Command.IndexErr(0)
if err != nil {
return "", err
}

Check warning on line 114 in instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go#L113-L114

Added lines #L113 - L114 were not covered by tests
if key, err := elt.KeyErr(); err == nil && key == evt.CommandName {
var v bson.RawValue
if v, err = elt.ValueErr(); err != nil || v.Type != bson.TypeString {
return "", err
}
return v.StringValue(), nil
}
return "", errors.New("collection name not found")

Check warning on line 122 in instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go#L122

Added line #L122 was not covered by tests
}

// NewMonitor creates a new mongodb event CommandMonitor.
func NewMonitor(opts ...Option) *event.CommandMonitor {
cfg := newConfig(opts...)
m := &monitor{
spans: make(map[spanKey]trace.Span),
cfg: cfg,
}
return &event.CommandMonitor{
Started: m.Started,
Succeeded: m.Succeeded,
Failed: m.Failed,
}
}

func peerInfo(evt *event.CommandStartedEvent) (hostname string, port int) {
hostname = evt.ConnectionID
port = 27017
if idx := strings.IndexByte(hostname, '['); idx >= 0 {
hostname = hostname[:idx]
}

Check warning on line 144 in instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go#L143-L144

Added lines #L143 - L144 were not covered by tests
if idx := strings.IndexByte(hostname, ':'); idx >= 0 {
port = func(p int, e error) int { return p }(strconv.Atoi(hostname[idx+1:]))
hostname = hostname[:idx]

Check warning on line 147 in instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go

View check run for this annotation

Codecov / codecov/patch

instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/mongo.go#L146-L147

Added lines #L146 - L147 were not covered by tests
}
return hostname, port
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

/*
Package test validates the otelmongo V2 instrumentation with the default SDK.
This package is in a separate module from the instrumentation it tests to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having this in a test subpackage shouldn't be required anymore, and we're in the process of removing that folder for every instrumentation.
Since this is a new one, could we avoid creating it altogether?

See #6763 as similar work for otelhttp.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure. I can move the tests to the package folder similar to what was done in #6763

isolate the dependency of the default SDK and not impose this as a transitive
dependency for users.
*/
package test // import "go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo/test"
Loading
Loading