コード例 #1
0
        private void OnBeginRequest(object sender, EventArgs eventArgs)
        {
            Scope scope = null;

            try
            {
                var tracer = Tracer.Instance;

                if (!tracer.Settings.IsIntegrationEnabled(IntegrationName))
                {
                    // integration disabled
                    return;
                }

                var httpContext = (sender as HttpApplication)?.Context;

                if (httpContext == null)
                {
                    return;
                }

                HttpRequest httpRequest       = httpContext.Request;
                SpanContext propagatedContext = null;

                if (tracer.ActiveScope == null)
                {
                    try
                    {
                        // extract propagated http headers
                        var headers = httpRequest.Headers.Wrap();
                        propagatedContext = SpanContextPropagator.Instance.Extract(headers);
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Error extracting propagated HTTP headers.");
                    }
                }

                string host         = httpRequest.Headers.Get("Host");
                string httpMethod   = httpRequest.HttpMethod.ToUpperInvariant();
                string url          = httpRequest.RawUrl.ToLowerInvariant();
                string path         = UriHelpers.GetRelativeUrl(httpRequest.Url, tryRemoveIds: true);
                string resourceName = $"{httpMethod} {path.ToLowerInvariant()}";

                scope = tracer.StartActive(_requestOperationName, propagatedContext);
                scope.Span.DecorateWebServerSpan(resourceName, httpMethod, host, url);

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true);
                scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate);

                httpContext.Items[_httpContextScopeKey] = scope;
            }
            catch (Exception ex)
            {
                // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case...
                scope?.Dispose();
                Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error");
            }
        }
コード例 #2
0
        public static object ExecuteReaderAsync(
            object command,
            object boxedCancellationToken,
            int opCode,
            int mdToken,
            long moduleVersionPtr)
        {
            const string methodName        = AdoNetConstants.MethodNames.ExecuteReaderAsync;
            var          cancellationToken = (CancellationToken)boxedCancellationToken;

            Type npgsqlComandType;
            Type npgsqlDataReaderType;

            try
            {
                npgsqlComandType     = command.GetInstrumentedType(NpgsqlCommandTypeName);
                npgsqlDataReaderType = npgsqlComandType.Assembly.GetType(NpgsqlDataReaderTypeName);
            }
            catch (Exception ex)
            {
                // This shouldn't happen because the assembly holding the Npgsql.NpgsqlDataReader type should have been loaded already
                // profiled app will not continue working as expected without this method
                Log.Error(ex, "Error finding the Npgsql.NpgsqlDataReader type");
                throw;
            }

            Func <DbCommand, CancellationToken, object> instrumentedMethod;

            try
            {
                instrumentedMethod =
                    MethodBuilder <Func <DbCommand, CancellationToken, object> >
                    .Start(moduleVersionPtr, mdToken, opCode, methodName)
                    .WithConcreteType(npgsqlComandType)
                    .WithParameters(cancellationToken)
                    .WithNamespaceAndNameFilters(ClrNames.GenericTask, ClrNames.CancellationToken)
                    .Build();
            }
            catch (Exception ex)
            {
                Log.ErrorRetrievingMethod(
                    exception: ex,
                    moduleVersionPointer: moduleVersionPtr,
                    mdToken: mdToken,
                    opCode: opCode,
                    instrumentedType: NpgsqlCommandTypeName,
                    methodName: methodName,
                    instanceType: command.GetType().AssemblyQualifiedName);
                throw;
            }

            return(AsyncHelper.InvokeGenericTaskDelegate(
                       owningType: command.GetType(),
                       taskResultType: npgsqlDataReaderType,
                       nameOfIntegrationMethod: nameof(ExecuteReaderAsyncInternal),
                       integrationType: typeof(NpgsqlCommandIntegration),
                       (DbCommand)command,
                       cancellationToken,
                       instrumentedMethod));
        }
コード例 #3
0
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationName">The name of the integration creating this scope.</param>
        /// <returns>A new pre-populated scope.</returns>
        public static Scope CreateOutboundHttpScope(Tracer tracer, string httpMethod, Uri requestUri, string integrationName)
        {
            if (!tracer.Settings.IsIntegrationEnabled(integrationName))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            Scope scope = null;

            try
            {
                Span parent = tracer.ActiveScope?.Span;

                if (parent != null &&
                    parent.Type == SpanTypes.Http &&
                    parent.GetTag(Tags.InstrumentationName) != null)
                {
                    // we are already instrumenting this,
                    // don't instrument nested methods that belong to the same stacktrace
                    // e.g. HttpClientHandler.SendAsync() -> SocketsHttpHandler.SendAsync()
                    return(null);
                }

                string resourceUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : true, tryRemoveIds : true) : null;

                string httpUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : false, tryRemoveIds : false) : null;

                scope = tracer.StartActive(OperationName, serviceName: $"{tracer.DefaultServiceName}-{ServiceName}");
                var span = scope.Span;

                span.Type         = SpanTypes.Http;
                span.ResourceName = $"{httpMethod} {resourceUrl}";

                span.SetTag(Tags.SpanKind, SpanKinds.Client);
                span.SetTag(Tags.HttpMethod, httpMethod?.ToUpperInvariant());
                span.SetTag(Tags.HttpUrl, httpUrl);
                span.SetTag(Tags.InstrumentationName, integrationName);

                // set analytics sample rate if enabled
                if (integrationName != null)
                {
                    var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false);
                    span.SetMetric(Tags.Analytics, analyticsSampleRate);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            // always returns the scope, even if it's null because we couldn't create it,
            // or we couldn't populate it completely (some tags is better than no tags)
            return(scope);
        }
コード例 #4
0
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationId">The id of the integration creating this scope.</param>
        /// <param name="tags">The tags associated to the scope</param>
        /// <returns>A new pre-populated scope.</returns>
        public static Scope CreateOutboundHttpScope(Tracer tracer, string httpMethod, Uri requestUri, IntegrationInfo integrationId, out HttpTags tags)
        {
            tags = null;

            if (!tracer.Settings.IsIntegrationEnabled(integrationId))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            Scope scope = null;

            try
            {
                Span parent = tracer.ActiveScope?.Span;

                if (parent != null &&
                    parent.Type == SpanTypes.Http &&
                    parent.GetTag(Tags.InstrumentationName) != null)
                {
                    // we are already instrumenting this,
                    // don't instrument nested methods that belong to the same stacktrace
                    // e.g. HttpClientHandler.SendAsync() -> SocketsHttpHandler.SendAsync()
                    return(null);
                }

                string resourceUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : true, tryRemoveIds : true) : null;

                string httpUrl = requestUri != null?UriHelpers.CleanUri(requestUri, removeScheme : false, tryRemoveIds : false) : null;

                tags = new HttpTags();

                string serviceName = tracer.Settings.GetServiceName(tracer, ServiceName);
                scope = tracer.StartActiveWithTags(OperationName, tags: tags, serviceName: serviceName);
                var span = scope.Span;

                span.Type         = SpanTypes.Http;
                span.ResourceName = $"{httpMethod} {resourceUrl}";

                tags.HttpMethod          = httpMethod?.ToUpperInvariant();
                tags.HttpUrl             = httpUrl;
                tags.InstrumentationName = IntegrationRegistry.GetName(integrationId);

                tags.SetAnalyticsSampleRate(integrationId, tracer.Settings, enabledWithGlobalSetting: false);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            // always returns the scope, even if it's null because we couldn't create it,
            // or we couldn't populate it completely (some tags is better than no tags)
            return(scope);
        }
コード例 #5
0
        public static object ExecuteAsyncGeneric(
            object wireProtocol,
            object connection,
            object cancellationTokenSource,
            int opCode,
            int mdToken,
            long moduleVersionPtr)
        {
            // The generic type for this method comes from the declaring type of wireProtocol
            if (wireProtocol == null)
            {
                throw new ArgumentNullException(nameof(wireProtocol));
            }

            var tokenSource       = cancellationTokenSource as CancellationTokenSource;
            var cancellationToken = tokenSource?.Token ?? CancellationToken.None;

            var wireProtocolType        = wireProtocol.GetType();
            var wireProtocolGenericArgs = GetGenericsFromWireProtocol(wireProtocolType);

            const string methodName = nameof(ExecuteAsync);
            Func <object, object, CancellationToken, object> executeAsync;

            try
            {
                executeAsync =
                    MethodBuilder <Func <object, object, CancellationToken, object> >
                    .Start(moduleVersionPtr, mdToken, opCode, methodName)
                    .WithConcreteType(wireProtocolType)
                    .WithDeclaringTypeGenerics(wireProtocolGenericArgs)
                    .WithParameters(connection, cancellationToken)
                    .WithNamespaceAndNameFilters(ClrNames.GenericTask, "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken)
                    .Build();
            }
            catch (Exception ex)
            {
                // profiled app will not continue working as expected without this method
                Log.Error(ex, $"Error resolving {wireProtocolType.Name}.{methodName}(IConnection connection, CancellationToken cancellationToken)");
                throw;
            }

            return(AsyncHelper.InvokeGenericTaskDelegate(
                       wireProtocolType,
                       wireProtocolGenericArgs[0],
                       nameof(ExecuteAsyncInternalGeneric),
                       typeof(MongoDbIntegration),
                       wireProtocol,
                       connection,
                       cancellationToken,
                       executeAsync));
        }
コード例 #6
0
        private void OnBeginRequest(object sender, EventArgs eventArgs)
        {
            var tracer = Tracer.Instance;

            if (!tracer.Settings.IsIntegrationEnabled(IntegrationName))
            {
                // integration disabled
                return;
            }

            Scope scope = null;

            try
            {
                if (!TryGetContext(sender, out var httpContext))
                {
                    return;
                }

                SpanContext propagatedContext = null;

                if (tracer.ActiveScope == null)
                {
                    try
                    {
                        // extract propagated http headers
                        var headers = httpContext.Request.Headers.Wrap();
                        propagatedContext = SpanContextPropagator.Instance.Extract(headers);
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Error extracting propagated HTTP headers.");
                    }
                }

                scope = tracer.StartActive(_operationName, propagatedContext);

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true);
                scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate);

                httpContext.Items[_httpContextDelegateKey] = HttpContextSpanIntegrationDelegate.CreateAndBegin(httpContext, scope);
            }
            catch (Exception ex)
            {
                // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case...
                scope?.Dispose();
                Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error");
            }
        }
コード例 #7
0
        /// <summary>
        /// Gets a <see cref="ConcurrentDictionary{TKey, TValue}"/> containing all of the values.
        /// </summary>
        /// <remarks>
        /// Example JSON where `globalTags` is the configuration key.
        /// {
        ///  "globalTags": {
        ///     "name1": "value1",
        ///     "name2": "value2"
        ///     }
        /// }
        /// </remarks>
        /// <param name="key">The key that identifies the setting.</param>
        /// <returns><see cref="IDictionary{TKey, TValue}"/> containing all of the key-value pairs.</returns>
        /// <exception cref="JsonReaderException">Thrown if the configuration value is not a valid JSON string.</exception>"
        public IDictionary <string, string> GetDictionary(string key)
        {
            var token = _configuration.SelectToken(key, errorWhenNoMatch: false);

            if (token == null)
            {
                return(null);
            }

            if (token.Type == JTokenType.Object)
            {
                try
                {
                    var dictionary = token
                                     ?.ToObject <ConcurrentDictionary <string, string> >();
                    return(dictionary);
                }
                catch (Exception e)
                {
                    Log.Error(e, "Unable to parse configuration value for {0} as key-value pairs of strings.", key);
                    return(null);
                }
            }

            return(StringConfigurationSource.ParseCustomKeyValues(token.ToString()));
        }
コード例 #8
0
        private bool DoesNotMatch(string input, string pattern)
        {
            try
            {
                if (pattern != null &&
                    !Regex.IsMatch(
                        input: input,
                        pattern: pattern,
                        options: RegexOptions.None,
                        matchTimeout: RegexTimeout))
                {
                    return(true);
                }
            }
            catch (RegexMatchTimeoutException timeoutEx)
            {
                _hasPoisonedRegex = true;
                Log.Error(
                    timeoutEx,
                    "Timeout when trying to match against {0} on {1}.",
                    input,
                    pattern);
            }

            return(false);
        }
コード例 #9
0
        // IMPORTANT: For all logging frameworks, do not set any default values for
        //            "dd.trace_id" and "dd.span_id" when initializing the subscriber
        //            because the Tracer may be initialized at a time when it is not safe
        //            to add properties logging context of the underlying logging framework.
        //
        //            Failure to abide by this can cause a SerializationException when
        //            control is passed from one AppDomain to another where the originating
        //            AppDomain used a logging framework that stored logging context properties
        //            inside the System.Runtime.Remoting.Messaging.CallContext structure
        //            but the target AppDomain is unable to de-serialize the object --
        //            this can easily happen if the target AppDomain cannot find/load the
        //            logging framework assemblies.
        public LibLogScopeEventSubscriber(IScopeManager scopeManager)
        {
            _scopeManager = scopeManager;

            try
            {
                _logProvider = LogProvider.CurrentLogProvider ?? LogProvider.ResolveLogProvider();
                if (_logProvider is SerilogLogProvider)
                {
                    // Do not set default values for Serilog because it is unsafe to set
                    // except at the application startup, but this would require auto-instrumentation
                    _scopeManager.SpanOpened += StackOnSpanOpened;
                    _scopeManager.SpanClosed += StackOnSpanClosed;
                }
                else
                {
                    _scopeManager.SpanActivated += MapOnSpanActivated;
                    _scopeManager.TraceEnded    += MapOnTraceEnded;
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Could not successfully start the LibLogScopeEventSubscriber. There was an issue resolving the application logger.");
            }
        }
コード例 #10
0
        private async Task FlushTracesTaskLoopAsync()
        {
            while (true)
            {
                try
                {
                    await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(1)), _processExit.Task)
                    .ConfigureAwait(false);

                    if (_processExit.Task.IsCompleted)
                    {
                        await FlushTracesAsync().ConfigureAwait(false);

                        return;
                    }
                    else
                    {
                        await FlushTracesAsync().ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "An unhandled error occurred during the flushing task");
                }
            }
        }
コード例 #11
0
        public static void ErrorRetrievingMethod(
            this Vendors.Serilog.ILogger logger,
            Exception exception,
            long moduleVersionPointer,
            int mdToken,
            int opCode,
            string instrumentedType,
            string methodName,
            string instanceType        = null,
            string[] relevantArguments = null)
        {
            var instrumentedMethod = $"{instrumentedType}.{methodName}(...)";

            if (instanceType != null)
            {
                instrumentedMethod = $"{instrumentedMethod} on {instanceType}";
            }

            if (relevantArguments != null)
            {
                instrumentedMethod = $"{instrumentedMethod} with {string.Join(", ", relevantArguments)}";
            }

            var moduleVersionId = PointerHelpers.GetGuidFromNativePointer(moduleVersionPointer);

            logger.Error(
                exception,
                $"Error (MVID: {moduleVersionId}, mdToken: {mdToken}, opCode: {opCode}) could not retrieve: {instrumentedMethod}");
        }
コード例 #12
0
        public AzureAppServices(IDictionary environmentVariables)
        {
            try
            {
                IsRelevant = GetVariableIfExists(AzureAppServicesContextKey, environmentVariables)?.ToBoolean() ?? false;

                if (IsRelevant)
                {
                    var apiKey = GetVariableIfExists(Configuration.ConfigurationKeys.ApiKey, environmentVariables);
                    if (apiKey == null)
                    {
                        Log.Error("The Azure Site Extension will not work if you have not configured DD_API_KEY.");
                        IsUnsafeToTrace = true;
                        return;
                    }

                    // Azure App Services Basis
                    SubscriptionId = GetSubscriptionId(environmentVariables);
                    ResourceGroup  = GetVariableIfExists(ResourceGroupKey, environmentVariables);
                    SiteName       = GetVariableIfExists(SiteNameKey, environmentVariables);
                    ResourceId     = CompileResourceId();

                    InstanceId      = GetVariableIfExists(InstanceIdKey, environmentVariables);
                    InstanceName    = GetVariableIfExists(InstanceNameKey, environmentVariables);
                    OperatingSystem = GetVariableIfExists(OperatingSystemKey, environmentVariables);

                    // Functions
                    FunctionsWorkerRuntime =
                        GetVariableIfExists(
                            FunctionsWorkerRuntimeKey,
                            environmentVariables,
                            i => AzureContext = AzureContext.AzureFunction);
                    FunctionsExtensionVersion =
                        GetVariableIfExists(
                            FunctionsExtensionVersionKey,
                            environmentVariables,
                            i => AzureContext = AzureContext.AzureFunction);

                    switch (AzureContext)
                    {
                    case AzureContext.AzureFunction:
                        SiteKind = "functionapp";
                        SiteType = "function";
                        break;

                    case AzureContext.AzureAppService:
                        SiteKind = "app";
                        SiteType = "app";
                        break;
                    }

                    Runtime = FrameworkDescription.Instance.Name;
                }
            }
            catch (Exception ex)
            {
                IsUnsafeToTrace = true;
                Log.SafeLogError(ex, "Unable to initialize AzureAppServices metadata.");
            }
        }
コード例 #13
0
        private static SpanContext ExtractPropagatedContext(HttpRequest request)
        {
            try
            {
                // extract propagation details from http headers
                var requestHeaders = request.Headers;

                if (requestHeaders != null)
                {
                    var headersCollection = new DictionaryHeadersCollection();

                    foreach (var header in requestHeaders)
                    {
                        string   key    = header.Key;
                        string[] values = header.Value.ToArray();

                        if (key != null && values.Length > 0)
                        {
                            headersCollection.Add(key, values);
                        }
                    }

                    return(B3SpanContextPropagator.Instance.Extract(headersCollection));
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error extracting propagated HTTP headers.");
            }

            return(null);
        }
コード例 #14
0
        public async Task SendTracesAsync(Span[][] traces)
        {
            // retry up to 5 times with exponential back-off
            var retryLimit    = 5;
            var retryCount    = 1;
            var sleepDuration = 100; // in milliseconds

            while (true)
            {
                HttpResponseMessage responseMessage;

                try
                {
                    // re-create content on every retry because some versions of HttpClient always dispose of it, so we can't reuse.
                    using (var content = new ZipkinContent(traces, _settings))
                    {
                        responseMessage = await _client.PostAsync(_settings.EndpointUrl, content).ConfigureAwait(false);

                        responseMessage.EnsureSuccessStatusCode();
                        return;
                    }
                }
                catch (Exception ex)
                {
#if DEBUG
                    if (ex.InnerException is InvalidOperationException ioe)
                    {
                        Log.Error("An error occurred while sending traces to {Endpoint}\n{Exception}", ex, _settings.EndpointUrl, ex.ToString());
                        return;
                    }
#endif
                    if (retryCount >= retryLimit)
                    {
                        // stop retrying
                        Log.Error("An error occurred while sending traces to {Endpoint}", ex, _settings.EndpointUrl);
                        return;
                    }

                    // retry
                    await Task.Delay(sleepDuration).ConfigureAwait(false);

                    retryCount++;
                    sleepDuration *= 2;
                }
            }
        }
コード例 #15
0
        private static Scope CreateScope(object controllerContext)
        {
            Scope scope = null;

            try
            {
                if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName))
                {
                    // integration disabled, don't create a scope, skip this trace
                    return(null);
                }

                var         tracer            = Tracer.Instance;
                var         request           = controllerContext.GetProperty <HttpRequestMessage>("Request").GetValueOrDefault();
                SpanContext propagatedContext = null;

                if (request != null && tracer.ActiveScope == null)
                {
                    try
                    {
                        // extract propagated http headers
                        var headers = request.Headers.Wrap();
                        propagatedContext = SpanContextPropagator.Instance.Extract(headers);
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Error extracting propagated HTTP headers.");
                    }
                }

                scope = tracer.StartActive(OperationName, propagatedContext);
                UpdateSpan(controllerContext, scope.Span);

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true);
                scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating scope.");
            }

            return(scope);
        }
コード例 #16
0
 void IObserver <KeyValuePair <string, object> > .OnNext(KeyValuePair <string, object> value)
 {
     try
     {
         OnNext(value.Key, value.Value);
     }
     catch (Exception ex)
     {
         Log.Error(ex, "Event Exception: {0}", value.Key);
     }
 }
コード例 #17
0
        /// <summary>
        /// Creates a scope for outbound http requests and populates some common details.
        /// </summary>
        /// <param name="tracer">The tracer instance to use to create the new scope.</param>
        /// <param name="httpMethod">The HTTP method used by the request.</param>
        /// <param name="requestUri">The URI requested by the request.</param>
        /// <param name="integrationName">The name of the integration creating this scope.</param>
        /// <returns>A new pre-populated scope.</returns>
        public static Scope CreateOutboundHttpScope(Tracer tracer, string httpMethod, Uri requestUri, string integrationName)
        {
            if (!tracer.Settings.IsIntegrationEnabled(integrationName))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            Scope scope = null;

            try
            {
                scope = tracer.StartActive(OperationName);
                var span = scope.Span;

                span.Type        = SpanTypes.Http;
                span.ServiceName = $"{tracer.DefaultServiceName}-{ServiceName}";

                span.ResourceName = string.Join(
                    " ",
                    httpMethod,
                    UriHelpers.CleanUri(requestUri, removeScheme: true, tryRemoveIds: true));

                span.SetTag(Tags.SpanKind, SpanKinds.Client);
                span.SetTag(Tags.HttpMethod, httpMethod?.ToUpperInvariant());
                span.SetTag(Tags.HttpUrl, UriHelpers.CleanUri(requestUri, removeScheme: false, tryRemoveIds: false));
                span.SetTag(Tags.InstrumentationName, integrationName);

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false);
                span.SetMetric(Tags.Analytics, analyticsSampleRate);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            // always returns the scope, even if it's null because we couldn't create it,
            // or we couldn't populate it completely (some tags is better than no tags)
            return(scope);
        }
コード例 #18
0
        public static Scope CreateScope(Tracer tracer, string integrationName, object pipeline, object requestData)
        {
            if (!tracer.Settings.IsIntegrationEnabled(integrationName))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            string requestName = pipeline.GetProperty("RequestParameters")
                                 .GetValueOrDefault()
                                 ?.GetType()
                                 .Name
                                 .Replace("RequestParameters", string.Empty);

            var pathAndQuery = requestData.GetProperty <string>("PathAndQuery").GetValueOrDefault() ??
                               requestData.GetProperty <string>("Path").GetValueOrDefault();

            string method = requestData.GetProperty("Method").GetValueOrDefault()?.ToString();
            var    url    = requestData.GetProperty("Uri").GetValueOrDefault()?.ToString();

            var serviceName = $"{tracer.DefaultServiceName}-{ServiceName}";

            Scope scope = null;

            try
            {
                var tags = new ElasticsearchTags();
                scope = tracer.StartActiveWithTags(OperationName, serviceName: serviceName, tags: tags);
                var span = scope.Span;
                span.ResourceName        = requestName ?? pathAndQuery ?? string.Empty;
                span.Type                = SpanType;
                tags.InstrumentationName = ComponentValue;
                tags.SpanKind            = SpanKinds.Client;
                tags.Action              = requestName;
                tags.Method              = method;
                tags.Url = url;

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false);

                if (analyticsSampleRate != null)
                {
                    tags.AnalyticsSampleRate = analyticsSampleRate;
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            return(scope);
        }
コード例 #19
0
        public static int ExecuteNonQuery(
            object command,
            int opCode,
            int mdToken,
            long moduleVersionPtr)
        {
            Func <IDbCommand, int> instrumentedMethod;

            try
            {
                instrumentedMethod =
                    MethodBuilder <Func <IDbCommand, int> >
                    .Start(moduleVersionPtr, mdToken, opCode, AdoNetConstants.MethodNames.ExecuteNonQuery)
                    .WithConcreteType(typeof(IDbCommand))
                    .WithNamespaceAndNameFilters(ClrNames.Int32)
                    .Build();
            }
            catch (Exception ex)
            {
                Log.Error(ex, $"Error resolving {DbCommandTypeName}.{AdoNetConstants.MethodNames.ExecuteNonQuery}(...)");
                throw;
            }

            var dbCommand = command as IDbCommand;

            using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName))
            {
                try
                {
                    return(instrumentedMethod(dbCommand));
                }
                catch (Exception ex)
                {
                    scope?.Span.SetException(ex);
                    throw;
                }
            }
        }
コード例 #20
0
        private static FrameworkDescription CreateFromRuntimeInformation()
        {
            string frameworkName = null;
            string osPlatform    = null;

            try
            {
                // RuntimeInformation.FrameworkDescription returns a string like ".NET Framework 4.7.2" or ".NET Core 2.1",
                // we want to return everything before the last space
                string frameworkDescription = RuntimeInformation.FrameworkDescription;
                int    index = frameworkDescription.LastIndexOf(' ');
                frameworkName = frameworkDescription.Substring(0, index).Trim();
            }
            catch (Exception e)
            {
                Log.Error(e, "Error getting framework name from RuntimeInformation");
            }

            if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
            {
                osPlatform = "Windows";
            }
            else if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux))
            {
                osPlatform = "Linux";
            }
            else if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX))
            {
                osPlatform = "MacOS";
            }

            return(new FrameworkDescription(
                       frameworkName ?? "unknown",
                       GetNetCoreVersion() ?? "unknown",
                       osPlatform ?? "unknown",
                       RuntimeInformation.OSArchitecture.ToString().ToLowerInvariant(),
                       RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant()));
        }
コード例 #21
0
        /// <summary>
        /// Gets an "application name" for the executing application by looking at
        /// the hosted app name (.NET Framework on IIS only), assembly name, and process name.
        /// </summary>
        /// <returns>The default service name.</returns>
        private static string GetApplicationName()
        {
            try
            {
#if !NETSTANDARD2_0
                // System.Web.dll is only available on .NET Framework
                if (System.Web.Hosting.HostingEnvironment.IsHosted)
                {
                    // if this app is an ASP.NET application, return "SiteName/ApplicationVirtualPath".
                    // note that ApplicationVirtualPath includes a leading slash.
                    return((System.Web.Hosting.HostingEnvironment.SiteName + System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath).TrimEnd('/'));
                }
#endif

                return(Assembly.GetEntryAssembly()?.GetName().Name ??
                       Process.GetCurrentProcess().ProcessName);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating default service name.");
                return(null);
            }
        }
コード例 #22
0
        internal static Scope CreateScope(Tracer tracer, string integrationName, string host, string port, string rawCommand)
        {
            if (!Tracer.Instance.Settings.IsIntegrationEnabled(integrationName))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            string serviceName = $"{tracer.DefaultServiceName}-{ServiceName}";
            Scope  scope       = null;

            try
            {
                var tags = new RedisTags();

                scope = tracer.StartActiveWithTags(OperationName, serviceName: serviceName, tags: tags);
                int    separatorIndex = rawCommand.IndexOf(' ');
                string command;

                if (separatorIndex >= 0)
                {
                    command = rawCommand.Substring(0, separatorIndex);
                }
                else
                {
                    command = rawCommand;
                }

                var span = scope.Span;
                span.Type         = SpanTypes.Redis;
                span.ResourceName = command;
                tags.RawCommand   = rawCommand;
                tags.Host         = host;
                tags.Port         = port;

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false);

                if (analyticsSampleRate != null)
                {
                    tags.AnalyticsSampleRate = analyticsSampleRate;
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            return(scope);
        }
コード例 #23
0
        public static Module Get(Guid moduleVersionId)
        {
            // First attempt at cached values with no blocking
            if (_modules.TryGetValue(moduleVersionId, out Module value))
            {
                return(value);
            }

            // Block if a population event is happening
            _populationResetEvent.Wait();

            // See if the previous population event populated what we need
            if (_modules.TryGetValue(moduleVersionId, out value))
            {
                return(value);
            }

            if (_failures >= MaxFailures)
            {
                // For some unforeseeable reason we have failed on a lot of AppDomain lookups
                if (!_shortCircuitLogicHasLogged)
                {
                    Log.Warning("Datadog is unable to continue attempting module lookups for this AppDomain. Falling back to legacy method lookups.");
                }

                return(null);
            }

            // Block threads on this event
            _populationResetEvent.Reset();

            try
            {
                PopulateModules();
            }
            catch (Exception ex)
            {
                _failures++;
                Log.Error(ex, "Error when populating modules.");
            }
            finally
            {
                // Continue threads blocked on this event
                _populationResetEvent.Set();
            }

            _modules.TryGetValue(moduleVersionId, out value);

            return(value);
        }
コード例 #24
0
        private string CompileResourceId()
        {
            string resourceId = null;

            try
            {
                var success = true;
                if (SubscriptionId == null)
                {
                    success = false;
                    Log.Warning("Could not successfully retrieve the subscription ID from variable: {0}", WebsiteOwnerNameKey);
                }

                if (SiteName == null)
                {
                    success = false;
                    Log.Warning("Could not successfully retrieve the deployment ID from variable: {0}", SiteNameKey);
                }

                if (ResourceGroup == null)
                {
                    success = false;
                    Log.Warning("Could not successfully retrieve the resource group name from variable: {0}", ResourceGroupKey);
                }

                if (success)
                {
                    resourceId = $"/subscriptions/{SubscriptionId}/resourcegroups/{ResourceGroup}/providers/microsoft.web/sites/{SiteName}".ToLowerInvariant();
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Could not successfully setup the resource id for azure app services.");
            }

            return(resourceId);
        }
コード例 #25
0
        internal static Scope CreateScope(Tracer tracer, string integrationName, string componentName, string host, string port, string rawCommand)
        {
            if (!Tracer.Instance.Settings.IsIntegrationEnabled(integrationName))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            Scope scope = null;

            try
            {
                int    separatorIndex = rawCommand.IndexOf(' ');
                string command;

                if (separatorIndex >= 0)
                {
                    command = rawCommand.Substring(0, separatorIndex);
                }
                else
                {
                    command = rawCommand;
                }

                scope = tracer.StartActive(command ?? OperationName, serviceName: tracer.DefaultServiceName);

                var span = scope.Span;
                span.SetTag(Tags.InstrumentationName, componentName);
                span.SetTag(Tags.DbType, SpanTypes.Redis);
                span.SetTag(Tags.SpanKind, SpanKinds.Client);
                if (Tracer.Instance.Settings.TagRedisCommands)
                {
                    span.SetTag(Tags.DbStatement, rawCommand);
                }

                span.SetTag(Tags.OutHost, host);
                span.SetTag(Tags.OutPort, port);

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false);
                span.SetMetric(Tags.Analytics, analyticsSampleRate);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            return(scope);
        }
コード例 #26
0
        void IObserver <KeyValuePair <string, object> > .OnNext(KeyValuePair <string, object> value)
        {
            try
            {
                OnNext(value.Key, value.Value);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Event Exception: {0}", value.Key);
#if DEBUG
                // In debug mode we allow exceptions to be catch in the test suite
                throw;
#endif
            }
        }
コード例 #27
0
        /// <summary>
        /// Entry method for invoking the beginning of every web server request pipeline
        /// </summary>
        /// <param name="httpContext">Instance being instrumented.</param>
        /// <param name="features">Initialize features.</param>
        /// <param name="opCode">The OpCode used in the original method call.</param>
        /// <param name="mdToken">The mdToken of the original method call.</param>
        /// <param name="moduleVersionPtr">A pointer to the module version GUID.</param>
        // [InterceptMethod(
        //     TargetAssembly = "Microsoft.AspNetCore.Http.Abstractions",
        //     TargetType = DefaultHttpContextTypeName,
        //     TargetSignatureTypes = new[] { ClrNames.Void, ClrNames.Ignore })]
        // ***************************************************************
        //  DISABLED UNTIL WE FIX SCOPING ISSUES AT HTTP CONTEXT LEVEL
        // ***************************************************************
        public static void Initialize(object httpContext, object features, int opCode, int mdToken, long moduleVersionPtr)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            var httpContextType = httpContext.GetInstrumentedType(DefaultHttpContextTypeName);

            Action <object, object> instrumentedMethod;

            try
            {
                instrumentedMethod =
                    MethodBuilder <Action <object, object> >
                    .Start(moduleVersionPtr, mdToken, opCode, nameof(Initialize))
                    .WithConcreteType(httpContextType)
                    .WithParameters(features)
                    .Build();
            }
            catch (Exception ex)
            {
                Log.ErrorRetrievingMethod(
                    exception: ex,
                    moduleVersionPointer: moduleVersionPtr,
                    mdToken: mdToken,
                    opCode: opCode,
                    instrumentedType: DefaultHttpContextTypeName,
                    methodName: nameof(Initialize),
                    instanceType: httpContext.GetType().AssemblyQualifiedName);
                throw;
            }

            try
            {
                instrumentedMethod.Invoke(httpContext, features);
            }
            catch (Exception ex)
            {
                Log.Error(ex, $"Error calling {DefaultHttpContextTypeName}.{nameof(Initialize)}(...)");
                throw;
            }

            if (Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName))
            {
                AspNetAmbientContext.Initialize(httpContext);
            }
        }
コード例 #28
0
        public static Scope CreateScope(Tracer tracer, string integrationName, object pipeline, object requestData)
        {
            if (!tracer.Settings.IsIntegrationEnabled(integrationName))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            string requestName = pipeline.GetProperty("RequestParameters")
                                 .GetValueOrDefault()
                                 ?.GetType()
                                 .Name
                                 .Replace("RequestParameters", string.Empty);

            var pathAndQuery = requestData.GetProperty <string>("PathAndQuery").GetValueOrDefault() ??
                               requestData.GetProperty <string>("Path").GetValueOrDefault();

            string method = requestData.GetProperty("Method").GetValueOrDefault()?.ToString();
            var    url    = requestData.GetProperty("Uri").GetValueOrDefault()?.ToString();

            var serviceName = string.Join("-", tracer.DefaultServiceName, ServiceName);

            Scope scope = null;

            try
            {
                scope = tracer.StartActive(OperationName, serviceName: serviceName);
                var span = scope.Span;
                span.ResourceName = requestName ?? pathAndQuery ?? string.Empty;
                span.Type         = SpanType;
                span.SetTag(Tags.InstrumentationName, ComponentValue);
                span.SetTag(Tags.SpanKind, SpanKinds.Client);
                span.SetTag(ElasticsearchActionKey, requestName);
                span.SetTag(ElasticsearchMethodKey, method);
                span.SetTag(ElasticsearchUrlKey, url);

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false);
                span.SetMetric(Tags.Analytics, analyticsSampleRate);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            return(scope);
        }
コード例 #29
0
        internal static Scope CreateScope(Tracer tracer, string integrationName, string host, string port, string rawCommand)
        {
            if (!Tracer.Instance.Settings.IsIntegrationEnabled(integrationName))
            {
                // integration disabled, don't create a scope, skip this trace
                return(null);
            }

            string serviceName = string.Join("-", tracer.DefaultServiceName, ServiceName);
            Scope  scope       = null;

            try
            {
                scope = tracer.StartActive(OperationName, serviceName: serviceName);
                int    separatorIndex = rawCommand.IndexOf(' ');
                string command;

                if (separatorIndex >= 0)
                {
                    command = rawCommand.Substring(0, separatorIndex);
                }
                else
                {
                    command = rawCommand;
                }

                var span = scope.Span;
                span.Type         = SpanTypes.Redis;
                span.ResourceName = command;
                span.SetTag(Tags.RedisRawCommand, rawCommand);
                span.SetTag(Tags.OutHost, host);
                span.SetTag(Tags.OutPort, port);

                // set analytics sample rate if enabled
                var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false);
                span.SetMetric(Tags.Analytics, analyticsSampleRate);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error creating or populating scope.");
            }

            return(scope);
        }
コード例 #30
0
        public static object ExecuteReader(
            object command,
            int opCode,
            int mdToken,
            long moduleVersionPtr)
        {
            Func <object, object> instrumentedMethod;

            try
            {
                var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName);

                instrumentedMethod =
                    MethodBuilder <Func <object, object> >
                    .Start(moduleVersionPtr, mdToken, opCode, AdoNetConstants.MethodNames.ExecuteReader)
                    .WithConcreteType(targetType)
                    .WithNamespaceAndNameFilters(NpgsqlDataReaderTypeName)
                    .Build();
            }
            catch (Exception ex)
            {
                Log.Error(ex, $"Error resolving {NpgsqlCommandTypeName}.{AdoNetConstants.MethodNames.ExecuteReader}(...)");
                throw;
            }

            using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command as DbCommand, IntegrationName))
            {
                try
                {
                    return(instrumentedMethod(command));
                }
                catch (Exception ex)
                {
                    scope?.Span.SetException(ex);
                    throw;
                }
            }
        }