Skip to content

StartupQueue plugin loses enrichment closure on replay #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
richerm opened this issue Apr 16, 2025 · 9 comments
Closed

StartupQueue plugin loses enrichment closure on replay #132

richerm opened this issue Apr 16, 2025 · 9 comments
Assignees

Comments

@richerm
Copy link

richerm commented Apr 16, 2025

Describe the bug

We are trying to use the enrichment closure for Track events. The incoming event is null IF the StartupQueue hasn't completed yet (meaning it'll replay it later). If I thread sleep for say a few seconds, then track the event, the enrichment closure is fire.

I believe this is because the startup plugin does not have the enrichment closure with it so when it plays it back it loses the original closure.

To Reproduce
Steps to reproduce the behavior:

  1. Start the Analytics with a config and immediately call Track with an enrichment closure

Expected behavior
The enrichment closure RawEvent is not null.

Platform (please complete the following information):

  • Library Version in use: 2.5.1
  • Platform being tested: Windows, Linux
  • Integrations in use: N/A

Additional context

Track Call

var analyticsClient = scope.ServiceProvider.GetService<Analytics>();
// System.Threading.Thread.Sleep(5000);   // This gives time for it to startup (no replay needed)
analyticsClient.Track(
    "TestEvent",
    properties,
    (RawEvent evt) =>
    {
        evt.UserId = "12345"; // explodes if StartupQueue plugin stores an event for replay.
    }
);

Scoped Configuration:

builder.Services.AddScoped<Analytics>(
    (provider) =>
    {
        var config = new Configuration(
            writeKey: builder.Configuration.GetSection("Segment")["WriteKey"],
            storageProvider: new InMemoryStorageProvider(),
            flushAt: 1,
            eventPipelineProvider: new SyncEventPipelineProvider()
        );

        var analytics = new Analytics(config);

        return analytics;
    }
);

Stock Plugins Loaded:

Before - StartupQueue
Before - ContextPlugin
Destination - SegmentDestination
@wenxi-zeng
Copy link
Contributor

hi @richerm, thanks for reporting this issue. this is in our roadmap. will get back to you once we have a release for it.

@richerm
Copy link
Author

richerm commented Apr 16, 2025

@wenxi-zeng - thanks - In the meantime is there a way I can check the 'state' or system status of the Analytics class? Basically I can block until it is 'ready'? This would save an arbitrary wait in code.

if (analyticsClient.state != SystemState.Running)
   // wait

@wenxi-zeng
Copy link
Contributor

@richerm unfortunately no. the state is marked as internal. another workaround would be custom plugin. see this comment for example. not sure if that'd work for your use case though. I'll also try to escalate this issue.

@richerm
Copy link
Author

richerm commented Apr 16, 2025

@wenxi-zeng Yes I saw that comment when searching earlier. Unfortunately, the enrichment I'm doing (in addition to user id) has contextual information and the serialize it to a property and to deserialize in a plugin and move to context is a pretty heavy workaround. Hopefully this gets addressed soon. In the meantime, I'm going to switch to a singleton model vs scoped with the caveats noted in the docs.

@wenxi-zeng
Copy link
Contributor

@richerm sounds good! I have prioritized a fix for this issue. should have a release out next monday.

@wenxi-zeng
Copy link
Contributor

hi @richerm, this issue should be fixed in the latest release 2.5.2. please have a try. thanks!

@richerm
Copy link
Author

richerm commented Apr 28, 2025

Awesome! Thank-you for the quick turn-around!

@richerm
Copy link
Author

richerm commented Apr 30, 2025

@wenxi-zeng

I received this error on writing to storage because the Enrichment property is marked as serializable. Is that expected behaviour?

The unsupported member type is located on type 'System.Func`2[Segment.Analytics.RawEvent,Segment.Analytics.RawEvent]'. Path: $.Enrichment.

[11:59:43 ERR] Segment.io: Error writing events to storage.
System.NotSupportedException: Serialization and deserialization of 'System.Func`2[[Segment.Analytics.RawEvent, Segment.Analytics.CSharp, Version=2.5.2.0, Culture=neutral, PublicKeyToken=null],[Segment.Analytics.RawEvent, Segment.Analytics.CSharp, Version=2.5.2.0, Culture=neutral, PublicKeyToken=null]]' instances is not supported. The unsupported member type is located on type 'System.Func`2[Segment.Analytics.RawEvent,Segment.Analytics.RawEvent]'. Path: $.Enrichment.
 ---> System.NotSupportedException: Serialization and deserialization of 'System.Func`2[[Segment.Analytics.RawEvent, Segment.Analytics.CSharp, Version=2.5.2.0, Culture=neutral, PublicKeyToken=null],[Segment.Analytics.RawEvent, Segment.Analytics.CSharp, Version=2.5.2.0, Culture=neutral, PublicKeyToken=null]]' instances is not supported.
   at System.Text.Json.Serialization.Converters.UnsupportedTypeConverter`1.Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ThrowNotSupportedException(WriteStack& state, Exception innerException)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Serialize(Utf8JsonWriter writer, T& rootValue, Object rootValueBoxed)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsObject(Utf8JsonWriter writer, Object rootValue)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Serialize(Utf8JsonWriter writer, T& rootValue, Object rootValueBoxed)
   at System.Text.Json.JsonSerializer.WriteString[TValue](TValue& value, JsonTypeInfo`1 jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)
   at Segment.Serialization.JsonUtility.ToJson(Object value, Boolean pretty)
   at Segment.Analytics.Utilities.SyncEventPipeline.<Write>b__22_0()

@wenxi-zeng
Copy link
Contributor

hi @richerm, no, this is not expected. I just released a fix. please give 2.5.3 a try. you shouldn't see this error anymore

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants