internal void CollectAllMetrics() { using var acq = _isCollectionInProgress.TryAcquireWithDisposable(); if (!acq.IsAcquired) { _logger.Trace()?.Log("Previous CollectAllMetrics call is still in progress - skipping this one"); return; } if (!_configSnapshotProvider.CurrentSnapshot.Recording) { //We only handle the Recording=false here. If Enabled=false, then the MetricsCollector is not started at all. _logger.Trace()?.Log("Skip collecting metrics - Recording is set to false"); return; } try { CollectAllMetricsImpl(); } catch (Exception e) { _logger.Error() ?.LogExceptionWithCaller(e); } }
internal static Runtime GetServiceRuntime(IApmLogger logger) { string name; if (IsDotNetFullFramework) { name = Runtime.DotNetFullFrameworkName; } else if (IsDotNetCore) { name = Runtime.DotNetCoreName; } else if (IsMono) { name = Runtime.MonoName; } else { name = "N/A"; logger.Error() ?.Log("Failed to detect whether the current .NET runtime is .NET Full Framework, Mono or .NET Core - " + "`{DotNetFrameworkRuntimeName}' will be used as the current .NET runtime name", name); } string version; try { if (IsDotNetFullFramework) { version = typeof(object).Assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>().InformationalVersion; } else if (IsDotNetCore) { version = GetDotNetCoreRuntimeVersion(logger); } else if (IsMono) { version = GetMonoVersion(logger); } else { version = "N/A"; logger.Error() ?.Log("Failed to detect whether the current .NET runtime is .NET Full Framework or .NET Core - " + "`{DotNetFrameworkRuntimeVersion}' will be used as the current .NET runtime version", version); } } catch (Exception ex) { version = "N/A"; logger.Error() ?.LogException(ex, "Exception was thrown while trying to obtain .NET runtime version" + " - `{DotNetFrameworkRuntimeVersion}' will be used", version); } return(new Runtime { Name = name, Version = version }); }
/// <summary> /// Extracts the request body using measure to prevent the 'read once' problem (cannot read after the body ha been already /// read). /// </summary> /// <param name="request"></param> /// <param name="logger"></param> /// <returns></returns> public static async Task <string> ExtractRequestBodyAsync(this HttpRequest request, IApmLogger logger) { string body = null; try { request.EnableBuffering(); request.Body.Position = 0; using (var reader = new StreamReader(request.Body, Encoding.UTF8, false, 1024 * 2, true)) body = await reader.ReadToEndAsync(); // Truncate the body to the first 2kb if it's longer if (body.Length > Consts.RequestBodyMaxLength) { body = body.Substring(0, Consts.RequestBodyMaxLength); } request.Body.Position = 0; } catch (IOException ioException) { logger.Error()?.LogException(ioException, "IO Error reading request body"); } catch (Exception e) { logger.Error()?.LogException(e, "Error reading request body"); } return(body); }
/// <summary> /// Extracts the request body using measure to prevent the 'read once' problem (cannot read after the body ha been already read). /// </summary> /// <param name="request"></param> /// <param name="logger"></param> /// <returns></returns> public static string ExtractRequestBody(this HttpRequest request, IApmLogger logger) { string body = null; try { request.EnableRewind(); request.Body.Position = 0; using (var reader = new StreamReader(request.Body, encoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024 * 2, leaveOpen: true)) { body = reader.ReadToEnd(); // Truncate the body to the first 2kb if it's longer if (body.Length > Consts.RequestBodyMaxLength) { body = body.Substring(0, Consts.RequestBodyMaxLength); } request.Body.Position = 0; } } catch (IOException ioException) { logger.Error()?.LogException(ioException, "IO Error reading request body"); } catch (Exception e) { logger.Error()?.LogException(e, "Error reading request body"); } return(body); }
private Transaction StartTransactionAsync(HttpContext context) { try { if (WildcardMatcher.IsAnyMatch(_configurationReader.TransactionIgnoreUrls, context.Request.Path)) { _logger.Debug()?.Log("Request ignored based on TransactionIgnoreUrls, url: {urlPath}", context.Request.Path); return(null); } Transaction transaction; var transactionName = $"{context.Request.Method} {context.Request.Path}"; if (context.Request.Headers.ContainsKey(TraceContext.TraceParentHeaderNamePrefixed) || context.Request.Headers.ContainsKey(TraceContext.TraceParentHeaderName)) { var headerValue = context.Request.Headers.ContainsKey(TraceContext.TraceParentHeaderName) ? context.Request.Headers[TraceContext.TraceParentHeaderName].ToString() : context.Request.Headers[TraceContext.TraceParentHeaderNamePrefixed].ToString(); var tracingData = context.Request.Headers.ContainsKey(TraceContext.TraceStateHeaderName) ? TraceContext.TryExtractTracingData(headerValue, context.Request.Headers[TraceContext.TraceStateHeaderName].ToString()) : TraceContext.TryExtractTracingData(headerValue); if (tracingData != null) { _logger.Debug() ?.Log( "Incoming request with {TraceParentHeaderName} header. DistributedTracingData: {DistributedTracingData}. Continuing trace.", TraceContext.TraceParentHeaderNamePrefixed, tracingData); transaction = _tracer.StartTransactionInternal(transactionName, ApiConstants.TypeRequest, tracingData); } else { _logger.Debug() ?.Log( "Incoming request with invalid {TraceParentHeaderName} header (received value: {TraceParentHeaderValue}). Starting trace with new trace id.", TraceContext.TraceParentHeaderNamePrefixed, headerValue); transaction = _tracer.StartTransactionInternal(transactionName, ApiConstants.TypeRequest); } } else { _logger.Debug()?.Log("Incoming request. Starting Trace."); transaction = _tracer.StartTransactionInternal(transactionName, ApiConstants.TypeRequest); } return(transaction); } catch (Exception ex) { _logger?.Error()?.LogException(ex, "Exception thrown while trying to start transaction"); return(null); } }
private Transaction StartTransaction(HttpContext context) { try { Transaction transaction; var transactionName = $"{context.Request.Method} {context.Request.Path}"; if (context.Request.Headers.ContainsKey(TraceParent.TraceParentHeaderName)) { var headerValue = context.Request.Headers[TraceParent.TraceParentHeaderName].ToString(); var distributedTracingData = TraceParent.TryExtractTraceparent(headerValue); if (distributedTracingData != null) { _logger.Debug() ?.Log( "Incoming request with {TraceParentHeaderName} header. DistributedTracingData: {DistributedTracingData}. Continuing trace.", TraceParent.TraceParentHeaderName, distributedTracingData); transaction = _tracer.StartTransactionInternal( transactionName, ApiConstants.TypeRequest, distributedTracingData); } else { _logger.Debug() ?.Log( "Incoming request with invalid {TraceParentHeaderName} header (received value: {TraceParentHeaderValue}). Starting trace with new trace id.", TraceParent.TraceParentHeaderName, headerValue); transaction = _tracer.StartTransactionInternal(transactionName, ApiConstants.TypeRequest); } } else { _logger.Debug()?.Log("Incoming request. Starting Trace."); transaction = _tracer.StartTransactionInternal(transactionName, ApiConstants.TypeRequest); } if (transaction.IsSampled) { FillSampledTransactionContextRequest(context, transaction); } return(transaction); } catch (Exception ex) { _logger?.Error()?.LogException(ex, "Exception thrown while trying to start transaction"); return(null); } }
public SystemTotalCpuProvider(IApmLogger logger) { _logger = logger.Scoped(nameof(SystemTotalCpuProvider)); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var categoryName = "Processor"; try { try { _processorTimePerfCounter = new PerformanceCounter(categoryName, "% Processor Time", "_Total"); } catch (InvalidOperationException e) { _logger.Debug()?.LogException(e, "Error instantiating '{CategoryName}' performance counter.", categoryName); _processorTimePerfCounter?.Dispose(); // If the Processor performance counter category does not exist, try Processor Information. categoryName = "Processor Information"; _processorTimePerfCounter = new PerformanceCounter(categoryName, "% Processor Time", "_Total"); } //The perf. counter API returns 0 the for the 1. call (probably because there is no delta in the 1. call) - so we just call it here first _processorTimePerfCounter.NextValue(); } catch (Exception e) { if (e is UnauthorizedAccessException) { _logger.Error() ?.LogException(e, "Error instantiating '{CategoryName}' performance counter." + " Process does not have permissions to read performance counters." + " See https://www.elastic.co/guide/en/apm/agent/dotnet/current/metrics.html#metrics-system to see how to configure.", categoryName); } else { _logger.Error() ?.LogException(e, "Error instantiating '{CategoryName}' performance counter", categoryName); } _logger.Warning()?.Log("System metrics won't be collected"); _processorTimePerfCounter?.Dispose(); _processorTimePerfCounter = null; } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { var(success, idle, total) = ReadProcStat(); if (!success) { return; } _prevIdleTime = idle; _prevTotalTime = total; } }
private string FindAppPoolName() { try { return(ReadEnvVarValue("APP_POOL_ID")); } catch (Exception ex) { _logger.Error()?.Log("Failed to get app pool name: {Exception}", ex); return(null); } }
private async Task <HttpResponseMessage> SendGetRequestToSampleAppAndVerifyResponseImpl( HttpRequestMessage httpRequestMessage, int expectedStatusCode ) { var url = httpRequestMessage.RequestUri; _logger.Debug()?.Log("Sending request with URL: {url} and expected status code: {HttpStatusCode}...", url, expectedStatusCode); var response = await HttpClient.SendAsync(httpRequestMessage).ConfigureAwait(false); _logger.Debug() ?.Log("Request sent. Actual status code: {HttpStatusCode} ({HttpStatusCodeEnum})", (int)response.StatusCode, response.StatusCode); try { response.StatusCode.Should().Be(expectedStatusCode); } catch (XunitException ex) { var responseContent = await response.Content.ReadAsStringAsync(); _logger.Error()?.Log("{ExceptionMessage}. Response content:\n{ResponseContent}", ex.Message, responseContent); throw; } var processIdInResponse = response.Headers.GetValues(AspNetFullFrameworkSampleApp.Consts.ProcessIdResponseHeaderName); _logger.Debug() ?.Log("{ProcessIdHeaderName} in response is {ProcessIdHeaderValue}", AspNetFullFrameworkSampleApp.Consts.ProcessIdResponseHeaderName, processIdInResponse); var apmServerUrlsInResponse = response.Headers?.GetValues(AspNetFullFrameworkSampleApp.Consts.ElasticApmServerUrlsResponseHeaderName).ToList(); try { apmServerUrlsInResponse.Should().HaveCount(1); apmServerUrlsInResponse.First().Should().Be(BuildApmServerUrl(_mockApmServerPort)); } catch (XunitException ex) { _logger.Error() ?.LogException(ex, "Sample application's APM-server-URLs configuration setting ({ActualApmServerUrl})" + " is different from expected ({ExpectedApmServerUrl})", string.Join(", ", apmServerUrlsInResponse), BuildApmServerUrl(_mockApmServerPort)); await PostTestFailureDiagnostics(); throw; } return(response); }
/// <summary> /// Gets the ASP.NET engine version /// </summary> /// <param name="logger">The logger</param> /// <returns>the engine version, or N/A if it cannot be found</returns> public static string GetEngineVersion(IApmLogger logger) { var aspNetVersion = "N/A"; try { // We would like to report the same ASP.NET version as the one printed at the bottom of the error page // (see https://github.com/microsoft/referencesource/blob/master/System.Web/ErrorFormatter.cs#L431) // It is stored in VersionInfo.EngineVersion // (see https://github.com/microsoft/referencesource/blob/3b1eaf5203992df69de44c783a3eda37d3d4cd10/System.Web/Util/versioninfo.cs#L91) // which is unfortunately an internal property of an internal class in System.Web assembly so we use reflection to get it const string versionInfoTypeName = "System.Web.Util.VersionInfo"; var versionInfoType = typeof(HttpRuntime).Assembly.GetType(versionInfoTypeName); if (versionInfoType == null) { logger.Error() ?.Log("Type {TypeName} was not found in assembly {AssemblyFullName} - {AspNetVersion} will be used as ASP.NET version", versionInfoTypeName, typeof(HttpRuntime).Assembly.FullName, aspNetVersion); return(aspNetVersion); } const string engineVersionPropertyName = "EngineVersion"; var engineVersionProperty = versionInfoType.GetProperty(engineVersionPropertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (engineVersionProperty == null) { logger.Error() ?.Log("Property {PropertyName} was not found in type {TypeName} - {AspNetVersion} will be used as ASP.NET version", engineVersionPropertyName, versionInfoType.FullName, aspNetVersion); return(aspNetVersion); } var engineVersionPropertyValue = (string)engineVersionProperty.GetValue(null); if (engineVersionPropertyValue == null) { logger.Error() ?.Log("Property {PropertyName} (in type {TypeName}) is of type {TypeName} and not a string as expected" + " - {AspNetVersion} will be used as ASP.NET version", engineVersionPropertyName, versionInfoType.FullName, engineVersionPropertyName.GetType().FullName, aspNetVersion); return(aspNetVersion); } aspNetVersion = engineVersionPropertyValue; } catch (Exception ex) { logger.Error()?.LogException(ex, "Failed to obtain ASP.NET version - {AspNetVersion} will be used as ASP.NET version", aspNetVersion); } logger.Debug()?.Log("Found ASP.NET version: {AspNetVersion}", aspNetVersion); return(aspNetVersion); }
internal void StartSpan <TResult>(IDbCommand command, DbCommandInterceptionContext <TResult> interceptCtx , [CallerMemberName] string dbgCaller = null ) { try { DoStartSpan(command, interceptCtx, dbgCaller); } catch (Exception ex) { _logger.Error()?.LogException(ex, "Processing of DB-operation-started event failed"); } }
private void OnBeginRequest(object eventSender, EventArgs eventArgs) { Logger.Debug()?.Log("Incoming request processing started - starting trace"); try { ProcessBeginRequest(eventSender); } catch (Exception ex) { Logger.Error()?.Log("Processing BeginRequest event failed. Exception: {Exception}", ex); } }
private void EnsureNoRunningWorkerProcesses(ServerManager serverManager) { var workerProcessIds = GetSampleAppWorkerProcessIds(serverManager); _logger.Debug() ?.Log("After stopping application pool found {NumberOfWorkerProcesses} worker processes." + " Their PIDs: {WorkerProcessesPIDs}", workerProcessIds.Count, string.Join(", ", workerProcessIds)); foreach (var workerProcessPid in workerProcessIds) { Process workerProcess; try { workerProcess = Process.GetProcessById(workerProcessPid); } catch (ArgumentException ex) { _logger.Debug()?.LogException(ex, "Worker process with PID {WorkerProcessPID} has already exited", workerProcessPid); continue; } using (workerProcess) { _logger.Info()?.Log("About to kill worker process with PID {WorkerProcessPID}...", workerProcessPid); try { workerProcess.Kill(); } catch (Exception ex) { _logger.Debug() ?.LogException(ex, "Attempt to kill worker process with PID {WorkerProcessPID} has thrown exception" + " - maybe process has already exited?", workerProcessPid); } const int maxWaitMs = 10 * 1000; // 10 seconds _logger.Info() ?.Log("Waiting for worker process with PID {WorkerProcessPID} to exit... Max wait time: {MaxWaitTimeMs}ms", workerProcessPid, maxWaitMs); var hasProcessExited = workerProcess.WaitForExit(maxWaitMs); if (hasProcessExited) { _logger.Info()?.Log("Worker process with PID {WorkerProcessPID} has exited", workerProcessPid); } else { _logger.Error()?.Log("Worker process with PID {WorkerProcessPID} has NOT exited during wait", workerProcessPid); throw new InvalidOperationException($"Failed to stop IIS worker process with PID {workerProcessPid}"); } } } }
private async Task ProcessQueueItems(object[] queueItems) { try { var metadataJson = _payloadItemSerializer.SerializeObject(_metadata); var ndjson = new StringBuilder(); ndjson.AppendLine("{\"metadata\": " + metadataJson + "}"); foreach (var item in queueItems) { var serialized = _payloadItemSerializer.SerializeObject(item); switch (item) { case Transaction _: ndjson.AppendLine("{\"transaction\": " + serialized + "}"); break; case Span _: ndjson.AppendLine("{\"span\": " + serialized + "}"); break; case Error _: ndjson.AppendLine("{\"error\": " + serialized + "}"); break; case MetricSet _: ndjson.AppendLine("{\"metricset\": " + serialized + "}"); break; } _logger?.Trace()?.Log("Serialized item to send: {ItemToSend} as {SerializedItem}", item, serialized); } var content = new StringContent(ndjson.ToString(), Encoding.UTF8, "application/x-ndjson"); var result = await _httpClient.PostAsync(Consts.IntakeV2Events, content, _cancellationTokenSource.Token); if (result != null && !result.IsSuccessStatusCode) { _logger?.Error() ?.Log("Failed sending event. " + "APM Server response: status code: {ApmServerResponseStatusCode}, content: \n{ApmServerResponseContent}", result.StatusCode, await result.Content.ReadAsStringAsync()); } else { _logger?.Debug() ?.Log("Sent items to server:\n{SerializedItems}", TextUtils.Indent(string.Join($",{Environment.NewLine}", queueItems.ToArray()))); } } catch (Exception e) { _logger?.Warning() ?.LogException( e, "Failed sending events. Following events were not transferred successfully to the server ({ApmServerUrl}):\n{SerializedItems}", _httpClient.BaseAddress, TextUtils.Indent(string.Join($",{Environment.NewLine}", queueItems.ToArray()))); } }
private static void FillSampledTransactionContextUser(HttpContext context, Transaction transaction, IApmLogger logger) { try { if (context.User?.Identity != null && context.User.Identity.IsAuthenticated && transaction.Context.User == null) { transaction.Context.User = new User { UserName = context.User.Identity.Name, Id = GetClaimWithFallbackValue(ClaimTypes.NameIdentifier, Consts.OpenIdClaimTypes.UserId), Email = GetClaimWithFallbackValue(ClaimTypes.Email, Consts.OpenIdClaimTypes.Email) }; logger.Debug()?.Log("Captured user - {CapturedUser}", transaction.Context.User); } } catch (Exception ex) { // context.user is optional: https://github.com/elastic/apm-server/blob/64a4ab96ba138050fe496b17d31deb2cf8830deb/docs/spec/user.json#L5 logger?.Error() ?.LogException(ex, "Exception thrown while trying to fill user context for sampled transaction {TransactionId}", transaction.Id); } string GetClaimWithFallbackValue(string claimType, string fallbackClaimType) { var idClaims = context.User.Claims.Where(n => n.Type == claimType || n.Type == fallbackClaimType); var enumerable = idClaims.ToList(); return(enumerable.Any() ? enumerable.First().Value : string.Empty); } }
private void HandleStartCommand(object payloadData, PropertyFetcherSet propertyFetcherSet) { try { if (propertyFetcherSet.StartCorrelationId.Fetch(payloadData) is Guid operationId && propertyFetcherSet.StartCommand.Fetch(payloadData) is IDbCommand dbCommand) { var span = _apmAgent.TracerInternal.DbSpanCommon.StartSpan(_apmAgent, dbCommand); _spans.TryAdd(operationId, span); } } catch (Exception ex) { //ignore _logger.Error()?.LogException(ex, "Exception was thrown while handling 'command started event'"); } }
protected override ConfigurationKeyValue Read(string key, string fallBackEnvVarName) { try { var value = ConfigurationManager.AppSettings[key]; if (value != null) { return(Kv(key, value, Origin)); } } catch (ConfigurationErrorsException ex) { _logger.Error()?.LogException(ex, "Exception thrown from ConfigurationManager.AppSettings - falling back on environment variables"); } return(Kv(fallBackEnvVarName, ReadEnvVarValue(fallBackEnvVarName), EnvironmentConfigurationReader.Origin)); }
internal static void StopTransaction(Transaction transaction, HttpContext context, IApmLogger logger) { if (transaction == null) { return; } try { if (!transaction.HasCustomName) { //fixup Transaction.Name - e.g. /user/profile/1 -> /user/profile/{id} var routeData = context.GetRouteData()?.Values; if (routeData != null && context.Response.StatusCode != StatusCodes.Status404NotFound) { logger?.Trace()?.Log("Calculating transaction name based on route data"); var name = GetNameFromRouteContext(routeData); if (!string.IsNullOrWhiteSpace(name)) { transaction.Name = $"{context.Request.Method} {name}"; } } else if (context.Response.StatusCode == StatusCodes.Status404NotFound) { logger?.Trace()? .Log("No route data found or status code is 404 - setting transaction name to 'unknown route"); transaction.Name = $"{context.Request.Method} unknown route"; } } transaction.Result = Transaction.StatusCodeToResult(GetProtocolName(context.Request.Protocol), context.Response.StatusCode); if (context.Response.StatusCode >= 500) { transaction.Outcome = Outcome.Failure; } else { transaction.Outcome = Outcome.Success; } if (transaction.IsSampled) { FillSampledTransactionContextResponse(context, transaction, logger); FillSampledTransactionContextUser(context, transaction, logger); } } catch (Exception ex) { logger?.Error()?.LogException(ex, "Exception thrown while trying to stop transaction"); } finally { transaction.End(); } }
internal void CollectAllMetrics() { using (var acq = _isCollectionInProgress.TryAcquireWithDisposable()) { if (!acq.IsAcquired) { _logger.Trace()?.Log("Previous CollectAllMetrics call is still in progress - skipping this one"); return; } try { CollectAllMetricsImpl(); } catch (Exception e) { _logger.Error() ?.LogExceptionWithCaller(e); } } }
public IActionResult Get() => _mockApmServer.DoUnderLock(() => { try { return(GetImpl()); } catch (Exception ex) { _logger.Error()?.LogException(ex, nameof(GetImpl) + " has thrown exception"); throw; } });
private async Task ProcessQueueItems(object[] queueItems) { try { var metadata = new Metadata { Service = _service }; var metadataJson = _payloadItemSerializer.SerializeObject(metadata); var ndjson = new StringBuilder(); ndjson.Append("{\"metadata\": " + metadataJson + "}" + "\n"); foreach (var item in queueItems) { var serialized = _payloadItemSerializer.SerializeObject(item); switch (item) { case Transaction _: ndjson.AppendLine("{\"transaction\": " + serialized + "}"); break; case Span _: ndjson.AppendLine("{\"span\": " + serialized + "}"); break; case Error _: ndjson.AppendLine("{\"error\": " + serialized + "}"); break; } _logger?.Trace()?.Log("Serialized item to send: {ItemToSend} as {SerializedItemToSend}", item, serialized); } var content = new StringContent(ndjson.ToString(), Encoding.UTF8, "application/x-ndjson"); var result = await _httpClient.PostAsync(Consts.IntakeV2Events, content); if (result != null && !result.IsSuccessStatusCode) { _logger?.Error()?.Log("Failed sending event. {ApmServerResponse}", await result.Content.ReadAsStringAsync()); } else { _logger?.Debug() ?.Log($"Sent items to server: {Environment.NewLine}{{items}}", string.Join($",{Environment.NewLine}", queueItems.ToArray())); } } catch (Exception e) { _logger?.Warning() ?.LogException( e, "Failed sending events. Following events were not transferred successfully to the server:\n{items}", string.Join($",{Environment.NewLine}", queueItems.ToArray())); } }
private void EndProfilingSession(object sender, ProfilingSession session) { IExecutionSegment executionSegment = sender as Span; string segmentType; if (executionSegment is null) { executionSegment = sender as Transaction; if (executionSegment is null) { return; } segmentType = "transaction"; } else { segmentType = "span"; } try { // Remove the session. Use session passed to EndProfilingSession rather than the removed session in the event // there was an issue in adding or removing the session if (!_executionSegmentSessions.TryRemove(executionSegment.Id, out _)) { _logger.Debug()?.Log( "could not remove profiling session from tracked sessions for {ExecutionSegment} {Id}", segmentType, executionSegment.Id); } var profiledCommands = session.FinishProfiling(); _logger.Trace()?.Log( "Finished profiling session for {ExecutionSegment}. Collected {ProfiledCommandCount} commands", executionSegment, profiledCommands.Count()); foreach (var profiledCommand in profiledCommands) { ProcessCommand(profiledCommand, executionSegment); } _logger.Trace()?.Log( "End profiling session for {ExecutionSegment} {Id}", segmentType, executionSegment.Id); } catch (Exception e) { _logger.Error()?.LogException(e, "Exception ending profiling session for {ExecutionSegment} {Id}", segmentType, executionSegment.Id); } }
/// <summary> /// Extracts the soap action from the header if exists only with Soap 1.1 /// </summary> /// <param name="headers">The request headers</param> /// <param name="requestStream">The request stream</param> /// <param name="logger">The logger.</param> public static string ExtractSoapAction(NameValueCollection headers, Stream requestStream, IApmLogger logger) { try { return(GetSoap11Action(headers) ?? GetSoap12Action(headers, requestStream)); } catch (Exception e) { logger.Error()?.LogException(e, "Error reading soap action header"); } return(null); }
public PayloadSenderV2(IApmLogger logger, IConfigSnapshot config, Service service, Api.System system, HttpMessageHandler httpMessageHandler = null, string dbgName = null ) : base(/* isEnabled: */ true, logger, ThisClassName, service, config, httpMessageHandler) { _logger = logger?.Scoped(ThisClassName + (dbgName == null ? "" : $" (dbgName: `{dbgName}')")); _payloadItemSerializer = new PayloadItemSerializer(config); _intakeV2EventsAbsoluteUrl = BackendCommUtils.ApmServerEndpoints.BuildIntakeV2EventsAbsoluteUrl(config.ServerUrls.First()); System = system; _metadata = new Metadata { Service = service, System = System }; foreach (var globalLabelKeyValue in config.GlobalLabels) { _metadata.Labels.Add(globalLabelKeyValue.Key, globalLabelKeyValue.Value); } if (config.MaxQueueEventCount < config.MaxBatchEventCount) { _logger?.Error() ?.Log( "MaxQueueEventCount is less than MaxBatchEventCount - using MaxBatchEventCount as MaxQueueEventCount." + " MaxQueueEventCount: {MaxQueueEventCount}." + " MaxBatchEventCount: {MaxBatchEventCount}.", config.MaxQueueEventCount, config.MaxBatchEventCount); _maxQueueEventCount = config.MaxBatchEventCount; } else { _maxQueueEventCount = config.MaxQueueEventCount; } _flushInterval = config.FlushInterval; _logger?.Debug() ?.Log( "Using the following configuration options:" + " Events intake API absolute URL: {EventsIntakeAbsoluteUrl}" + ", FlushInterval: {FlushInterval}" + ", MaxBatchEventCount: {MaxBatchEventCount}" + ", MaxQueueEventCount: {MaxQueueEventCount}" , _intakeV2EventsAbsoluteUrl, _flushInterval.ToHms(), config.MaxBatchEventCount, _maxQueueEventCount); _eventQueue = new BatchBlock <object>(config.MaxBatchEventCount); TransactionFilters.Add(new TransactionIgnoreUrlsFilter(config).Filter); StartWorkLoop(); }
internal AgentComponents( IApmLogger logger, IConfigurationReader configurationReader, IPayloadSender payloadSender, IMetricsCollector metricsCollector, ICurrentExecutionSegmentsContainer currentExecutionSegmentsContainer, ICentralConfigFetcher centralConfigFetcher, IApmServerInfo apmServerInfo ) { try { var tempLogger = logger ?? ConsoleLogger.LoggerOrDefault(configurationReader?.LogLevel); ConfigurationReader = configurationReader ?? new EnvironmentConfigurationReader(tempLogger); Logger = logger ?? ConsoleLogger.LoggerOrDefault(ConfigurationReader.LogLevel); Service = Service.GetDefaultService(ConfigurationReader, Logger); var systemInfoHelper = new SystemInfoHelper(Logger); var system = systemInfoHelper.ParseSystemInfo(ConfigurationReader.HostName); ConfigStore = new ConfigStore(new ConfigSnapshotFromReader(ConfigurationReader, "local"), Logger); ApmServerInfo = apmServerInfo ?? new ApmServerInfo(); PayloadSender = payloadSender ?? new PayloadSenderV2(Logger, ConfigStore.CurrentSnapshot, Service, system, ApmServerInfo, isEnabled: ConfigurationReader.Enabled); HttpTraceConfiguration = new HttpTraceConfiguration(); if (ConfigurationReader.Enabled) { CentralConfigFetcher = centralConfigFetcher ?? new CentralConfigFetcher(Logger, ConfigStore, Service); MetricsCollector = metricsCollector ?? new MetricsCollector(Logger, PayloadSender, ConfigStore); MetricsCollector.StartCollecting(); } TracerInternal = new Tracer(Logger, Service, PayloadSender, ConfigStore, currentExecutionSegmentsContainer ?? new CurrentExecutionSegmentsContainer(), ApmServerInfo); if (!ConfigurationReader.Enabled) { Logger?.Info()?.Log("The Elastic APM .NET Agent is disabled - the agent won't capture traces and metrics."); } } catch (Exception e) { logger?.Error()?.LogException(e, "Failed initializing agent."); } }
public ProcessTotalCpuTimeProvider(IApmLogger logger) { IApmLogger loggerInCtor = logger.Scoped(nameof(ProcessTotalCpuTimeProvider)); try { _lastTimeWindowStart = DateTime.UtcNow; _lastCurrentProcessCpuTime = Process.GetCurrentProcess().TotalProcessorTime; } catch (Exception e) { loggerInCtor.Error()?.LogException(e, "Failed reading Process Total CPU Time"); } }
/// <summary> /// Extracts the soap action from the header if exists only with Soap 1.1 /// </summary> /// <param name="request">The request.</param> /// <param name="logger">The logger.</param> public static string ExtractSoapAction(this HttpRequest request, IApmLogger logger) { try { return (GetSoap11Action(request) ?? GetSoap12Action(request)); } catch (Exception e) { logger.Error()?.LogException(e, "Error reading soap action header"); } return(null); }
internal IActionResult BuildResponse(HttpRequest httpRequest, HttpResponse httpResponse) { lock (_lock) { try { return(BuildResponseImpl(httpRequest, httpResponse)); } catch (Exception ex) { _logger.Error()?.LogException(ex, nameof(BuildResponseImpl) + " thrown exception"); _appliedByAgent.SetException(ex); throw; } } }
private static void DoLog(this IApmLogger logger, LogLevel level, string message, Exception e, params object[] args) { try { var formatter = logger is ScopedLogger sl ? sl.GetOrAddFormatter(message, args) : Formatters.GetOrAdd(message, s => new LogValuesFormatter(s, args)); var logValues = formatter.GetState(args); logger?.Log(level, logValues, e, (s, _) => formatter.Format(args)); } catch (Exception exception) { logger?.Error()?.LogException(exception, "Exception during logging - some log lines can be missing"); } }
private static void FillSampledTransactionContextResponse(HttpContext context, Transaction transaction, IApmLogger logger) { try { transaction.Context.Response = new Response { Finished = context.Response.HasStarted, //TODO ? StatusCode = context.Response.StatusCode, Headers = GetHeaders(context.Response.Headers, transaction.ConfigSnapshot) }; } catch (Exception ex) { // context.response is optional: https://github.com/elastic/apm-server/blob/64a4ab96ba138050fe496b17d31deb2cf8830deb/docs/spec/context.json#L16 logger?.Error() ?.LogException(ex, "Exception thrown while trying to fill response context for sampled transaction {TransactionId}", transaction.Id); } }