/// <summary> /// Creates and Allocates resources for message trasnmission /// </summary> /// <returns></returns> /// private async Task LogEventTransmissionSetup(CancellationToken token) { try { var logGroupResponse = await _client.DescribeLogGroupsAsync(new DescribeLogGroupsRequest { LogGroupNamePrefix = _config.LogGroup }, token).ConfigureAwait(false); if (logGroupResponse.LogGroups.FirstOrDefault(x => string.Equals(x.LogGroupName, _config.LogGroup, StringComparison.Ordinal)) == null) { await _client.CreateLogGroupAsync(new CreateLogGroupRequest { LogGroupName = _config.LogGroup }, token); } _currentStreamName = DateTime.Now.ToString("yyyy/MM/ddTHH.mm.ss") + " - " + _config.LogStreamNameSuffix; var streamResponse = await _client.CreateLogStreamAsync(new CreateLogStreamRequest { LogGroupName = _config.LogGroup, LogStreamName = _currentStreamName }, token).ConfigureAwait(false); _repo = new LogEventBatch(_config.LogGroup, _currentStreamName, Convert.ToInt32(_config.BatchPushInterval.TotalSeconds), _config.BatchSizeInBytes); } catch (Exception e) { // TODO how to log ? LogLibraryError(e); throw; } }
/// <summary> /// Creates and Allocates resources for message trasnmission /// </summary> /// <returns></returns> private async Task <string> LogEventTransmissionSetup(CancellationToken token) { string serviceURL = GetServiceUrl(); if (!_config.DisableLogGroupCreation) { var logGroupResponse = await _client.DescribeLogGroupsAsync(new DescribeLogGroupsRequest { LogGroupNamePrefix = _config.LogGroup }, token).ConfigureAwait(false); if (!IsSuccessStatusCode(logGroupResponse)) { LogLibraryServiceError(new System.Net.WebException($"Lookup LogGroup {_config.LogGroup} returned status: {logGroupResponse.HttpStatusCode}"), serviceURL); } if (logGroupResponse.LogGroups.FirstOrDefault(x => string.Equals(x.LogGroupName, _config.LogGroup, StringComparison.Ordinal)) == null) { var createGroupResponse = await _client.CreateLogGroupAsync(new CreateLogGroupRequest { LogGroupName = _config.LogGroup }, token).ConfigureAwait(false); if (!IsSuccessStatusCode(createGroupResponse)) { LogLibraryServiceError(new System.Net.WebException($"Create LogGroup {_config.LogGroup} returned status: {createGroupResponse.HttpStatusCode}"), serviceURL); } } } var currentStreamName = GenerateStreamName(_config); var streamResponse = await _client.CreateLogStreamAsync(new CreateLogStreamRequest { LogGroupName = _config.LogGroup, LogStreamName = currentStreamName }, token).ConfigureAwait(false); if (!IsSuccessStatusCode(streamResponse)) { LogLibraryServiceError(new System.Net.WebException($"Create LogStream {currentStreamName} for LogGroup {_config.LogGroup} returned status: {streamResponse.HttpStatusCode}"), serviceURL); } _repo = new LogEventBatch(_config.LogGroup, currentStreamName, Convert.ToInt32(_config.BatchPushInterval.TotalSeconds), _config.BatchSizeInBytes); return(currentStreamName); }
/// <summary> /// Method to transmit the PutLogEvent Request /// </summary> /// <param name="token"></param> /// <returns></returns> private async Task SendBatchAsync(LogEventBatch logBatch, CancellationToken token) { if (!logBatch.ShouldSendRequest) { return; } try { lock (_sequenceTokenLock) logBatch.Request.SequenceToken = SequenceToken; var response = await _client.PutLogEventsAsync(logBatch.Request, token).ConfigureAwait(false); lock (_sequenceTokenLock) SequenceToken = response.NextSequenceToken; MaxTryCount = 5; } catch (InvalidSequenceTokenException ex) { //In case the NextSequenceToken is invalid for the last sent message, a new stream would be //created for the said application. LogLibraryError(ex, _config.LibraryLogFileName); if (MaxTryCount > 0) { MaxTryCount--; var regexResult = Invalid_sequence_token_regex.Match(ex.Message); if (regexResult.Success) { lock (_sequenceTokenLock) SequenceToken = logBatch.Request.SequenceToken = regexResult.Groups[1].Value; await SendBatchAsync(logBatch, token).ConfigureAwait(false); } } else { _currentStreamName = await CreateLogStreamAsync(token).ConfigureAwait(false); lock (_sequenceTokenLock) SequenceToken = null; } } catch (AmazonUnmarshallingException) { // Giving it one more chance here. // TODO: Create RetryManager class and retry transient errors lock (_sequenceTokenLock) logBatch.Request.SequenceToken = SequenceToken; var response = await _client.PutLogEventsAsync(logBatch.Request, token).ConfigureAwait(false); lock (_sequenceTokenLock) SequenceToken = response.NextSequenceToken; } catch (Exception e) { LogLibraryError(e, _config.LibraryLogFileName); throw; } }
/// <summary> /// Patrolling thread. keeps tab on the PutLogEvent request and the /// Concurrent Queue /// </summary> private async Task Monitor(CancellationToken token) { try { token.ThrowIfCancellationRequested(); if (_currentStreamName == null) { _currentStreamName = await CreateLogStreamAsync(token).ConfigureAwait(false); } while (!token.IsCancellationRequested) { if (_pendingMessageQueue.Count > 0) { var pendingMessages = Interlocked.Exchange(ref _pendingMessageQueue, new Queue <InputLogEvent>(200000)); var batches = LogEventBatch.CreateBatches(pendingMessages, _currentStreamName, _config); foreach (var batch in batches) { await SendBatchAsync(batch, token).ConfigureAwait(false); } } else { // If the logger is being terminated and all the messages have been sent, then exit out of loop. // If there are messages left, then keep aggressively polling the message queue until it gets empty, so the process can die, but maximum it has 5 sec. if (_isTerminated) { if (_pendingMessageQueue.Count == 0 || _terminationStopWatch.ElapsedMilliseconds > 5000) { break; } else { continue; } } await Task.Delay(TimeSpan.FromMilliseconds(_config.MonitorSleepTime.TotalMilliseconds)).ConfigureAwait(false); } } } catch (OperationCanceledException oc) { LogLibraryError(oc, _config.LibraryLogFileName); throw; } catch (AmazonServiceException amazonEx) { LogLibraryError(amazonEx, _config.LibraryLogFileName); if (!TransientErrorCodes.Any(x => amazonEx.ErrorCode.Equals(x))) { throw; } } catch (Exception ex) { LogLibraryError(ex, _config.LibraryLogFileName); } }