-
Notifications
You must be signed in to change notification settings - Fork 473
Description
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