コード例 #1
0
        public ZipkinApi(TracerSettings settings)
        {
            Log.Debug("Creating new Zipkin Api");

            _settings       = settings ?? throw new ArgumentNullException(nameof(settings));
            _tracesEndpoint = _settings.AgentUri; // User needs to include the proper path.
        }
コード例 #2
0
        public SamplingPriority GetSamplingPriority(Span span)
        {
            var traceId = span.TraceId;

            if (_rules.Count > 0)
            {
                foreach (var rule in _rules)
                {
                    if (rule.IsMatch(span))
                    {
                        var sampleRate = rule.GetSamplingRate(span);

                        Log.Debug(
                            "Matched on rule {0}. Applying rate of {1} to trace id {2}",
                            rule.RuleName,
                            sampleRate,
                            traceId);

                        return(GetSamplingPriority(span, sampleRate, agentSampling: rule is DefaultSamplingRule));
                    }
                }
            }

            Log.Debug("No rules matched for trace {0}", traceId);

            return(SamplingPriority.AutoKeep);
        }
コード例 #3
0
        public bool Allowed(ulong traceId)
        {
            if (_maxTracesPerInterval == 0)
            {
                // Rate limit of 0 blocks everything
                return(false);
            }

            if (_maxTracesPerInterval < 0)
            {
                // Negative rate limit disables rate limiting
                return(true);
            }

            WaitForRefresh();

            // This must happen after the wait, because we check for window statistics, modifying this number
            Interlocked.Increment(ref _windowChecks);

            var count = _intervalQueue.Count;

            if (count >= _maxTracesPerInterval)
            {
                Log.Debug("Dropping trace id {0} with count of {1} for last {2}ms.", traceId, count, _intervalMilliseconds);
                return(false);
            }

            _intervalQueue.Enqueue(DateTime.Now);
            Interlocked.Increment(ref _windowAllowed);

            return(true);
        }
コード例 #4
0
        private void ExtractCounters(ReadOnlyCollection <object> payload)
        {
            for (int i = 0; i < payload.Count; ++i)
            {
                if (!(payload[i] is IDictionary <string, object> eventPayload))
                {
                    continue;
                }

                if (!eventPayload.TryGetValue("Name", out object name) ||
                    !MetricsMapping.TryGetValue(name.ToString(), out var statName))
                {
                    continue;
                }

                if (eventPayload.TryGetValue("Mean", out object rawValue) ||
                    eventPayload.TryGetValue("Increment", out rawValue))
                {
                    var value = (double)rawValue;

                    _statsd.Gauge(statName, value);
                }
                else
                {
                    Log.Debug <object>("EventCounter {0} has no Mean or Increment field", name);
                }
            }
        }
コード例 #5
0
        private void OnHostingHttpRequestInStart(object arg)
        {
            var httpContext = (HttpContext)HttpRequestInStartHttpContextFetcher.Fetch(arg);

            if (ShouldIgnore(httpContext))
            {
                if (_isLogLevelDebugEnabled)
                {
                    Log.Debug("Ignoring request");
                }
            }
            else
            {
                HttpRequest request    = httpContext.Request;
                string      host       = request.Host.Value;
                string      httpMethod = request.Method?.ToUpperInvariant() ?? "UNKNOWN";
                string      url        = GetUrl(request);

                string resourceUrl = UriHelpers.GetRelativeUrl(new Uri(url), tryRemoveIds: true)
                                     .ToLowerInvariant();

                SpanContext propagatedContext = ExtractPropagatedContext(request);

                Span span = _tracer.StartSpan(HttpRequestInOperationName, propagatedContext)
                            .SetTag(Tags.InstrumentationName, ComponentName);

                IPAddress remoteIp = null;
                if (Trace.Tracer.Instance.Settings.AddClientIpToServerSpans)
                {
                    remoteIp = httpContext?.Connection?.RemoteIpAddress;
                }

                span.DecorateWebServerSpan(null, httpMethod, host, url, remoteIp);
                span.SetTag(Tags.InstrumentationName, IntegrationName);

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

                Scope scope = _tracer.ActivateSpan(span);

                _options.OnRequest?.Invoke(scope.Span, httpContext);
            }
        }
コード例 #6
0
        public float GetSamplingRate(Span span)
        {
            Log.Debug("Using the default sampling logic");

            var env     = span.GetTag(Tags.Env);
            var service = span.ServiceName;

            var key = $"service:{service},env:{env}";

            if (_sampleRates.TryGetValue(key, out var sampleRate))
            {
                span.SetMetric(Metrics.SamplingAgentDecision, sampleRate);
                return(sampleRate);
            }

            Log.Debug("Could not establish sample rate for trace {0}", span.TraceId);

            return(1);
        }
コード例 #7
0
        internal Span(SpanContext context, DateTimeOffset?start)
        {
            Context     = context;
            ServiceName = context.ServiceName;
            StartTime   = start ?? Context.TraceContext.UtcNow;

            Log.Debug(
                "Span started: [s_id: {0}, p_id: {1}, t_id: {2}]",
                SpanId,
                Context.ParentId,
                TraceId);
        }
コード例 #8
0
        private void EventSource_BuildStarted(object sender, BuildStartedEventArgs e)
        {
            try
            {
                Log.Debug("Build Started");

                _buildSpan = _tracer.StartSpan(BuildTags.BuildOperationName);
                _buildSpan.SetMetric(Tags.Analytics, 1.0d);
                _buildSpan.SetTraceSamplingPriority(SamplingPriority.AutoKeep);

                _buildSpan.Type = SpanTypes.Build;
                _buildSpan.SetTag(BuildTags.BuildName, e.SenderName);
                foreach (KeyValuePair <string, string> envValue in e.BuildEnvironment)
                {
                    _buildSpan.SetTag($"{BuildTags.BuildEnvironment}.{envValue.Key}", envValue.Value);
                }

                _buildSpan.SetTag(BuildTags.BuildCommand, Environment.CommandLine);
                _buildSpan.SetTag(BuildTags.BuildWorkingFolder, Environment.CurrentDirectory);
                _buildSpan.SetTag(BuildTags.BuildStartMessage, e.Message);

                _buildSpan.SetTag(CommonTags.RuntimeOSArchitecture, Environment.Is64BitOperatingSystem ? "x64" : "x86");
                _buildSpan.SetTag(CommonTags.RuntimeProcessArchitecture, Environment.Is64BitProcess ? "x64" : "x86");

                CIEnvironmentValues.DecorateSpan(_buildSpan);
            }
            catch (Exception ex)
            {
                Log.SafeLogError(ex, "Error in BuildStarted event");
            }
        }
コード例 #9
0
        public virtual IDisposable SubscribeIfMatch(DiagnosticListener diagnosticListener)
        {
            if (ListenerNames.Any(diagnosticListener.Name.Contains))
            {
                return(diagnosticListener.Subscribe(this, IsEventEnabled));
            }
            else
            {
                Log.Debug($"{diagnosticListener.Name} not subscribing to {this.GetType().Name}.");
            }

            return(null);
        }
コード例 #10
0
        public ISpanBuilder AddReference(string referenceType, global::OpenTracing.ISpanContext referencedContext)
        {
            lock (_lock)
            {
                if (referenceType == References.ChildOf)
                {
                    _parent = referencedContext;
                    return(this);
                }
            }

            Log.Debug("ISpanBuilder.AddReference is not implemented for other references than ChildOf by Datadog.Trace");
            return(this);
        }
コード例 #11
0
        public SamplingPriority GetSamplingPriority(Span span)
        {
            float sampleRate;
            var   traceId = span.TraceId;

            if (_rules.Count > 0)
            {
                foreach (var rule in _rules)
                {
                    if (rule.IsMatch(span))
                    {
                        sampleRate = rule.GetSamplingRate();
                        Log.Debug(
                            "Matched on rule {0}. Applying rate of {1} to trace id {2}",
                            rule.Name,
                            sampleRate,
                            traceId);
                        span.SetMetric(Metrics.SamplingRuleDecision, sampleRate);
                        return(GetSamplingPriority(span, sampleRate, withRateLimiter: true));
                    }
                }
            }

            var env     = span.GetTag(Tags.Env);
            var service = span.ServiceName;

            var key = $"service:{service},env:{env}";

            if (_sampleRates.TryGetValue(key, out sampleRate))
            {
                Log.Debug("Using the default sampling logic for trace {0}", traceId);
                return(GetSamplingPriority(span, sampleRate, withRateLimiter: false));
            }

            Log.Debug("Could not establish sample rate for trace {0}", traceId);
            return(SamplingPriority.AutoKeep);
        }
コード例 #12
0
        public bool Allowed(Span span)
        {
            try
            {
                if (_maxTracesPerInterval == 0)
                {
                    // Rate limit of 0 blocks everything
                    return(false);
                }

                if (_maxTracesPerInterval < 0)
                {
                    // Negative rate limit disables rate limiting
                    return(true);
                }

                WaitForRefresh();

                // This must happen after the wait, because we check for window statistics, modifying this number
                Interlocked.Increment(ref _windowChecks);

                var count = _intervalQueue.Count;

                if (count >= _maxTracesPerInterval)
                {
                    Log.Debug("Dropping trace id {0} with count of {1} for last {2}ms.", span.TraceId, count, _intervalMilliseconds);
                    return(false);
                }

                _intervalQueue.Enqueue(DateTime.UtcNow);
                Interlocked.Increment(ref _windowAllowed);

                return(true);
            }
            finally
            {
                // Always set the sample rate metric whether it was allowed or not
                // DEV: Setting this allows us to properly compute metrics and debug the
                //      various sample rates that are getting applied to this span
                span.SetMetric(Metrics.SamplingLimitDecision, GetEffectiveRate());
            }
        }
コード例 #13
0
 /// <inheritdoc />
 public void Init(HttpApplication httpApplication)
 {
     // Intent: The first HttpModule to run Init for this HttpApplication will register for events
     // Actual: Each HttpApplication that comes through here is potentially a new .NET object, even
     //         if it refers to the same web application. Based on my reading, it appears that initialization
     //         is done for several types of resources. Read more in this SO article -- look at Sunday Ironfoot's
     //         (yes, reliable sounding name of course) response toward the end of this article:
     //         https://stackoverflow.com/a/2416546/24231.
     //         I've discovered that not letting each of these unique application objects be added, and thus
     //         the event handlers be registered within each HttpApplication object, leads to the runtime
     //         weirdness: at one point it crashed consistently for me, and later, I saw no spans at all.
     Log.Debug("[sts] TracingHttpModule - Init");
     if (registeredEventHandlers.TryAdd(httpApplication, 1))
     {
         _httpApplication              = httpApplication;
         httpApplication.BeginRequest += OnBeginRequest;
         httpApplication.EndRequest   += OnEndRequest;
         httpApplication.Error        += OnError;
     }
 }
コード例 #14
0
        private async Task SendRequestAsync(HttpRequest request, Stream requestStream)
        {
            // Headers are always ASCII per the HTTP spec
            using (var writer = new StreamWriter(requestStream, Encoding.ASCII, bufferSize: MaxRequestHeadersBufferSize, leaveOpen: true))
            {
                await DatadogHttpHeaderHelper.WriteLeadingHeaders(request, writer).ConfigureAwait(false);

                foreach (var header in request.Headers)
                {
                    await DatadogHttpHeaderHelper.WriteHeader(writer, header).ConfigureAwait(false);
                }

                await DatadogHttpHeaderHelper.WriteEndOfHeaders(writer).ConfigureAwait(false);
            }

            await request.Content.CopyToAsync(requestStream, null).ConfigureAwait(false);

            Logger.Debug("Datadog HTTP: Flushing stream.");
            await requestStream.FlushAsync().ConfigureAwait(false);
        }
コード例 #15
0
        public void WriteTrace(Span[] trace)
        {
            var success = _tracesBuffer.Push(trace);

            if (!success)
            {
                Log.Debug("Trace buffer is full. Dropping a trace from the buffer.");
            }

            if (_statsd != null)
            {
                _statsd.Increment(TracerMetricNames.Queue.EnqueuedTraces);
                _statsd.Increment(TracerMetricNames.Queue.EnqueuedSpans, trace.Length);

                if (!success)
                {
                    _statsd.Increment(TracerMetricNames.Queue.DroppedTraces);
                    _statsd.Increment(TracerMetricNames.Queue.DroppedSpans, trace.Length);
                }
            }
        }
コード例 #16
0
        public void WriteTrace(List <Span> trace)
        {
            var success = _tracesBuffer.Push(trace);

            if (!success)
            {
                Log.Debug("Trace buffer is full, dropping it.");
            }

            if (_statsd != null)
            {
                _statsd.AppendIncrementCount(TracerMetricNames.Queue.EnqueuedTraces);
                _statsd.AppendIncrementCount(TracerMetricNames.Queue.EnqueuedSpans, trace.Count);

                if (!success)
                {
                    _statsd.AppendIncrementCount(TracerMetricNames.Queue.DroppedTraces);
                }

                _statsd.Send();
            }
        }
コード例 #17
0
        public static object BeginInvokeAction(
            object asyncControllerActionInvoker,
            object controllerContext,
            object actionName,
            object callback,
            object state,
            int opCode,
            int mdToken,
            long moduleVersionPtr)
        {
            Log.Debug("[sts] AspNetMvcIntegration - BeginInvokeAction");
            if (asyncControllerActionInvoker == null)
            {
                throw new ArgumentNullException(nameof(asyncControllerActionInvoker));
            }

            Scope scope = null;

            try
            {
                if (HttpContext.Current != null)
                {
                    scope = CreateScope(controllerContext);
                    HttpContext.Current.Items[HttpContextKey] = scope;
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error instrumenting method {0}", "System.Web.Mvc.Async.IAsyncActionInvoker.BeginInvokeAction()");
            }

            Func <object, object, object, object, object, object> instrumentedMethod;

            try
            {
                var asyncActionInvokerType = asyncControllerActionInvoker.GetInstrumentedInterface(AsyncActionInvokerTypeName);

                instrumentedMethod = MethodBuilder <Func <object, object, object, object, object, object> >
                                     .Start(moduleVersionPtr, mdToken, opCode, nameof(BeginInvokeAction))
                                     .WithConcreteType(asyncActionInvokerType)
                                     .WithParameters(controllerContext, actionName, callback, state)
                                     .WithNamespaceAndNameFilters(
                    ClrNames.IAsyncResult,
                    "System.Web.Mvc.ControllerContext",
                    ClrNames.String,
                    ClrNames.AsyncCallback,
                    ClrNames.Object)
                                     .Build();
            }
            catch (Exception ex)
            {
                Log.ErrorRetrievingMethod(
                    exception: ex,
                    moduleVersionPointer: moduleVersionPtr,
                    mdToken: mdToken,
                    opCode: opCode,
                    instrumentedType: AsyncActionInvokerTypeName,
                    methodName: nameof(BeginInvokeAction),
                    instanceType: asyncControllerActionInvoker.GetType().AssemblyQualifiedName);
                throw;
            }

            try
            {
                // call the original method, inspecting (but not catching) any unhandled exceptions
                return(instrumentedMethod(asyncControllerActionInvoker, controllerContext, actionName, callback, state));
            }
            catch (Exception ex)
            {
                scope?.Span.SetException(ex);
                throw;
            }
        }
コード例 #18
0
        public static object GetResponse(object webRequest, int opCode, int mdToken, long moduleVersionPtr)
        {
            Log.Debug("[sts] WebRequestIntegration - GetResponse");
            if (webRequest == null)
            {
                throw new ArgumentNullException(nameof(webRequest));
            }

            const string methodName = nameof(GetResponse);

            Func <object, WebResponse> callGetResponse;

            try
            {
                var instrumentedType = webRequest.GetInstrumentedType("System.Net.WebRequest");
                callGetResponse =
                    MethodBuilder <Func <object, WebResponse> >
                    .Start(moduleVersionPtr, mdToken, opCode, methodName)
                    .WithConcreteType(instrumentedType)
                    .WithNamespaceAndNameFilters("System.Net.WebResponse")
                    .Build();
            }
            catch (Exception ex)
            {
                Log.ErrorRetrievingMethod(
                    exception: ex,
                    moduleVersionPointer: moduleVersionPtr,
                    mdToken: mdToken,
                    opCode: opCode,
                    instrumentedType: WebRequestTypeName,
                    methodName: methodName,
                    instanceType: webRequest.GetType().AssemblyQualifiedName);
                throw;
            }

            var request = (WebRequest)webRequest;

            if (!(request is HttpWebRequest) || !IsTracingEnabled(request))
            {
                return(callGetResponse(webRequest));
            }

            using (var scope = ScopeFactory.CreateOutboundHttpScope(Tracer.Instance, request.Method, request.RequestUri, IntegrationName))
            {
                try
                {
                    if (scope != null)
                    {
                        // add distributed tracing headers to the HTTP request
                        SpanContextPropagator.Instance.Inject(scope.Span.Context, request.Headers.Wrap());
                    }

                    WebResponse response = callGetResponse(webRequest);

                    if (scope != null && response is HttpWebResponse webResponse)
                    {
                        scope.Span.SetTag(Tags.HttpStatusCode, ((int)webResponse.StatusCode).ToString());
                    }

                    return(response);
                }
                catch (Exception ex)
                {
                    scope?.Span.SetException(ex);
                    throw;
                }
            }
        }
コード例 #19
0
 public float GetSamplingRate(Span span)
 {
     Log.Debug("Using the global sampling rate: {0}", _globalRate);
     span.SetMetric(Metrics.SamplingRuleDecision, _globalRate);
     return(_globalRate);
 }
コード例 #20
0
ファイル: Tracer.cs プロジェクト: DavidSanr/dd-trace-dotnet
        internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IDogStatsd statsd)
        {
            // update the count of Tracer instances
            Interlocked.Increment(ref _liveTracerCount);

            Settings = settings ?? TracerSettings.FromDefaultSources();

            // if not configured, try to determine an appropriate service name
            DefaultServiceName = Settings.ServiceName ??
                                 GetApplicationName() ??
                                 UnknownServiceName;

            // only set DogStatsdClient if tracer metrics are enabled
            if (Settings.TracerMetricsEnabled)
            {
                // Run this first in case the port override is ready
                TracingProcessManager.SubscribeToDogStatsDPortOverride(
                    port =>
                {
                    Log.Debug("Attempting to override dogstatsd port with {0}", port);
                    Statsd = CreateDogStatsdClient(Settings, DefaultServiceName, port);
                });

                Statsd = statsd ?? CreateDogStatsdClient(Settings, DefaultServiceName, Settings.DogStatsdPort);
            }

            // Run this first in case the port override is ready
            TracingProcessManager.SubscribeToTraceAgentPortOverride(
                port =>
            {
                Log.Debug("Attempting to override trace agent port with {0}", port);
                var builder = new UriBuilder(Settings.AgentUri)
                {
                    Port = port
                };
                var baseEndpoint = builder.Uri;

                if (_agentWriter == null)
                {
                    IApi overridingApiClient = new Api(baseEndpoint, apiRequestFactory: null, Statsd);
                    _agentWriter             = _agentWriter ?? new AgentWriter(overridingApiClient, Statsd, queueSize: Settings.TraceQueueSize);
                }
                else
                {
                    _agentWriter.SetApiBaseEndpoint(baseEndpoint);
                }
            });

            // fall back to default implementations of each dependency if not provided
            _agentWriter = agentWriter ?? new AgentWriter(new Api(Settings.AgentUri, apiRequestFactory: null, Statsd), Statsd, queueSize: Settings.TraceQueueSize);

            _scopeManager = scopeManager ?? new AsyncLocalScopeManager();
            Sampler       = sampler ?? new RuleBasedSampler(new RateLimiter(Settings.MaxTracesSubmittedPerSecond));

            if (!string.IsNullOrWhiteSpace(Settings.CustomSamplingRules))
            {
                foreach (var rule in CustomSamplingRule.BuildFromConfigurationString(Settings.CustomSamplingRules))
                {
                    Sampler.RegisterRule(rule);
                }
            }

            if (Settings.GlobalSamplingRate != null)
            {
                var globalRate = (float)Settings.GlobalSamplingRate;

                if (globalRate < 0f || globalRate > 1f)
                {
                    Log.Warning("{0} configuration of {1} is out of range", ConfigurationKeys.GlobalSamplingRate, Settings.GlobalSamplingRate);
                }
                else
                {
                    Sampler.RegisterRule(new GlobalSamplingRule(globalRate));
                }
            }

            // Register callbacks to make sure we flush the traces before exiting
            AppDomain.CurrentDomain.ProcessExit  += CurrentDomain_ProcessExit;
            AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;

            try
            {
                // Registering for the AppDomain.UnhandledException event cannot be called by a security transparent method
                // This will only happen if the Tracer is not run full-trust
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            }
            catch (Exception ex)
            {
                Log.Warning(ex, "Unable to register a callback to the AppDomain.UnhandledException event.");
            }

            try
            {
                // Registering for the cancel key press event requires the System.Security.Permissions.UIPermission
                Console.CancelKeyPress += Console_CancelKeyPress;
            }
            catch (Exception ex)
            {
                Log.Warning(ex, "Unable to register a callback to the Console.CancelKeyPress event.");
            }

            // start the heartbeat loop
            _heartbeatTimer = new Timer(HeartbeatCallback, state: null, dueTime: TimeSpan.Zero, period: TimeSpan.FromMinutes(1));

            // If configured, add/remove the correlation identifiers into the
            // LibLog logging context when a scope is activated/closed
            if (Settings.LogsInjectionEnabled)
            {
                InitializeLibLogScopeEventSubscriber(_scopeManager, DefaultServiceName, Settings.ServiceVersion, Settings.Environment);
            }

            if (Interlocked.Exchange(ref _firstInitialization, 0) == 1)
            {
                if (Settings.StartupDiagnosticLogEnabled)
                {
                    _ = WriteDiagnosticLog();
                }

                if (Settings.RuntimeMetricsEnabled)
                {
                    _runtimeMetricsWriter = new RuntimeMetricsWriter(Statsd ?? CreateDogStatsdClient(Settings, DefaultServiceName, Settings.DogStatsdPort), 10000);
                }
            }
        }
コード例 #21
0
        internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IStatsd statsd)
        {
            // update the count of Tracer instances
            Interlocked.Increment(ref _liveTracerCount);

            Settings = settings ?? TracerSettings.FromDefaultSources();

            // if not configured, try to determine an appropriate service name
            DefaultServiceName = Settings.ServiceName ??
                                 GetApplicationName() ??
                                 UnknownServiceName;

            // only set DogStatsdClient if tracer metrics are enabled
            if (Settings.TracerMetricsEnabled)
            {
                // Run this first in case the port override is ready
                TracingProcessManager.SubscribeToDogStatsDPortOverride(
                    port =>
                {
                    Log.Debug("Attempting to override dogstatsd port with {0}", port);
                    Statsd = CreateDogStatsdClient(Settings, DefaultServiceName, port);
                });

                Statsd = statsd ?? CreateDogStatsdClient(Settings, DefaultServiceName, Settings.DogStatsdPort);
            }

            // Run this first in case the port override is ready
            TracingProcessManager.SubscribeToTraceAgentPortOverride(
                port =>
            {
                Log.Debug("Attempting to override trace agent port with {0}", port);
                var builder = new UriBuilder(Settings.AgentUri)
                {
                    Port = port
                };
                var baseEndpoint         = builder.Uri;
                IApi overridingApiClient = new Api(baseEndpoint, delegatingHandler: null, Statsd);
                if (_agentWriter == null)
                {
                    _agentWriter = _agentWriter ?? new AgentWriter(overridingApiClient, Statsd);
                }
                else
                {
                    _agentWriter.OverrideApi(overridingApiClient);
                }
            });

            // fall back to default implementations of each dependency if not provided
            _agentWriter = agentWriter ?? new AgentWriter(new Api(Settings.AgentUri, delegatingHandler: null, Statsd), Statsd);

            _scopeManager = scopeManager ?? new AsyncLocalScopeManager();
            Sampler       = sampler ?? new RuleBasedSampler(new RateLimiter(Settings.MaxTracesSubmittedPerSecond));

            if (!string.IsNullOrWhiteSpace(Settings.CustomSamplingRules))
            {
                // User has opted in, ensure rate limiter is used
                RuleBasedSampler.OptInTracingWithoutLimits();

                foreach (var rule in CustomSamplingRule.BuildFromConfigurationString(Settings.CustomSamplingRules))
                {
                    Sampler.RegisterRule(rule);
                }
            }

            if (Settings.GlobalSamplingRate != null)
            {
                var globalRate = (float)Settings.GlobalSamplingRate;

                if (globalRate < 0f || globalRate > 1f)
                {
                    Log.Warning("{0} configuration of {1} is out of range", ConfigurationKeys.GlobalSamplingRate, Settings.GlobalSamplingRate);
                }
                else
                {
                    Sampler.RegisterRule(new GlobalSamplingRule(globalRate));
                }
            }

            // Register callbacks to make sure we flush the traces before exiting
            AppDomain.CurrentDomain.ProcessExit        += CurrentDomain_ProcessExit;
            AppDomain.CurrentDomain.DomainUnload       += CurrentDomain_DomainUnload;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            Console.CancelKeyPress += Console_CancelKeyPress;

            // start the heartbeat loop
            _heartbeatTimer = new Timer(HeartbeatCallback, state: null, dueTime: TimeSpan.Zero, period: TimeSpan.FromMinutes(1));

            // If configured, add/remove the correlation identifiers into the
            // LibLog logging context when a scope is activated/closed
            if (Settings.LogsInjectionEnabled)
            {
                InitializeLibLogScopeEventSubscriber(_scopeManager, DefaultServiceName, Settings.ServiceVersion, Settings.Environment);
            }
        }
コード例 #22
0
        internal static DynamicMethod CreateBeginMethodDelegate(Type integrationType, Type targetType, Type[] argumentsTypes)
        {
            /*
             * OnMethodBegin signatures with 1 or more parameters with 1 or more generics:
             *      - CallTargetState OnMethodBegin<TTarget>(TTarget instance);
             *      - CallTargetState OnMethodBegin<TTarget, TArg1>(TTarget instance, TArg1 arg1);
             *      - CallTargetState OnMethodBegin<TTarget, TArg1, TArg2>(TTarget instance, TArg1 arg1, TArg2);
             *      - CallTargetState OnMethodBegin<TTarget, TArg1, TArg2, ...>(TTarget instance, TArg1 arg1, TArg2, ...);
             *      - CallTargetState OnMethodBegin<TTarget>();
             *      - CallTargetState OnMethodBegin<TTarget, TArg1>(TArg1 arg1);
             *      - CallTargetState OnMethodBegin<TTarget, TArg1, TArg2>(TArg1 arg1, TArg2);
             *      - CallTargetState OnMethodBegin<TTarget, TArg1, TArg2, ...>(TArg1 arg1, TArg2, ...);
             *
             */

            Log.Debug($"Creating BeginMethod Dynamic Method for '{integrationType.FullName}' integration. [Target={targetType.FullName}]");
            MethodInfo onMethodBeginMethodInfo = integrationType.GetMethod(BeginMethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);

            if (onMethodBeginMethodInfo is null)
            {
                throw new NullReferenceException($"Couldn't find the method: {BeginMethodName} in type: {integrationType.FullName}");
            }

            if (onMethodBeginMethodInfo.ReturnType != typeof(CallTargetState))
            {
                throw new ArgumentException($"The return type of the method: {BeginMethodName} in type: {integrationType.FullName} is not {nameof(CallTargetState)}");
            }

            Type[] genericArgumentsTypes = onMethodBeginMethodInfo.GetGenericArguments();
            if (genericArgumentsTypes.Length < 1)
            {
                throw new ArgumentException($"The method: {BeginMethodName} in type: {integrationType.FullName} doesn't have the generic type for the instance type.");
            }

            ParameterInfo[] onMethodBeginParameters = onMethodBeginMethodInfo.GetParameters();
            if (onMethodBeginParameters.Length < argumentsTypes.Length)
            {
                throw new ArgumentException($"The method: {BeginMethodName} with {onMethodBeginParameters.Length} parameters in type: {integrationType.FullName} has less parameters than required.");
            }
            else if (onMethodBeginParameters.Length > argumentsTypes.Length + 1)
            {
                throw new ArgumentException($"The method: {BeginMethodName} with {onMethodBeginParameters.Length} parameters in type: {integrationType.FullName} has more parameters than required.");
            }
            else if (onMethodBeginParameters.Length != argumentsTypes.Length && onMethodBeginParameters[0].ParameterType != genericArgumentsTypes[0])
            {
                throw new ArgumentException($"The first generic argument for method: {BeginMethodName} in type: {integrationType.FullName} must be the same as the first parameter for the instance value.");
            }

            List <Type> callGenericTypes = new List <Type>();

            bool mustLoadInstance          = onMethodBeginParameters.Length != argumentsTypes.Length;
            Type instanceGenericType       = genericArgumentsTypes[0];
            Type instanceGenericConstraint = instanceGenericType.GetGenericParameterConstraints().FirstOrDefault();
            Type instanceProxyType         = null;

            if (instanceGenericConstraint != null)
            {
                var result = DuckType.GetOrCreateProxyType(instanceGenericConstraint, targetType);
                instanceProxyType = result.ProxyType;
                callGenericTypes.Add(instanceProxyType);
            }
            else
            {
                callGenericTypes.Add(targetType);
            }

            DynamicMethod callMethod = new DynamicMethod(
                $"{onMethodBeginMethodInfo.DeclaringType.Name}.{onMethodBeginMethodInfo.Name}",
                typeof(CallTargetState),
                new Type[] { targetType }.Concat(argumentsTypes),
                onMethodBeginMethodInfo.Module,
                true);

            ILGenerator ilWriter = callMethod.GetILGenerator();

            // Load the instance if is needed
            if (mustLoadInstance)
            {
                ilWriter.Emit(OpCodes.Ldarg_0);

                if (instanceGenericConstraint != null)
                {
                    WriteCreateNewProxyInstance(ilWriter, instanceProxyType, targetType);
                }
            }

            // Load arguments
            for (var i = mustLoadInstance ? 1 : 0; i < onMethodBeginParameters.Length; i++)
            {
                Type sourceParameterType           = argumentsTypes[mustLoadInstance ? i - 1 : i];
                Type targetParameterType           = onMethodBeginParameters[i].ParameterType;
                Type targetParameterTypeConstraint = null;
                Type parameterProxyType            = null;

                if (targetParameterType.IsGenericParameter)
                {
                    targetParameterType           = genericArgumentsTypes[targetParameterType.GenericParameterPosition];
                    targetParameterTypeConstraint = targetParameterType.GetGenericParameterConstraints().FirstOrDefault(pType => pType != typeof(IDuckType));
                    if (targetParameterTypeConstraint is null)
                    {
                        callGenericTypes.Add(sourceParameterType);
                    }
                    else
                    {
                        var result = DuckType.GetOrCreateProxyType(targetParameterTypeConstraint, sourceParameterType);
                        parameterProxyType = result.ProxyType;
                        callGenericTypes.Add(parameterProxyType);
                    }
                }
                else if (!targetParameterType.IsAssignableFrom(sourceParameterType) && (!(sourceParameterType.IsEnum && targetParameterType.IsEnum)))
                {
                    throw new InvalidCastException($"The target parameter {targetParameterType} can't be assigned from {sourceParameterType}");
                }

                WriteLoadArgument(ilWriter, i, mustLoadInstance);
                if (parameterProxyType != null)
                {
                    WriteCreateNewProxyInstance(ilWriter, parameterProxyType, sourceParameterType);
                }
            }

            // Call method
            onMethodBeginMethodInfo = onMethodBeginMethodInfo.MakeGenericMethod(callGenericTypes.ToArray());
            ilWriter.EmitCall(OpCodes.Call, onMethodBeginMethodInfo, null);
            ilWriter.Emit(OpCodes.Ret);

            Log.Debug($"Created BeginMethod Dynamic Method for '{integrationType.FullName}' integration. [Target={targetType.FullName}]");
            return(callMethod);
        }