Beispiel #1
0
        protected override async Task EmitBatchAsync(IEnumerable <LogEvent> events)
        {
            // We do not need synchronization in this method since it is only called from a single thread by the PeriodicBatchSink.
            try
            {
                await EnsureInitialized();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error initializing log stream. No logs will be sent to AWS CloudWatch.");
                Console.WriteLine(ex);
                return;
            }

            try
            {
                // log events need to be ordered by timestamp within a single bulk upload to CloudWatch
                var logEvents =
                    events.OrderBy(e => e.Timestamp)
                    .Select(e => new InputLogEvent {
                    Message = renderer.RenderLogEvent(e), Timestamp = e.Timestamp.UtcDateTime
                })
                    .ToList();

                // creates the request to upload a new event to CloudWatch
                PutLogEventsRequest putEventsRequest = new PutLogEventsRequest(options.LogGroupName, logStreamName, logEvents)
                {
                    SequenceToken = nextSequenceToken
                };

                // actually upload the event to CloudWatch
                var putLogEventsResponse = await cloudWatchClient.PutLogEventsAsync(putEventsRequest);

                // validate success
                if (!putLogEventsResponse.HttpStatusCode.IsSuccessStatusCode())
                {
                    // let's start a new log stream in case anything went wrong with the upload
                    UpdateLogStreamName();
                    throw new Exception(
                              $"Tried to send logs, but failed with status code '{putLogEventsResponse.HttpStatusCode}' and data '{putLogEventsResponse.ResponseMetadata.FlattenedMetaData()}'.");
                }

                // remember the next sequence token, which is required
                nextSequenceToken = putLogEventsResponse.NextSequenceToken;
            }
            catch (Exception ex)
            {
                try
                {
                    traceLogger.Error("Error sending logs. No logs will be sent to AWS CloudWatch. Error was {0}", ex);
                }
                catch (Exception)
                {
                    // we event failed to log to the trace logger - giving up trying to put something out
                }
            }
        }
        /// <summary>
        /// Transforms Serilog's LogEvent into AWS CloudWatch InputLogEvent.
        /// </summary>
        /// <param name="event">The event itself.</param>
        /// <returns></returns>
        private InputLogEvent TransformToInputLogEvent(LogEvent @event)
        {
            var message       = renderer.RenderLogEvent(@event);
            var messageLength = System.Text.Encoding.UTF8.GetByteCount(message);

            if (messageLength > MaxLogEventSize)
            {
                // truncate event message
                Debugging.SelfLog.WriteLine("Truncating log event with length of {0}",
                                            messageLength);
                message = message.Substring(0, MaxLogEventSize);
            }
            return(new InputLogEvent
            {
                Message = message,
                Timestamp = @event.Timestamp.UtcDateTime
            });
        }
Beispiel #3
0
        /// <summary>
        /// Emit a batch of log events, running asynchronously.
        /// </summary>
        /// <param name="events">The events to emit.</param>
        protected override async Task EmitBatchAsync(IEnumerable <LogEvent> events)
        {
            // We do not need synchronization in this method since it is only called from a single thread by the PeriodicBatchSink.

            if (events?.Count() == 0)
            {
                return;
            }

            try
            {
                await EnsureInitializedAsync();
            }
            catch (Exception ex)
            {
                Debugging.SelfLog.WriteLine("Error initializing log stream. No logs will be sent to AWS CloudWatch. Exception was {0}.", ex);
                return;
            }

            try
            {
                var logEvents =
                    new Queue <InputLogEvent>(events
                                              .OrderBy(e => e.Timestamp) // log events need to be ordered by timestamp within a single bulk upload to CloudWatch
                                              .Select(                   // transform
                                                  @event =>
                {
                    var message       = renderer.RenderLogEvent(@event);
                    var messageLength = System.Text.Encoding.UTF8.GetByteCount(message);
                    if (messageLength > MaxLogEventSize)
                    {
                        // truncate event message
                        Debugging.SelfLog.WriteLine("Truncating log event with length of {0}", messageLength);
                        message = message.Substring(0, MaxLogEventSize);
                    }
                    return(new InputLogEvent
                    {
                        Message = message,
                        Timestamp = @event.Timestamp.UtcDateTime
                    });
                }));

                while (logEvents.Count > 0)
                {
                    var batch = CreateBatch(logEvents);

                    await PublishBatchAsync(batch);
                }
            }
            catch (Exception ex)
            {
                try
                {
                    Debugging.SelfLog.WriteLine("Error sending logs. No logs will be sent to AWS CloudWatch. Error was {0}", ex);
                }
                catch (Exception)
                {
                    // we even failed to log to the trace logger - giving up trying to put something out
                }
            }
        }