private void OnRawFeedMessageReceived(object sender, RawFeedMessageEventArgs e) { if (RawFeedMessageReceived == null) { return; } var timerOptionsOnRawFeedMessageReceived = new TimerOptions { Context = "FeedExt", Name = "OnRawFeedMessageReceived", MeasurementUnit = Unit.Items }; using var t = MetricsRoot.Measure.Timer.Time(timerOptionsOnRawFeedMessageReceived, $"{e.MessageInterest} - {e.FeedMessage?.EventId}"); try { RawFeedMessageReceived?.Invoke(sender, e); var requestId = e.FeedMessage?.RequestId == null ? null : $" ({e.FeedMessage.RequestId})"; Log.LogInformation($"Dispatching raw feed message [{e.MessageInterest}]: {e.FeedMessage?.GetType().Name} for event {e.FeedMessage?.EventId}{requestId} took {t.Elapsed.TotalMilliseconds} ms."); } catch (Exception ex) { Log.LogError(ex, $"Error dispatching raw feed message [{e.MessageInterest}] for {e.RoutingKey} and {e.FeedMessage?.EventId}. Took {t.Elapsed.TotalMilliseconds} ms."); } }
private void OnRawFeedMessageReceived(object sender, RawFeedMessageEventArgs e) { try { RawFeedMessageReceived?.Invoke(sender, e); } catch (Exception ex) { Log.Error($"Error dispatching raw feed message for {e.RoutingKey} and {e.FeedMessage?.EventId}", ex); } }
/// <summary> /// Handles the message received event /// </summary> /// <param name="sender">The <see cref="object"/> representation of the event sender</param> /// <param name="eventArgs">A <see cref="BasicDeliverEventArgs"/> containing event information</param> private void consumer_OnReceived(object sender, BasicDeliverEventArgs eventArgs) { if (eventArgs.Body == null || !eventArgs.Body.Any()) { var body = eventArgs.Body == null ? "null" : "empty"; ExecutionLog.LogWarning($"A message with {body} body received. Aborting message processing"); return; } var receivedAt = SdkInfo.ToEpochTime(DateTime.Now); // NOT used for GetRawMessage() var sessionName = _interest == null ? "system" : _interest.Name; string messageBody = null; FeedMessage feedMessage; IProducer producer; string messageName; try { using (var t = SdkMetricsFactory.MetricsRoot.Measure.Timer.Time(new TimerOptions { Context = "FEED", Name = "Message deserialization time", MeasurementUnit = Unit.Items })) { t.TrackUserValue(eventArgs.RoutingKey); messageBody = Encoding.UTF8.GetString(eventArgs.Body); feedMessage = _deserializer.Deserialize(new MemoryStream(eventArgs.Body)); producer = _producerManager.Get(feedMessage.ProducerId); messageName = feedMessage.GetType().Name; if (t.Elapsed.TotalMilliseconds > 300) { _keyParser.TryGetSportId(eventArgs.RoutingKey, messageName, out var sportId); var marketCounts = 0; var outcomeCounts = 0; if (feedMessage is odds_change oddsChange) { marketCounts = oddsChange.odds?.market?.Length ?? 0; outcomeCounts = oddsChange.odds?.market?.Where(w => w.outcome != null).SelectMany(list => list.outcome).Count() ?? 0; } if (feedMessage is bet_settlement betSettlement) { marketCounts = betSettlement.outcomes?.Length ?? 0; outcomeCounts = betSettlement.outcomes?.Where(w => w.Items != null).SelectMany(list => list.Items).Count() ?? 0; } ExecutionLog.LogDebug($"Deserialization of {feedMessage.GetType().Name} for {feedMessage.EventId} ({feedMessage.GeneratedAt}) and sport {sportId} took {t.Elapsed.TotalMilliseconds}ms. Markets={marketCounts}, Outcomes={outcomeCounts}"); } } if (producer.IsAvailable && !producer.IsDisabled) { FeedLog.LogInformation($"<~> {sessionName} <~> {eventArgs.RoutingKey} <~> {messageBody}"); } else { if (FeedLog.IsEnabled(LogLevel.Debug)) { FeedLog.LogDebug($"<~> {sessionName} <~> {eventArgs.RoutingKey} <~> {producer.Id}"); } } if (eventArgs.BasicProperties?.Headers != null) { feedMessage.SentAt = eventArgs.BasicProperties.Headers.ContainsKey("timestamp_in_ms") ? long.Parse(eventArgs.BasicProperties.Headers["timestamp_in_ms"].ToString()) : feedMessage.GeneratedAt; } feedMessage.ReceivedAt = receivedAt; SdkMetricsFactory.MetricsRoot.Measure.Meter.Mark(new MeterOptions { Context = "FEED", Name = "Message received" }, MetricTags.Empty, messageName); } catch (DeserializationException ex) { ExecutionLog.LogError($"Failed to parse message. RoutingKey={eventArgs.RoutingKey} Message: {messageBody}", ex); SdkMetricsFactory.MetricsRoot.Measure.Meter.Mark(new MeterOptions { Context = "FEED", Name = "Message deserialization exception" }, MetricTags.Empty, eventArgs.RoutingKey); RaiseDeserializationFailed(eventArgs.Body); return; } catch (Exception ex) { ExecutionLog.LogError($"Error consuming feed message. RoutingKey={eventArgs.RoutingKey} Message: {messageBody}", ex); SdkMetricsFactory.MetricsRoot.Measure.Meter.Mark(new MeterOptions { Context = "FEED", Name = "Exception consuming feed message" }, MetricTags.Empty, eventArgs.RoutingKey); RaiseDeserializationFailed(eventArgs.Body); return; } // send RawFeedMessage if needed try { if (producer.IsAvailable && !producer.IsDisabled) { //ExecutionLog.LogDebug($"Raw msg [{_interest}]: {feedMessage.GetType().Name} for event {feedMessage.EventId}."); var args = new RawFeedMessageEventArgs(eventArgs.RoutingKey, feedMessage, sessionName); RawFeedMessageReceived?.Invoke(this, args); } } catch (Exception e) { ExecutionLog.LogError($"Error dispatching raw message for {feedMessage.EventId}", e); } // continue normal processing if (!_producerManager.Exists(feedMessage.ProducerId)) { ExecutionLog.LogWarning($"A message for producer which is not defined was received. Producer={feedMessage.ProducerId}"); return; } if (!_useReplay && (!producer.IsAvailable || producer.IsDisabled)) { ExecutionLog.LogDebug($"A message for producer which is disabled was received. Producer={producer}, MessageType={messageName}"); return; } ExecutionLog.LogInformation($"Message received. Message=[{feedMessage}]."); if (feedMessage.IsEventRelated) { if (!string.IsNullOrEmpty(eventArgs.RoutingKey) && _keyParser.TryGetSportId(eventArgs.RoutingKey, messageName, out var sportId)) { feedMessage.SportId = sportId; } else { ExecutionLog.LogWarning($"Failed to parse the SportId from the routing key. RoutingKey={eventArgs.RoutingKey}, message=[{feedMessage}]. SportId will not be set."); } } RaiseMessageReceived(feedMessage, eventArgs.Body); }
/// <summary> /// Handles the message received event /// </summary> /// <param name="sender">The <see cref="object"/> representation of the event sender</param> /// <param name="eventArgs">A <see cref="BasicDeliverEventArgs"/> containing event information</param> private void consumer_OnReceived(object sender, BasicDeliverEventArgs eventArgs) { if (eventArgs.Body == null || !eventArgs.Body.Any()) { ExecutionLog.WarnFormat("A message with {0} body received. Aborting message processing", eventArgs.Body == null ? "null" : "empty"); return; } var receivedAt = SdkInfo.ToEpochTime(DateTime.Now); // NOT used for GetRawMessage() var sessionName = _interest == null ? "system" : _interest.Name; string messageBody = null; FeedMessage feedMessage; try { if (FeedLog.IsDebugEnabled) { messageBody = Encoding.UTF8.GetString(eventArgs.Body); FeedLog.Debug($"<~> {sessionName} <~> {eventArgs.RoutingKey} <~> {messageBody}"); } else { FeedLog.Info(eventArgs.RoutingKey); } feedMessage = _deserializer.Deserialize(new MemoryStream(eventArgs.Body)); if (eventArgs.BasicProperties?.Headers != null) { feedMessage.SentAt = eventArgs.BasicProperties.Headers.ContainsKey("timestamp_in_ms") ? long.Parse(eventArgs.BasicProperties.Headers["timestamp_in_ms"].ToString()) : feedMessage.GeneratedAt; } feedMessage.ReceivedAt = receivedAt; } catch (DeserializationException ex) { ExecutionLog.Error($"Failed to parse message. RoutingKey={eventArgs.RoutingKey} Message: {messageBody}", ex); Metric.Context("RABBIT").Meter("RabbitMqMessageReceiver->DeserializationException", Unit.Calls).Mark(); RaiseDeserializationFailed(eventArgs.Body); return; } // send RawFeedMessage if needed try { //ExecutionLog.Debug($"Raw msg [{_interest}]: {feedMessage.GetType().Name} for event {feedMessage.EventId}."); var args = new RawFeedMessageEventArgs(eventArgs.RoutingKey, feedMessage, sessionName); RawFeedMessageReceived?.Invoke(this, args); } catch (Exception e) { ExecutionLog.Error($"Error dispatching raw message for {feedMessage.EventId}", e); } // continue normal processing if (!_producerManager.Exists(feedMessage.ProducerId)) { ExecutionLog.Warn($"A message for producer which is not defined was received. Producer={feedMessage.ProducerId}"); return; } var producer = _producerManager.Get(feedMessage.ProducerId); var messageName = feedMessage.GetType().Name; if (!_useReplay && (!producer.IsAvailable || producer.IsDisabled)) { ExecutionLog.Debug($"A message for producer which is disabled was received. Producer={producer}, MessageType={messageName}"); return; } ExecutionLog.Info($"Message received. Message=[{feedMessage}]."); if (feedMessage.IsEventRelated) { URN sportId; if (!string.IsNullOrEmpty(eventArgs.RoutingKey) && _keyParser.TryGetSportId(eventArgs.RoutingKey, messageName, out sportId)) { feedMessage.SportId = sportId; } else { ExecutionLog.Warn($"Failed to parse the SportId from the routing key. RoutingKey={eventArgs.RoutingKey}, message=[{feedMessage}]. SportId will not be set."); } } Metric.Context("RABBIT").Meter("RabbitMqMessageReceiver", Unit.Items).Mark(messageName); RaiseMessageReceived(feedMessage, eventArgs.Body); }