private async Task<bool> SendTracesAsync(Span[][] traces, IApiRequest request) { IApiResponse response = null; try { try { _statsd?.AppendIncrementCount(TracerMetricNames.Api.Requests); response = await request.PostAsync(traces, _formatterResolver).ConfigureAwait(false); } catch { // count only network/infrastructure errors, not valid responses with error status codes // (which are handled below) _statsd?.AppendIncrementCount(TracerMetricNames.Api.Errors); throw; } if (_statsd != null) { // don't bother creating the tags array if trace metrics are disabled string[] tags = { $"status:{response.StatusCode}" }; // count every response, grouped by status code _statsd.AppendIncrementCount(TracerMetricNames.Api.Responses, tags: tags); } // Attempt a retry if the status code is not SUCCESS if (response.StatusCode < 200 || response.StatusCode >= 300) { return false; } try { if (response.ContentLength > 0 && Tracer.Instance.Sampler != null) { var responseContent = await response.ReadAsStringAsync().ConfigureAwait(false); var apiResponse = JsonConvert.DeserializeObject<ApiResponse>(responseContent); Tracer.Instance.Sampler.SetDefaultSampleRates(apiResponse?.RateByService); } } catch (Exception ex) { Log.Error(ex, "Traces sent successfully to the Agent at {0}, but an error occurred deserializing the response.", _tracesEndpoint); } } finally { response?.Dispose(); } return true; }
private async Task <bool> SendPayloadAsync(ArraySegment <byte> payload, string mimeType, IApiRequest request, bool finalTry) { IApiResponse response = null; try { try { response = await request.PostAsync(payload, mimeType).ConfigureAwait(false); } catch { // count only network/infrastructure errors, not valid responses with error status codes // (which are handled below) throw; } // Attempt a retry if the status code is not SUCCESS if (response.StatusCode < 200 || response.StatusCode >= 300) { if (finalTry) { try { string responseContent = await response.ReadAsStringAsync().ConfigureAwait(false); Log.Error <int, string>("Failed to submit events with status code {StatusCode} and message: {ResponseContent}", response.StatusCode, responseContent); } catch (Exception ex) { Log.Error <int>(ex, "Unable to read response for failed request with status code {StatusCode}", response.StatusCode); } } return(false); } } finally { response?.Dispose(); } return(true); }
public async Task <bool> SendLogsAsync(ArraySegment <byte> logs, int numberOfLogs) { var retriesRemaining = MaxNumberRetries - 1; var nextSleepDuration = InitialSleepDurationMs; Log.Debug <int>("Sending {Count} logs to the logs intake", numberOfLogs); while (true) { IApiRequest request; try { request = _apiRequestFactory.Create(_logsIntakeEndpoint); } catch (Exception ex) { Log.Error(ex, "An error occurred while generating request to send logs to the intake at {IntakeEndpoint}", _apiRequestFactory.Info(_logsIntakeEndpoint)); return(false); } // Set additional headers request.AddHeader(IntakeHeaderNameApiKey, _apiKey); Exception?exception = null; var isFinalTry = retriesRemaining <= 0; var shouldRetry = true; try { IApiResponse?response = null; try { // TODO: Metrics/Telemetry? response = await request.PostAsync(logs, MimeType).ConfigureAwait(false); if (response.StatusCode is >= 200 and < 300) { Log.Debug <int>("Successfully sent {Count} logs to the intake", numberOfLogs); return(true); } shouldRetry = response.StatusCode switch { 400 => false, // Bad request (likely an issue in the payload formatting) 401 => false, // Unauthorized (likely a missing API Key) 403 => false, // Permission issue (likely using an invalid API Key) 408 => true, // Request Timeout, request should be retried after some time 413 => false, // Payload too large (batch is above 5MB uncompressed) 429 => true, // Too Many Requests, request should be retried after some time >= 400 and < 500 => false, // generic "client" error, don't retry _ => true // Something else, probably server error, do retry }; if (!shouldRetry || isFinalTry) { try { var responseContent = await response.ReadAsStringAsync().ConfigureAwait(false); Log.Error <int, string>("Failed to submit logs with status code {StatusCode} and message: {ResponseContent}", response.StatusCode, responseContent); } catch (Exception ex) { Log.Error <int>(ex, "Unable to read response for failed request with status code {StatusCode}", response.StatusCode); } } } finally { response?.Dispose(); } } catch (Exception ex) { exception = ex; #if DEBUG if (ex.InnerException is InvalidOperationException) { Log.Error <int, string>(ex, "An error occurred while sending {Count} logs to the intake at {IntakeEndpoint}", numberOfLogs, _apiRequestFactory.Info(_logsIntakeEndpoint)); return(false); } #endif } // Error handling block if (!shouldRetry || isFinalTry) { // stop retrying Log.Error <int, string>(exception, "An error occurred while sending {Count} traces to the intake at {IntakeEndpoint}", numberOfLogs, _apiRequestFactory.Info(_logsIntakeEndpoint)); return(false); } // Before retry delay if (IsSocketException(exception)) { Log.Debug(exception, "Unable to communicate with the logs intake at {IntakeEndpoint}", _apiRequestFactory.Info(_logsIntakeEndpoint)); } // Execute retry delay await Task.Delay(nextSleepDuration).ConfigureAwait(false); retriesRemaining--; nextSleepDuration *= 2; } }
private async Task <bool> SendTracesAsync(ArraySegment <byte> traces, int numberOfTraces, IApiRequest request, bool finalTry) { IApiResponse response = null; try { try { _statsd?.Increment(TracerMetricNames.Api.Requests); response = await request.PostAsync(traces, MimeTypes.MsgPack).ConfigureAwait(false); } catch { // count only network/infrastructure errors, not valid responses with error status codes // (which are handled below) _statsd?.Increment(TracerMetricNames.Api.Errors); throw; } if (_statsd != null) { // don't bother creating the tags array if trace metrics are disabled string[] tags = { $"status:{response.StatusCode}" }; // count every response, grouped by status code _statsd?.Increment(TracerMetricNames.Api.Responses, tags: tags); } // Attempt a retry if the status code is not SUCCESS if (response.StatusCode < 200 || response.StatusCode >= 300) { if (finalTry) { try { string responseContent = await response.ReadAsStringAsync().ConfigureAwait(false); _log.Error <int, string>("Failed to submit traces with status code {StatusCode} and message: {ResponseContent}", response.StatusCode, responseContent); } catch (Exception ex) { _log.Error <int>(ex, "Unable to read response for failed request with status code {StatusCode}", response.StatusCode); } } return(false); } try { if (_agentVersion == null) { var version = response.GetHeader(AgentHttpHeaderNames.AgentVersion); LogPartialFlushWarningIfRequired(version ?? string.Empty); } if (response.ContentLength != 0 && _updateSampleRates is not null) { var responseContent = await response.ReadAsStringAsync().ConfigureAwait(false); if (responseContent != _cachedResponse) { var apiResponse = JsonConvert.DeserializeObject <ApiResponse>(responseContent); _updateSampleRates(apiResponse.RateByService); _cachedResponse = responseContent; } } } catch (Exception ex) { _log.Error(ex, "Traces sent successfully to the Agent at {AgentEndpoint}, but an error occurred deserializing the response.", _apiRequestFactory.Info(_tracesEndpoint)); } } finally { response?.Dispose(); } return(true); }
public async Task <BaseResponseRestModel> PerformNetworkRequest(TaskType type, Dictionary <string, object> args, bool showIndicator) { BaseResponseRestModel answer = null; IApiResponse apiResponse = null; try { if (Connectivity.NetworkAccess != NetworkAccess.Internet) { throw new InternalException("Network is not available"); } if (!Initialized) { Init(BASE_URL); } if (showIndicator) { loadingIndicatorManager.ShowIndicator(); } switch (type) { case TaskType.LOGIN: { if (args.TryGetValue("arg1", out object reqObj) && reqObj is LoginRequest request) { var response = await api.Login(request, Constants.REQUEST_PARAM_DEVELOPER); apiResponse = response; answer = response.Content; } break; } case TaskType.GET_TASKS: { if (args.TryGetValue("arg1", out object reqObj) && reqObj is GetTasksRequest request) { var response = await api.GetTasks(request, Constants.REQUEST_PARAM_DEVELOPER); apiResponse = response; answer = response.Content; } break; } case TaskType.CREATE_TASK: { if (args.TryGetValue("arg1", out object reqObj) && reqObj is CreateTaskRequest request) { var response = await api.CreateTask(request, Constants.REQUEST_PARAM_DEVELOPER); apiResponse = response; answer = response.Content; } break; } case TaskType.EDIT_TASK: { if (args.TryGetValue("arg1", out object reqObj) && reqObj is EditTaskRequest request && args.TryGetValue("arg2", out object idObj) && idObj is string taskId) { request.Token = activeToken; var response = await api.EditTask(request, taskId, Constants.REQUEST_PARAM_DEVELOPER); apiResponse = response; answer = response.Content; } break; } } if (showIndicator) { loadingIndicatorManager.HideIndicator(); } if (answer == null) { throw new InternalException(apiResponse != null ? apiResponse.Error.Content : String.Format("Unknown arguments for {0} request", type.ToString())); } if (answer.IsStatusOk) { apiResponse?.Dispose(); return(answer); } if (answer.Data is JObject dict) { List <string> list = new List <string>(); foreach (JToken token in dict.Children()) { if (token is JProperty) { var prop = token as JProperty; list.Add(prop.Value.ToString()); } } throw new InternalException(String.Join("\n", list)); } else { throw new InternalException(answer.Data as string); } } catch (Exception e) { apiResponse?.Dispose(); loadingIndicatorManager.HideIndicator(); var exp = ErrorHandler.HandleException(e); MessagingCenter.Send <string>(exp != null ? exp.Message : e.Message, Constants.ERROR_OCCURED); return(null); } }
private async Task <bool> SendTracesAsync(Span[][] traces, IApiRequest request, bool finalTry) { IApiResponse response = null; try { try { _statsd?.Increment(TracerMetricNames.Api.Requests); response = await request.PostAsync(traces, _formatterResolver).ConfigureAwait(false); } catch { // count only network/infrastructure errors, not valid responses with error status codes // (which are handled below) _statsd?.Increment(TracerMetricNames.Api.Errors); throw; } if (_statsd != null) { // don't bother creating the tags array if trace metrics are disabled string[] tags = { $"status:{response.StatusCode}" }; // count every response, grouped by status code _statsd?.Increment(TracerMetricNames.Api.Responses, tags: tags); } // Attempt a retry if the status code is not SUCCESS if (response.StatusCode < 200 || response.StatusCode >= 300) { if (finalTry) { try { string responseContent = await response.ReadAsStringAsync().ConfigureAwait(false); Log.Error("Failed to submit traces with status code {StatusCode} and message: {ResponseContent}", response.StatusCode, responseContent); } catch (Exception ex) { Log.Error <int>(ex, "Unable to read response for failed request with status code {StatusCode}", response.StatusCode); } } return(false); } try { if (response.ContentLength != 0 && Tracer.Instance.Sampler != null) { var responseContent = await response.ReadAsStringAsync().ConfigureAwait(false); if (responseContent != _cachedResponse) { var apiResponse = JsonConvert.DeserializeObject <ApiResponse>(responseContent); Tracer.Instance.Sampler.SetDefaultSampleRates(apiResponse?.RateByService); _cachedResponse = responseContent; } } } catch (Exception ex) { Log.Error(ex, "Traces sent successfully to the Agent at {AgentEndpoint}, but an error occurred deserializing the response.", _apiRequestFactory.Info(_tracesEndpoint)); } } finally { response?.Dispose(); } return(true); }