private IScope BeforeWrappedMethod(string name, ILambdaContext lambdaContext, ISpanContext distributedTraceContext, object input = null)
        {
            // Should we use  _tracer.ScopeManager.Active instead?  It returns null if none is active;
            IScope scope = null;

            try
            {
                var tags           = IOParser.ParseRequest(input);
                var extractAdapter = new TextMapExtractAdapter(tags);
                var spanContext    = distributedTraceContext ?? _tracer.Extract(BuiltinFormats.TextMap, extractAdapter);
                tags.Remove("newrelic");
                scope = _tracer
                        .BuildSpan(name)
                        .AsChildOf(spanContext)
                        .WithTag("aws.requestId", lambdaContext.AwsRequestId ?? string.Empty)
                        .WithTag("aws.arn", lambdaContext.InvokedFunctionArn ?? string.Empty)
                        .StartActive();

                DetectColdStart(scope, ref _isColdStart);

                if (input != null)
                {
                    AddTagsToActiveSpan(scope.Span, "request", tags);
                }
            }
            catch (Exception exception)
            {
                Logger.Log(message: exception.ToString(), level: "ERROR");
            }

            return(scope);
        }
        public void TestInjectExtract()
        {
            var tracer = new WavefrontTracer
                         .Builder(new ConsoleReporter(DefaultSource), BuildApplicationTags())
                         .Build();

            var span = tracer.BuildSpan("testOp").Start();

            Assert.NotNull(span);

            span.SetBaggageItem("customer", "testCustomer");
            span.SetBaggageItem("requestType", "mobile");

            var dictionary           = new Dictionary <string, string>();
            var textMapInjectAdapter = new TextMapInjectAdapter(dictionary);

            tracer.Inject(span.Context, BuiltinFormats.TextMap, textMapInjectAdapter);

            var textMapExtractAdapter = new TextMapExtractAdapter(dictionary);
            var context =
                (WavefrontSpanContext)tracer.Extract(BuiltinFormats.TextMap, textMapExtractAdapter);

            Assert.Equal("testCustomer", context.GetBaggageItem("customer"));
            Assert.Equal("mobile", context.GetBaggageItem("requesttype"));
        }
            /// <summary>
            /// 开始执行Action
            /// </summary>
            /// <param name="context"></param>
            public void OnActionExecuting(ActionExecutingContext context)
            {
                var          path           = context.HttpContext.Request.Path;
                var          callingHeaders = new TextMapExtractAdapter(context.HttpContext.Request.Headers.ToDictionary(m => m.Key, m => m.Value.ToString()));
                var          spanContex     = _tracer.Extract(BuiltinFormats.HttpHeaders, callingHeaders);
                ISpanBuilder builder        = null;

                if (spanContex != null)
                {
                    builder = _tracer.BuildSpan("中间件Span").AsChildOf(spanContex);
                }
                else
                {
                    builder = _tracer.BuildSpan("中间件Span");
                }
                _scope = builder.StartActive(true);
                _scope.Span.SetOperationName(path);
                // 记录请求信息到span
                foreach (var query in context.HttpContext.Request.Query)
                {
                    _scope.Span.SetTag(query.Key, query.Value);
                }
                if (context.HttpContext.Request.HasFormContentType)
                {
                    foreach (var form in context.HttpContext.Request.Form)
                    {
                        _scope.Span.SetTag(form.Key, form.Value);
                    }
                }
            }
Exemple #4
0
        private async Task OnMessage <TMessage>(IMessage <TMessage> message, Func <TMessage, Task> processMessage)
        {
            var stringDictionary      = message.Properties.Headers.ToDictionary(x => x.Key, x => Encoding.UTF8.GetString((byte[])x.Value));
            var textMapExtractAdapter = new TextMapExtractAdapter(stringDictionary);
            var spanContext           = _tracer.Extract(BuiltinFormats.HttpHeaders, textMapExtractAdapter);

            using (_tracer.BuildSpan(nameof(OnMessage)).AddReference(References.FollowsFrom, spanContext).StartActive(true))
                using (_logger.BeginScope(new[] { new KeyValuePair <string, object>(nameof(_tracer.ActiveSpan.Context.TraceId), _tracer.ActiveSpan.Context.TraceId) }))
                {
                    var tryCount = 0;

                    //TODO надо фильтровать ошибки базы, с3 и реббита, но тогда цикл должен быть выше по абстракции
                    while (true)
                    {
                        try
                        {
                            await processMessage(message.Body).ConfigureAwait(false);

                            break;
                        }
                        catch (Exception e)
                        {
                            tryCount++;
                            _logger.LogError(e, $"Process error, try count {tryCount}");

                            if (tryCount >= 5)
                            {
                                throw;
                            }
                        }
                    }
                }
        }
Exemple #5
0
        /// <summary>
        ///     Обработка вернувшихся сообщений
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnMessageReturned(object sender, EasyNetQ.MessageReturnedEventArgs args)
        {
            var stringDictionary      = args.MessageProperties.Headers.ToDictionary(x => x.Key, x => Encoding.UTF8.GetString((byte[])x.Value));
            var textMapExtractAdapter = new TextMapExtractAdapter(stringDictionary);
            var spanContext           = _tracer.Extract(BuiltinFormats.HttpHeaders, textMapExtractAdapter);

            using (_tracer.BuildSpan(nameof(OnMessageReturned)).AddReference(References.ChildOf, spanContext).StartActive(true))
                using (_logger.BeginScope(new[] { new KeyValuePair <string, object>(nameof(_tracer.ActiveSpan.Context.TraceId), _tracer.ActiveSpan.Context.TraceId) }))
                {
                    _tracer.ActiveSpan.SetTag(Tags.Error, true);

                    if (args.MessageProperties.Headers.TryGetValue(MessageKeyHeader, out var bytes) && bytes is byte[] value)
                    {
                        var key = Encoding.UTF8.GetString(value);

                        _logger.LogError("Message returned {Exchange} {RoutingKey} reason {ReturnReason} {Key}",
                                         args.MessageReturnedInfo.Exchange,
                                         args.MessageReturnedInfo.RoutingKey,
                                         args.MessageReturnedInfo.ReturnReason,
                                         key);

                        MessageReturned?.Invoke(new MessageReturnedEventArgs(key));
                    }
                    else
                    {
                        _logger.LogError("Can not get error message filename");
                    }
                }
        }
        /// <summary>
        /// 调用管道
        /// </summary>
        /// <param name="context">上下文</param>
        /// <param name="tracer">跟踪器</param>
        /// <returns></returns>
        public async Task InvokeAsync(HttpContext context, ITracer tracer)
        {
            _logger.LogInformation("jaeger调用");
            var path = context.Request.Path;

            if (Path.HasExtension(path))
            {
                await _next(context);
            }
            else
            {
                //接收传入的Headers
                var          callingHeaders = new TextMapExtractAdapter(context.Request.Headers.ToDictionary(m => m.Key, m => m.Value.ToString()));
                var          spanContex     = tracer.Extract(BuiltinFormats.HttpHeaders, callingHeaders);
                ISpanBuilder builder        = null;
                if (spanContex != null)
                {
                    builder = tracer.BuildSpan("中间件Span").AsChildOf(spanContex);
                }
                else
                {
                    builder = tracer.BuildSpan("中间件Span");
                }
                //开始设置Span
                using (IScope scope = builder.StartActive(true))
                {
                    scope.Span.SetOperationName(path);
                    // 记录请求信息到span
                    if (_jaegerOptions.IsQuerySpan)
                    {
                        foreach (var query in context.Request.Query)
                        {
                            //包含敏感词跳出
                            if (_jaegerOptions.NoSpanKeys.Contains(query.Key))
                            {
                                continue;
                            }
                            var value = query.Value.ToString().Length > _jaegerOptions.QueryValueMaxLength ? query.Value.ToString()?.Substring(0, _jaegerOptions.QueryValueMaxLength) : query.Value.ToString();
                            scope.Span.SetTag(query.Key, value);
                        }
                    }
                    if (_jaegerOptions.IsFormSpan && context.Request.HasFormContentType)
                    {
                        foreach (var form in context.Request.Form)
                        {
                            //包含敏感词跳出
                            if (_jaegerOptions.NoSpanKeys.Contains(form.Key))
                            {
                                continue;
                            }
                            var value = form.Value.ToString().Length > _jaegerOptions.FormValueMaxLength ? form.Value.ToString()?.Substring(0, _jaegerOptions.FormValueMaxLength) : form.Value.ToString();
                            scope.Span.SetTag(form.Key, value);
                        }
                    }
                    await _next(context);
                }
            }
        }
Exemple #7
0
        public Tracer(string operaName, string spanContextStr)
        {
            Dictionary <string, string> dic = new Dictionary <string, string>();

            dic.Add("uber-trace-id", spanContextStr);
            var callingHeaders   = new TextMapExtractAdapter(dic);
            var extractedContext = GlobalTracer.Instance.Extract(BuiltinFormats.HttpHeaders, callingHeaders);

            Scope = GlobalTracer.Instance.BuildSpan(operaName).AsChildOf(extractedContext).StartActive();
        }
        public void TestInvalidTraceIdExtract()
        {
            string val        = ":7499dd16d98ab60e:3771de7e09c55ae8:1";
            var    dictionary = new Dictionary <string, string>();

            dictionary.Add(JaegerHeader, val);
            var textMapExtractAdapter = new TextMapExtractAdapter(dictionary);
            WavefrontSpanContext ctx  = wfJaegerPropagator.Extract(textMapExtractAdapter);

            Assert.Null(ctx);
        }
        protected ISpanBuilder CreateTracingSpanBuilder(string spanName, ITracer tracer, HttpRequest request)
        {
            var callingHeaders = new TextMapExtractAdapter(request.Headers.ToDictionary(m => m.Key, m => m.Value.ToString()));
            var spanContex     = tracer.Extract(BuiltinFormats.HttpHeaders, callingHeaders);

            if (spanContex != null)
            {
                return(tracer.BuildSpan(spanName).AsChildOf(spanContex));
            }
            else
            {
                return(tracer.BuildSpan(spanName));
            }
        }
        private static ISpanContext ExtractSpanContextOrDefault(
            ITracer tracer,
            ServerCallContext context,
            ISpanContext defaultVal = null)
        {
            ISpanContext spanContext = defaultVal;

            try {
                var dict    = MetadataToDictionary(context.RequestHeaders);
                var adapter = new TextMapExtractAdapter(dict);
                spanContext = tracer.Extract(BuiltinFormats.HttpHeaders, adapter);
            } catch {}
            return(spanContext);
        }
        public void TestTraceIdExtractEncoded()
        {
            string val        = "3871de7e09c53ae8%3A7499dd16d98ab60e%3A3771de7e09c55ae8%3A1";
            var    dictionary = new Dictionary <string, string>();

            dictionary.Add(JaegerHeader, val);
            var textMapExtractAdapter = new TextMapExtractAdapter(dictionary);
            WavefrontSpanContext ctx  = wfJaegerPropagator.Extract(textMapExtractAdapter);

            Assert.NotNull(ctx);
            Assert.Equal("00000000-0000-0000-3871-de7e09c53ae8", ctx.TraceId);
            Assert.Equal("00000000-0000-0000-7499-dd16d98ab60e", ctx.SpanId);
            Assert.Equal("00000000-0000-0000-7499-dd16d98ab60e", ctx.GetBaggageItem(ParentIdKey));
            Assert.True(ctx.GetSamplingDecision() ?? false);
        }
        public async Task InvokeAsync(HttpContext context, ITracer tracer)
        {
            var path = context.Request.Path;

            if (Path.HasExtension(path))
            {
                await _next(context);
            }
            else
            {
                var          callingHeaders = new TextMapExtractAdapter(context.Request.Headers.ToDictionary(m => m.Key, m => m.Value.ToString()));
                var          spanContex     = tracer.Extract(BuiltinFormats.HttpHeaders, callingHeaders);
                ISpanBuilder builder        = null;
                if (spanContex != null)
                {
                    builder = tracer.BuildSpan("中间件Span").AsChildOf(spanContex);
                }
                else
                {
                    builder = tracer.BuildSpan("中间件Span");
                }
                using (IScope scope = builder.StartActive(true))
                {
                    scope.Span.SetOperationName(path);
                    // 记录请求信息到span
                    foreach (var query in context.Request.Query)
                    {
                        scope.Span.SetTag(query.Key, query.Value);
                    }
                    if (context.Request.HasFormContentType)
                    {
                        foreach (var form in context.Request.Form)
                        {
                            scope.Span.SetTag(form.Key, form.Value);
                        }
                    }
                    await _next(context);
                }
            }
        }
        public void TestDebugCorrelationId()
        {
            Tracer tracer = new Tracer.Builder("test")
                            .WithReporter(new InMemoryReporter())
                            .WithSampler(new ConstSampler(true))
                            .Build();

            var headers = new Dictionary <string, string>();

            headers.Add(Constants.DebugIdHeaderKey, "Coraline");
            ITextMap    carrier     = new TextMapExtractAdapter(headers);
            SpanContext spanContext = (SpanContext)tracer.Extract(BuiltinFormats.TextMap, carrier);

            Assert.True(spanContext.IsDebugIdContainerOnly());
            Assert.Equal("Coraline", spanContext.DebugId);
            Span span = (Span)tracer.BuildSpan("span").AsChildOf(spanContext).Start();

            spanContext = (SpanContext)span.Context;
            Assert.True(spanContext.IsSampled);
            Assert.True(spanContext.IsDebug);
            Assert.Equal("Coraline", span.GetTags()[Constants.DebugIdHeaderKey]);
        }
Exemple #14
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            //Begin code instrumentation - reference https://github.com/wavefrontHQ/wavefront-opentracing-sdk-csharp
            //The application, service, cluster, and shard variables are all metadata to be added to each span created.
            string application = "VMworld2020Demo";
            string service     = "GlobalDataAggregator";
            string cluster     = "Azure";
            string shard       = "networknerd4";

            //The URL and token are for direct ingestion of metrics, traces, and spans (no proxy in use here).
            //The API token can be found inside the Tanzu Observability (Wavefront) web UI and is unique to your environment.  Click the gear icon in the upper right, click your e-mail address, and then select API Access.
            string wfURL = "https://vmware.wavefront.com";
            string token = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

            // Create ApplicationTags - for tracing purposes
            ApplicationTags applicationTags = new ApplicationTags.Builder(application, service).Cluster(cluster).Shard(shard).Build();

            //Configure a MetricsBuilder object - for custom metrics sent via the Metrics SDK
            var MyMetricsBuilder = new MetricsBuilder();

            //Initialize WavefrontDirectIngestionClient
            WavefrontDirectIngestionClient.Builder wfDirectIngestionClientBuilder = new WavefrontDirectIngestionClient.Builder(wfURL, token);

            // Create an IWavefrontSender instance for sending data via direct ingestion.
            IWavefrontSender wavefrontSender = wfDirectIngestionClientBuilder.Build();

            //Configure MeetricsBuilder to Report to Wavefront with proper sender object and source tag specified.  In this case my source is the function name.
            MyMetricsBuilder.Report.ToWavefront(
                options =>
            {
                options.WavefrontSender = wavefrontSender;
                options.Source          = "TruckGlobalDataAggregator";
            });

            //Build IMetrics instance
            var MyMetrics = MyMetricsBuilder.Build();

            //These are arrays for key value pairs to add as metric tags.  You can add some or many here as you instrument your code.
            string[] keys = new string[3] {
                "FunctionApp", "Cloud", "Region"
            };
            string[] values = new string[3] {
                "networknerd4", "Azure", "Central-US"
            };

            // Configure and instantiate a DeltaCounter using DeltaCounterOptions.Builder.  The metric name is azure.function.execution.deltacounter.
            var myDeltaCounter = new DeltaCounterOptions.Builder("azure.function.execution.deltacounter").MeasurementUnit(Unit.Calls).Tags(new MetricTags(keys, values)).Build();

            // Increment the counter by 1
            MyMetrics.Measure.Counter.Increment(myDeltaCounter);

            //Force reporting all custom metrics
            await Task.WhenAll(MyMetrics.ReportRunner.RunAllAsync());


            //Create a WavefrontSpanReporter for reporting trace data that originates on <sourceName>.  The source is the function name in this case.
            IReporter wfSpanReporter = new WavefrontSpanReporter.Builder()
                                       .WithSource("TruckGlobalDataAggregator").Build(wavefrontSender);

            //Create CompositeReporter and ConsoleReporter objects for more OpenTracing metrics
            IReporter consoleReporter   = new ConsoleReporter("TruckGlobalDataAggregator");
            IReporter compositeReporter = new CompositeReporter(wfSpanReporter, consoleReporter);

            //Create the WavefrontTracer.
            WavefrontTracer MyTracer = new WavefrontTracer.Builder(wfSpanReporter, applicationTags).Build();

            //The variable MyDictionary is needed to extract span context in case a call is made from another function / outside this function.
            IDictionary <string, string> MyDictionary = new Dictionary <string, string>();

            foreach (var entry in req.Headers)
            {
                MyDictionary.TryAdd(entry.Key, entry.Value);
            }

            //Attempt to pull span fontext from HTTP headers passed into this function to continue a span across environments.  The proper context will be loaded into the variable
            //ctx if so.  The second line of code loads all metadata from the span context.
            ITextMap carrier = new TextMapExtractAdapter(MyDictionary);

            OpenTracing.ISpanContext ctx            = MyTracer.Extract(BuiltinFormats.HttpHeaders, carrier);
            OpenTracing.IScope       receivingScope = MyTracer.BuildSpan("TruckGlobalDataAggregator.Execute").AsChildOf(ctx).StartActive(true);

            //Start building a new span called TruckGlobalDataAggregator.Execute if there was no context passed into headers.
            if (MyTracer.ActiveSpan != null)
            {
                MyTracer.BuildSpan("TruckGlobalDataAggregator.Execute").StartActive();
            }

            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string  requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data        = JsonConvert.DeserializeObject(requestBody);

            name = name ?? data?.name;

            //Add function execution delays based on input - for personal testing only.
            if (string.Equals(name, "0.5"))
            {
                await Task.Delay(500);
            }
            if (string.Equals(name, "1"))
            {
                await Task.Delay(1000);
            }
            if (string.Equals(name, "1.5"))
            {
                await Task.Delay(1500);
            }
            if (string.Equals(name, "2"))
            {
                await Task.Delay(2000);
            }

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            //Finish the span
            MyTracer.ActiveSpan.Finish();

            //Close the tracer before application exit
            MyTracer.Close();

            return(new OkObjectResult(responseMessage));
        }