Describe the bug
I am using the "snowplow.tracker" Nuget package in my dotnet core project. when I deployed my code on the server with the container, my server restarted every 2 minutes with the following error.
Occurred exception
Unhandled exception. System.ArgumentException: An item with the same key has already been added. Key: stm at System.Collections.Generic.Dictionary
2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at System.Collections.Generic.Dictionary
2.Add(TKey key, TValue value)
at Snowplow.Tracker.Endpoints.SnowplowHttpCollectorEndpoint.AddSendTimestamp(List1 payloadList) at Snowplow.Tracker.Endpoints.SnowplowHttpCollectorEndpoint.SendPostAsync(List
1 itemList) at Snowplow.Tracker.Endpoints.SnowplowHttpCollectorEndpoint.Send(List`1 itemList) at Snowplow.Tracker.Emitters.AsyncEmitter.loop()
My code
public class SnowplowService : ISnowplowService
{
private readonly SnowplowConfig _configuration;
private readonly ILogger<SnowplowService> _logger;
public SnowplowService(IOptions<SnowplowConfig> configuration,
ILogger<SnowplowService> logger)
{
this._configuration = configuration.Value;
this._logger = logger;
}
public async Task<SnowplowResponse> SendEvent(SnowplowRequest request)
{
var response = new SnowplowResponse();
var tracker = Tracker.Instance;
var logger = new ConsoleLogger();
var endpoint = new SnowplowHttpCollectorEndpoint
(host: _configuration.BaseAddress, port: _configuration.Port, l: logger,
method: Snowplow.Tracker.Endpoints.HttpMethod.POST, protocol: HttpProtocol.HTTP);
try
{
var queue = new InMemoryBlockingQueue();
var emitter = new AsyncEmitter(endpoint, queue, l: logger);
var subject = new Subject().SetPlatform(Platform.Srv).SetLang(_configuration.Language);
if (tracker.Started == false)
{
tracker.Start(
emitter: emitter,
subject: subject,
trackerNamespace: _configuration.TrackerNamespace,
appId: _configuration.AppId,
encodeBase64: false,
l: logger);
}
if (tracker.Started)
{
var dataKeyValues = new Dictionary<string, object>
{
{ "userId", request.UserId! },
{ "eventName", request.EventName },
{ "eventTime", request.EventTime },
{ "eventData", Utility.ConvertToDictionaryObject(request: request.EventData) }
};
var eventKeyValues = new Dictionary<string, object>()
{
{ "vendor", _configuration.Vendor! },
{ "model", request.SnowplowRequestName!},
};
var eventData = new SelfDescribingJson
($"iglu:{_configuration.Vendor}/{request.SnowplowRequestName!}/jsonschema/1-0-0", dataKeyValues);
var requestItem = new List<IContext>();
var context = new GenericContext()
.SetSchema($"iglu:com.vendor/meta/jsonschema/1-0-0")
.AddDict(eventKeyValues)
.Build();
requestItem.Add(item: context);
var trackingItem =
new SelfDescribing()
.SetEventData(eventData: eventData)
.SetCustomContext(customContexts: requestItem)
.Build();
tracker.Track(newEvent: trackingItem);
}
response = new SnowplowResponse(true, "");
}
catch (Exception ex)
{
response = new SnowplowResponse(false, ex.Message);
}
return response;
}
}
internal static Dictionary<string, object> ConvertToDictionaryObject<T>(T request) where T : class
{
var result = new Dictionary<string, object>();
var properties = request.GetType().GetProperties();
foreach (var item in properties)
{
var key = item.Name.ToLower().Trim();
var value = item.GetValue(request);
if (result.ContainsKey(key) == false)
result.Add(key: key, value: value!);
}
return result;
}