protected override async Task EmitBatchAsync(IEnumerable <LogEvent> events) { var detailedLog = new NewRelicLogPayload(); detailedLog.common.attributes.Add("application", ApplicationName); var eventList = events.ToList(); foreach (var logEvent in eventList) { try { var logItem = new NewRelicLogItem { timestamp = UnixTimestampFromDateTime(logEvent.Timestamp.UtcDateTime), message = logEvent.RenderMessage(FormatProvider), attributes = new Dictionary <string, object> { { "level", logEvent.Level.ToString() }, { "stack_trace", logEvent.Exception?.StackTrace ?? "" }, } }; foreach (var prop in logEvent.Properties) { if (prop.Key.Equals("newrelic.linkingmetadata", StringComparison.InvariantCultureIgnoreCase)) { UnrollNewRelicDistributedTraceAttributes(logItem, prop.Value); } else { logItem.attributes.Add(prop.Key, NewRelicPropertyFormatter.Simplify(prop.Value)); } } detailedLog.logs.Add(logItem); } catch (Exception ex) { SelfLog.WriteLine("Log event could not be formatted and was dropped: {0} {1}", ex.Message, ex.StackTrace); } } var body = Serialize(new List <object> { detailedLog }, eventList.Count); await Task.Run(() => { try { SendToNewRelicLogs(body); } catch (Exception ex) { SelfLog.WriteLine("Event batch could not be sent to NewRelic Logs and was dropped: {0} {1}", ex.Message, ex.StackTrace); } }) .ConfigureAwait(false); }
private static void UnrollNewRelicDistributedTraceAttributes(NewRelicLogItem logItem, LogEventPropertyValue propValue) { if (!(propValue is DictionaryValue newRelicProperties)) { return; } foreach (var newRelicProperty in newRelicProperties.Elements) { logItem.attributes.Add( NewRelicPropertyFormatter.Simplify(newRelicProperty.Key).ToString(), NewRelicPropertyFormatter.Simplify(newRelicProperty.Value)); } }