Skip to content

Commit dd613bc

Browse files
[mq] working branch - merge 298e6cd on top of main at fa72b69
{"baseBranch":"main","baseCommit":"fa72b69e5371c19505a674205beb4e63f0dd9c0e","createdAt":"2026-01-27T15:08:46.145299Z","headSha":"298e6cd1dee260c469ffb30a4a11f589bfa095ab","id":"d4350c16-f2d4-4898-8fc7-d92c715b376b","priority":"200","pullRequestNumber":"3679","queuedAt":"2026-01-27T15:08:46.143352Z","retryAttempt":"1","status":"STATUS_QUEUED"}
2 parents 649c66a + 298e6cd commit dd613bc

File tree

6 files changed

+182
-6
lines changed

6 files changed

+182
-6
lines changed

contrib/go.mongodb.org/mongo-driver.v2/mongo/mongo.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,11 @@ type monitor struct {
4141

4242
func (m *monitor) Started(ctx context.Context, evt *event.CommandStartedEvent) {
4343
hostname, port := peerInfo(evt)
44-
b, _ := bson.MarshalExtJSON(evt.Command, false, false)
4544
opts := []tracer.StartSpanOption{
4645
tracer.SpanType(ext.SpanTypeMongoDB),
4746
tracer.ServiceName(m.cfg.serviceName),
4847
tracer.ResourceName("mongo." + evt.CommandName),
4948
tracer.Tag(ext.DBInstance, evt.DatabaseName),
50-
tracer.Tag(m.cfg.spanName, string(b)),
5149
tracer.Tag(ext.DBType, "mongo"),
5250
tracer.Tag(ext.PeerHostname, hostname),
5351
tracer.Tag(ext.NetworkDestinationName, hostname),
@@ -56,6 +54,13 @@ func (m *monitor) Started(ctx context.Context, evt *event.CommandStartedEvent) {
5654
tracer.Tag(ext.SpanKind, ext.SpanKindClient),
5755
tracer.Tag(ext.DBSystem, ext.DBSystemMongoDB),
5856
}
57+
if m.cfg.maxQuerySize != 0 {
58+
b, _ := bson.MarshalExtJSON(evt.Command, false, false)
59+
if m.cfg.maxQuerySize > 0 && len(b) > m.cfg.maxQuerySize {
60+
b = b[:m.cfg.maxQuerySize]
61+
}
62+
opts = append(opts, tracer.Tag(m.cfg.spanName, string(b)))
63+
}
5964
span, _ := tracer.StartSpanFromContext(ctx, m.cfg.spanName, opts...)
6065
key := spanKey{
6166
ConnectionID: evt.ConnectionID,

contrib/go.mongodb.org/mongo-driver.v2/mongo/mongo_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"context"
1010
"fmt"
1111
"os"
12+
"strings"
1213
"testing"
1314
"time"
1415

@@ -80,3 +81,68 @@ func Test(t *testing.T) {
8081
assert.Equal(t, ext.SpanKindClient, s.Tag(ext.SpanKind))
8182
assert.Equal(t, "mongodb", s.Tag(ext.DBSystem))
8283
}
84+
85+
func TestTruncation(t *testing.T) {
86+
getQuery := func(t *testing.T, max int) (string, bool) {
87+
mt := mocktracer.Start()
88+
defer mt.Stop()
89+
90+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
91+
defer cancel()
92+
93+
span, ctx := tracer.StartSpanFromContext(ctx, "mongodb-test")
94+
95+
addr := "mongodb://localhost:27017/?connect=direct"
96+
opts := options.Client()
97+
opts.Monitor = NewMonitor(WithMaxQuerySize(max))
98+
opts.ApplyURI(addr)
99+
client, err := mongo.Connect(opts)
100+
if err != nil {
101+
t.Fatal(err)
102+
}
103+
104+
_, err = client.
105+
Database("test-database").
106+
Collection("test-collection").
107+
UpdateOne(
108+
ctx,
109+
bson.D{{Key: "_id", Value: "68536ec8d906742797f5705a"}},
110+
bson.D{{Key: "$set", Value: map[string]any{"test-item": "test-value"}}},
111+
)
112+
if err != nil {
113+
t.Fatal(err)
114+
}
115+
116+
span.Finish()
117+
118+
spans := mt.FinishedSpans()
119+
value, ok := spans[0].Tag("mongodb.query").(string)
120+
return value, ok
121+
}
122+
123+
t.Run("zero", func(t *testing.T) {
124+
// Should *not* attach the tag.
125+
_, ok := getQuery(t, 0)
126+
assert.False(t, ok)
127+
})
128+
129+
t.Run("positive", func(t *testing.T) {
130+
// Should truncate.
131+
actual, _ := getQuery(t, 50)
132+
assert.Equal(t, actual, `{"update":"test-collection","ordered":true,"lsid":`)
133+
})
134+
135+
t.Run("negative", func(t *testing.T) {
136+
// Should *not* truncate. The actual query contains a random session ID, so we just check the end which is deterministic.
137+
actual, _ := getQuery(t, -1)
138+
wantSuffix := `"u":{"$set":{"test-item":"test-value"}}}]}`
139+
assert.True(t, strings.HasSuffix(actual, `"u":{"$set":{"test-item":"test-value"}}}]}`), "query %q does not end with %q", actual, wantSuffix)
140+
})
141+
142+
t.Run("greater than query size", func(t *testing.T) {
143+
// Should *not* truncate. The actual query contains a random session ID, so we just check the end which is deterministic.
144+
actual, _ := getQuery(t, 1000) // arbitrary value > the size of the query we will be truncating
145+
wantSuffix := `"u":{"$set":{"test-item":"test-value"}}}]}`
146+
assert.True(t, strings.HasSuffix(actual, `"u":{"$set":{"test-item":"test-value"}}}]}`), "query %q does not end with %q", actual, wantSuffix)
147+
})
148+
}

contrib/go.mongodb.org/mongo-driver.v2/mongo/option.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import (
1010
)
1111

1212
type config struct {
13-
serviceName string
14-
spanName string
13+
serviceName string
14+
spanName string
15+
maxQuerySize int
1516
}
1617

1718
// Option describes options for the Mongo integration.
@@ -29,6 +30,7 @@ func (fn OptionFn) apply(cfg *config) {
2930
func defaults(cfg *config) {
3031
cfg.serviceName = instr.ServiceName(instrumentation.ComponentDefault, nil)
3132
cfg.spanName = instr.OperationName(instrumentation.ComponentDefault, nil)
33+
cfg.maxQuerySize = -1
3234
}
3335

3436
// WithService sets the given service name for this integration spans.
@@ -37,3 +39,18 @@ func WithService(name string) OptionFn {
3739
cfg.serviceName = name
3840
}
3941
}
42+
43+
// WithMaxQuerySize sets the maximum query size (in bytes) before queries
44+
// are truncated when attached as a span tag.
45+
//
46+
// If negative (the default), query truncation is disabled and the query
47+
// will always be attached in full.
48+
//
49+
// If zero, traces will not include a query tag.
50+
//
51+
// Defaults to -1.
52+
func WithMaxQuerySize(max int) OptionFn {
53+
return func(cfg *config) {
54+
cfg.maxQuerySize = max
55+
}
56+
}

contrib/go.mongodb.org/mongo-driver/mongo/mongo.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,11 @@ type monitor struct {
4545

4646
func (m *monitor) Started(ctx context.Context, evt *event.CommandStartedEvent) {
4747
hostname, port := peerInfo(evt)
48-
b, _ := bson.MarshalExtJSON(evt.Command, false, false)
4948
opts := []tracer.StartSpanOption{
5049
tracer.SpanType(ext.SpanTypeMongoDB),
5150
tracer.ServiceName(m.cfg.serviceName),
5251
tracer.ResourceName("mongo." + evt.CommandName),
5352
tracer.Tag(ext.DBInstance, evt.DatabaseName),
54-
tracer.Tag(m.cfg.spanName, string(b)),
5553
tracer.Tag(ext.DBType, "mongo"),
5654
tracer.Tag(ext.PeerHostname, hostname),
5755
tracer.Tag(ext.NetworkDestinationName, hostname),
@@ -63,6 +61,13 @@ func (m *monitor) Started(ctx context.Context, evt *event.CommandStartedEvent) {
6361
if !math.IsNaN(m.cfg.analyticsRate) {
6462
opts = append(opts, tracer.Tag(ext.EventSampleRate, m.cfg.analyticsRate))
6563
}
64+
if m.cfg.maxQuerySize != 0 {
65+
b, _ := bson.MarshalExtJSON(evt.Command, false, false)
66+
if m.cfg.maxQuerySize > 0 && len(b) > m.cfg.maxQuerySize {
67+
b = b[:m.cfg.maxQuerySize]
68+
}
69+
opts = append(opts, tracer.Tag(m.cfg.spanName, string(b)))
70+
}
6671
span, _ := tracer.StartSpanFromContext(ctx, m.cfg.spanName, opts...)
6772
key := spanKey{
6873
ConnectionID: evt.ConnectionID,

contrib/go.mongodb.org/mongo-driver/mongo/mongo_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"context"
1010
"fmt"
1111
"os"
12+
"strings"
1213
"testing"
1314
"time"
1415

@@ -136,3 +137,68 @@ func TestAnalyticsSettings(t *testing.T) {
136137
assertRate(t, mt, 0.23, WithAnalyticsRate(0.23))
137138
})
138139
}
140+
141+
func TestTruncation(t *testing.T) {
142+
getQuery := func(t *testing.T, max int) (string, bool) {
143+
mt := mocktracer.Start()
144+
defer mt.Stop()
145+
146+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
147+
defer cancel()
148+
149+
span, ctx := tracer.StartSpanFromContext(ctx, "mongodb-test")
150+
151+
addr := "mongodb://localhost:27017/?connect=direct"
152+
opts := options.Client()
153+
opts.Monitor = NewMonitor(WithMaxQuerySize(max))
154+
opts.ApplyURI(addr)
155+
client, err := mongo.Connect(ctx, opts)
156+
if err != nil {
157+
t.Fatal(err)
158+
}
159+
160+
_, err = client.
161+
Database("test-database").
162+
Collection("test-collection").
163+
UpdateOne(
164+
ctx,
165+
bson.D{{Key: "_id", Value: "68536ec8d906742797f5705a"}},
166+
bson.D{{Key: "$set", Value: map[string]any{"test-item": "test-value"}}},
167+
)
168+
if err != nil {
169+
t.Fatal(err)
170+
}
171+
172+
span.Finish()
173+
174+
spans := mt.FinishedSpans()
175+
value, ok := spans[0].Tag("mongodb.query").(string)
176+
return value, ok
177+
}
178+
179+
t.Run("zero", func(t *testing.T) {
180+
// Should *not* attach the tag.
181+
_, ok := getQuery(t, 0)
182+
assert.False(t, ok)
183+
})
184+
185+
t.Run("positive", func(t *testing.T) {
186+
// Should truncate.
187+
actual, _ := getQuery(t, 50)
188+
assert.Equal(t, actual, `{"update":"test-collection","ordered":true,"lsid":`)
189+
})
190+
191+
t.Run("negative", func(t *testing.T) {
192+
// Should *not* truncate. The actual query contains a random session ID, so we just check the end which is deterministic.
193+
actual, _ := getQuery(t, -1)
194+
wantSuffix := `"u":{"$set":{"test-item":"test-value"}}}]}`
195+
assert.True(t, strings.HasSuffix(actual, `"u":{"$set":{"test-item":"test-value"}}}]}`), "query %q does not end with %q", actual, wantSuffix)
196+
})
197+
198+
t.Run("greater than query size", func(t *testing.T) {
199+
// Should *not* truncate. The actual query contains a random session ID, so we just check the end which is deterministic.
200+
actual, _ := getQuery(t, 1000) // arbitrary value > the size of the query we will be truncating
201+
wantSuffix := `"u":{"$set":{"test-item":"test-value"}}}]}`
202+
assert.True(t, strings.HasSuffix(actual, `"u":{"$set":{"test-item":"test-value"}}}]}`), "query %q does not end with %q", actual, wantSuffix)
203+
})
204+
}

contrib/go.mongodb.org/mongo-driver/mongo/option.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type config struct {
1515
serviceName string
1616
spanName string
1717
analyticsRate float64
18+
maxQuerySize int
1819
}
1920

2021
// Option describes options for the Mongo integration.
@@ -33,6 +34,7 @@ func defaults(cfg *config) {
3334
cfg.serviceName = instr.ServiceName(instrumentation.ComponentDefault, nil)
3435
cfg.spanName = instr.OperationName(instrumentation.ComponentDefault, nil)
3536
cfg.analyticsRate = instr.AnalyticsRate(false)
37+
cfg.maxQuerySize = -1
3638
}
3739

3840
// WithService sets the given service name for this integration spans.
@@ -64,3 +66,18 @@ func WithAnalyticsRate(rate float64) OptionFn {
6466
}
6567
}
6668
}
69+
70+
// WithMaxQuerySize sets the maximum query size (in bytes) before queries
71+
// are truncated when attached as a span tag.
72+
//
73+
// If negative (the default), query truncation is disabled and the query
74+
// will always be attached in full.
75+
//
76+
// If zero, traces will not include a query tag.
77+
//
78+
// Defaults to -1.
79+
func WithMaxQuerySize(max int) OptionFn {
80+
return func(cfg *config) {
81+
cfg.maxQuerySize = max
82+
}
83+
}

0 commit comments

Comments
 (0)