[BUG]: MongoDB query span tag should be truncated
Tracer Version(s)
v2.0.0
Go Version(s)
1.24.4
Bug Report
The MongoDB command is directly serialized as the mongodb.query span tag, without any truncation. We've run into situations at Rippling where this command can be quite large (e.g. writing 100 1MB documents via a BulkWrite call produces a 100MB mongodb.query span tag).
There is prior art for truncating raw queries, e.g. the ElasticSearch module truncates request/response tags to 5KB. Alternatively, the SQL modules like pgx don't truncate, but those queries would rarely include raw data and therefore should be much smaller in size (in theory).
I'd propose making this configurable and can open a PR if the DataDog team is interested (draft PR here).
Reproduction Code
The following code instruments a MongoDB update and logs the spans. You'll see a large span in the logs.
package main
import (
"context"
"runtime"
"strings"
"testing"
mongotrace "github.com/DataDog/dd-trace-go/contrib/go.mongodb.org/mongo-driver/v2/mongo"
ddotel "github.com/DataDog/dd-trace-go/v2/ddtrace/opentelemetry"
"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type logAdapter struct{ Logger *zerolog.Logger }
var _ tracer.Logger = &logAdapter{}
func (l *logAdapter) Log(msg string) {
l.Logger.Info().Msg(msg)
}
func TestRepro(t *testing.T) {
logger := zerolog.New(zerolog.NewTestWriter(t))
tp := ddotel.NewTracerProvider(
tracer.WithLogger(&logAdapter{Logger: &logger}),
tracer.WithDebugMode(true),
tracer.WithLogStartup(false),
)
tr := tp.Tracer("demo")
ctx, span := tr.Start(context.Background(), "HandleEvent")
defer span.End()
opts := options.Client().ApplyURI("mongodb://localhost:9572/?replicaSet=rs0&directConnection=true")
opts.Monitor = mongotrace.NewMonitor(
mongotrace.WithService("testing"),
)
client, err := mongo.Connect(t.Context(), opts)
require.NoError(t, err)
db := client.Database("tests")
col := db.Collection("test_collection")
n := 100
models := make([]mongo.WriteModel, 0, n)
for range n {
models = append(models, mongo.NewUpdateManyModel().
SetFilter(bson.D{{Key: "_id", Value: "68536ec8d906742797f5705a"}}).
SetUpdate(bson.D{{Key: "$set", Value: map[string]any{"value": strings.Repeat("1", 1000)}}}).
SetUpsert(true),
)
}
_, err = col.BulkWrite(ctx, models, options.BulkWrite().SetOrdered(false))
require.NoError(t, err)
runtime.GC()
var m runtime.MemStats
runtime.ReadMemStats(&m)
logger.Info().Msgf("Memory: %v", m.Alloc)
}
Error Logs
n/a
Go Env Output
n/a
Thanks for reaching out and for the contribution, @colinking. Please open the PR in our repository and our IDM team will review it.
Thanks @darccio. I've opened a PR here: https://github.com/DataDog/dd-trace-go/pull/3679