You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MongoDB C#驱动中为序列化/反序列化操作添加Activity?

为MongoDB序列化/反序列化操作添加Activity追踪

方案1:基于自定义ClassMap注入追踪逻辑

针对你已在使用的BsonClassMap,可以通过包装默认序列化器的方式,为指定类的序列化/反序列化操作添加Activity:

首先创建通用的追踪序列化器包装类:

public class ActivityTrackingSerializer<T> : IBsonSerializer<T>
{
    private readonly IBsonSerializer<T> _innerSerializer;

    public ActivityTrackingSerializer(IBsonSerializer<T> innerSerializer)
    {
        _innerSerializer = innerSerializer;
    }

    public T Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        using var activity = new Activity($"MongoDB Deserialize: {typeof(T).Name}").Start();
        activity.AddTag("mongo.type", typeof(T).FullName);
        try
        {
            return _innerSerializer.Deserialize(context, args);
        }
        catch (Exception ex)
        {
            activity.SetStatus(ActivityStatusCode.Error);
            activity.AddTag("error.message", ex.Message);
            throw;
        }
    }

    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, T value)
    {
        using var activity = new Activity($"MongoDB Serialize: {typeof(T).Name}").Start();
        activity.AddTag("mongo.type", typeof(T).FullName);
        try
        {
            _innerSerializer.Serialize(context, args, value);
        }
        catch (Exception ex)
        {
            activity.SetStatus(ActivityStatusCode.Error);
            activity.AddTag("error.message", ex.Message);
            throw;
        }
    }

    // 转发IBsonSerializer接口的其他成员实现
    public Type ValueType => _innerSerializer.ValueType;
    public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context, args);
    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) => Serialize(context, args, (T)value);
}

然后在ClassMap注册时替换默认序列化器:

BsonClassMap.RegisterClassMap<MyClass>(cm =>
{
    cm.AutoMap();
    cm.SetIgnoreExtraElements(true);
    
    // 为类的所有属性添加追踪
    foreach (var memberMap in cm.AllMemberMaps)
    {
        var originalSerializer = memberMap.GetSerializer();
        memberMap.SetSerializer(new ActivityTrackingSerializer<object>(originalSerializer));
    }
    
    // 或者为整个类的根序列化添加追踪
    var classSerializer = cm.GetSerializer();
    cm.SetSerializer(new ActivityTrackingSerializer<MyClass>(classSerializer));
});

方案2:全局注册追踪逻辑(覆盖所有类型)

如果需要为所有MongoDB序列化/反序列化操作添加Activity,可以自定义序列化器注册表实现全局拦截:

public class ActivityTrackingSerializerRegistry : IBsonSerializerRegistry
{
    private readonly IBsonSerializerRegistry _innerRegistry;

    public ActivityTrackingSerializerRegistry(IBsonSerializerRegistry innerRegistry)
    {
        _innerRegistry = innerRegistry;
    }

    public IBsonSerializer GetSerializer(Type type)
    {
        var innerSerializer = _innerRegistry.GetSerializer(type);
        // 避免重复包装序列化器
        if (innerSerializer.GetType().IsGenericType && 
            innerSerializer.GetType().GetGenericTypeDefinition() == typeof(ActivityTrackingSerializer<>))
            return innerSerializer;
        
        var genericWrapper = typeof(ActivityTrackingSerializer<>).MakeGenericType(type);
        return (IBsonSerializer)Activator.CreateInstance(genericWrapper, innerSerializer);
    }

    public IBsonSerializer<T> GetSerializer<T>()
    {
        var innerSerializer = _innerRegistry.GetSerializer<T>();
        if (innerSerializer is ActivityTrackingSerializer<T>)
            return innerSerializer;
        
        return new ActivityTrackingSerializer<T>(innerSerializer);
    }
}

// 注册全局序列化器注册表
BsonSerializer.RegisterSerializerRegistry(new ActivityTrackingSerializerRegistry(BsonSerializer.SerializerRegistry));

与MongoDB诊断扩展包联动

你提到的诊断包已覆盖MongoDB核心操作(查询、写入等),可以修改追踪序列化器的Activity创建逻辑,让序列化操作作为核心操作的子Activity:

// 在ActivityTrackingSerializer的Serialize/Deserialize方法中调整Activity创建逻辑
using var activity = new Activity($"MongoDB Serialize: {typeof(T).Name}")
{
    ParentId = Activity.Current?.Id
}.Start();

这样分布式追踪链路中,序列化/反序列化的耗时会被关联到对应的MongoDB命令操作下,完整展示全链路耗时。

注意事项

  • 性能评估:高并发场景下,每个序列化/反序列化创建Activity会带来一定开销,可通过开关控制是否启用。
  • 异常追踪:Activity中记录的异常标签可辅助排查序列化失败问题。
  • 避免重复包装:全局注册时需判断序列化器是否已被包装,防止无限嵌套。

内容的提问来源于stack exchange,提问作者TheoM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:52:44