Пример #1
0
        public void AddSpanAddsSpanToCurrentBlockBuilder()
        {
            // Arrange
            var factory = SpanFactory.CreateCsHtml();
            var mockListener = new Mock<ParserVisitor>();
            var context = SetupTestContext("phoo");

            var builder = new SpanBuilder()
            {
                Kind = SpanKind.Code
            };
            builder.Accept(new CSharpSymbol(1, 0, 1, "foo", CSharpSymbolType.Identifier));
            var added = builder.Build();

            using (context.StartBlock(BlockType.Functions))
            {
                context.AddSpan(added);
            }

            var expected = new BlockBuilder()
            {
                Type = BlockType.Functions,
            };
            expected.Children.Add(added);

            // Assert
            ParserTestBase.EvaluateResults(context.CompleteParse(), expected.Build());
        }
Пример #2
0
 public SpanConstructor(SpanKind kind, IEnumerable<ISymbol> symbols)
 {
     Builder = new SpanBuilder();
     Builder.Kind = kind;
     Builder.EditHandler = SpanEditHandler.CreateDefault(TestTokenizer);
     foreach (ISymbol sym in symbols)
     {
         Builder.Accept(sym);
     }
 }
Пример #3
0
        protected override SyntaxTreeNode RewriteBlock(BlockBuilder parent, Block block)
        {
            // Collect the content of this node
            var content = string.Concat(block.Children.Cast<Span>().Select(s => s.Content));

            // Create a new span containing this content
            var span = new SpanBuilder();
            span.EditHandler = new SpanEditHandler(HtmlTokenizer.Tokenize);
            FillSpan(span, block.Children.Cast<Span>().First().Start, content);
            return span.Build();
        }
Пример #4
0
        protected override SyntaxTreeNode RewriteSpan(BlockBuilder parent, Span span)
        {
            // Only rewrite if we have a previous that is also markup (CanRewrite does this check for us!)
            var previous = parent.Children.LastOrDefault() as Span;
            if (previous == null || !CanRewrite(previous))
            {
                return span;
            }

            // Merge spans
            parent.Children.Remove(previous);
            var merged = new SpanBuilder();
            FillSpan(merged, previous.Start, previous.Content + span.Content);
            return merged.Build();
        }
Пример #5
0
 protected virtual SpanBuilder UpdateSpan(Span target, TextChange normalizedChange)
 {
     var newContent = normalizedChange.ApplyChange(target);
     var newSpan = new SpanBuilder(target);
     newSpan.ClearSymbols();
     foreach (ISymbol sym in Tokenizer(newContent))
     {
         sym.OffsetStart(target.Start);
         newSpan.Accept(sym);
     }
     if (target.Next != null)
     {
         var newEnd = SourceLocationTracker.CalculateNewLocation(target.Start, newContent);
         target.Next.ChangeStart(newEnd);
     }
     return newSpan;
 }
Пример #6
0
        private static IBlock BuildParameterInfo(Parameter parameter)
        {
            Section result = new Section(
                new Header(parameter.Documentation.Title ?? parameter.Key));

            if (!string.IsNullOrEmpty(parameter.ArgumentTemplate))
            {
                result = result.AddChild(new Paragraph(
                                             SpanBuilder.Create()
                                             .Write("Regular expression: ")
                                             .Italic($"/{parameter.ArgumentTemplate}/")));
            }

            if (!string.IsNullOrEmpty(parameter.Documentation?.Description))
            {
                result = result.AddChild(new Paragraph(parameter.Documentation.Description));
            }

            return(result);
        }
            public override void VisitSpan(Span span)
            {
                if (span.Kind == SpanKind.Markup)
                {
                    var builder = new SpanBuilder
                    {
                        CodeGenerator = span.CodeGenerator,
                        EditHandler   = span.EditHandler,
                        Kind          = span.Kind,
                        Start         = span.Start,
                    };
                    var symbol = new MarkupSymbol {
                        Content = Minify(span.Content)
                    };
                    builder.Accept(symbol);
                    span.ReplaceWith(builder);
                }

                base.VisitSpan(span);
            }
Пример #8
0
        public void StartChildSpan_WithSpecifiedSampler()
        {
            ISpan rootSpan =
                SpanBuilder.CreateWithParent(SPAN_NAME, null, spanBuilderOptions)
                .SetSampler(Samplers.AlwaysSample)
                .StartSpan();

            Assert.True(rootSpan.Context.IsValid);
            Assert.True(rootSpan.Context.TraceOptions.IsSampled);

            // Apply the given sampler for child spans.
            ISpan childSpan =
                SpanBuilder.CreateWithParent(SPAN_NAME, rootSpan, spanBuilderOptions)
                .SetSampler(Samplers.NeverSample)
                .StartSpan();

            Assert.True(childSpan.Context.IsValid);
            Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId);
            Assert.False(childSpan.Context.TraceOptions.IsSampled);
        }
        public void StartRemoteChildSpan_WithoutSpecifiedSampler()
        {
            var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                           .SetSpanKind(SpanKind.Internal)
                           .SetSampler(Samplers.NeverSample)
                           .SetNoParent()
                           .StartSpan();

            Assert.True(rootSpan.Context.IsValid);
            Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0);
            // Apply default sampler (always true in the tests) for spans with remote parent.
            var childSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                            .SetSpanKind(SpanKind.Internal)
                            .SetParent(rootSpan.Context)
                            .StartSpan();

            Assert.True(childSpan.Context.IsValid);
            Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId);
            Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0);
        }
Пример #10
0
        public void ConstructorWithBlockBuilderSetsParent()
        {
            // Arrange
            var builder = new BlockBuilder()
            {
                Type = BlockType.Comment
            };
            var span = new SpanBuilder()
            {
                Kind = SpanKind.Code
            }.Build();

            builder.Children.Add(span);

            // Act
            var block = builder.Build();

            // Assert
            Assert.Same(block, span.Parent);
        }
Пример #11
0
        public void ConstructorTransfersChildrenFromBlockBuilder()
        {
            // Arrange
            var expected = new SpanBuilder()
            {
                Kind = SpanKind.Code
            }.Build();
            var builder = new BlockBuilder()
            {
                Type = BlockType.Functions
            };

            builder.Children.Add(expected);

            // Act
            var block = builder.Build();

            // Assert
            Assert.Same(expected, block.Children.Single());
        }
Пример #12
0
        private static SyntaxTreeNode CreateMarkupAttribute(SpanBuilder builder, bool isBoundNonStringAttribute)
        {
            Span value = null;

            // Builder will be null in the case of minimized attributes
            if (builder != null)
            {
                // If the attribute was requested by a tag helper but the corresponding property was not a string,
                // then treat its value as code. A non-string value can be any C# value so we need to ensure the
                // SyntaxTreeNode reflects that.
                if (isBoundNonStringAttribute)
                {
                    builder.Kind = SpanKind.Code;
                }

                value = builder.Build();
            }

            return(value);
        }
        public void StartChildSpan()
        {
            var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                           .SetSpanKind(SpanKind.Internal)
                           .SetNoParent()
                           .StartSpan();

            Assert.True(rootSpan.Context.IsValid);
            Assert.True(rootSpan.IsRecordingEvents);
            Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0);

            var childSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                            .SetSpanKind(SpanKind.Internal)
                            .SetParent(rootSpan)
                            .StartSpan();

            Assert.True(childSpan.Context.IsValid);
            Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId);
            Assert.Equal(rootSpan.Context.SpanId, ((Span)childSpan).ToSpanData().ParentSpanId);
        }
        public void StartSpanFromCurrentActivity()
        {
            var activity = new Activity(SpanName).Start();

            activity.TraceStateString = "k1=v1,k2=v2";

            var span = new SpanBuilder(SpanName, spanBuilderOptions)
                       .SetSpanKind(SpanKind.Internal)
                       .SetCreateChild(false)
                       .StartSpan();

            Assert.True(span.Context.IsValid);
            Assert.Equal(activity.TraceId, span.Context.TraceId);
            Assert.Equal(activity.SpanId, span.Context.SpanId);
            Assert.True(((Span)span).ParentSpanId == default);

            Assert.NotNull(Activity.Current);
            Assert.Equal(Activity.Current, activity);
            Assert.Equal("k1=v1,k2=v2", span.Context.Tracestate.ToString());
        }
Пример #15
0
        public void StartChildSpan()
        {
            var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTracerConfiguration, Resource.Empty)
                           .SetSpanKind(SpanKind.Internal)
                           .SetNoParent()
                           .StartSpan();

            Assert.True(rootSpan.Context.IsValid);
            Assert.True(rootSpan.IsRecordingEvents);
            Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0);

            var childSpan = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTracerConfiguration, Resource.Empty)
                            .SetSpanKind(SpanKind.Internal)
                            .SetParent(rootSpan)
                            .StartSpan();

            Assert.True(childSpan.Context.IsValid);
            Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId);
            Assert.Equal(rootSpan.Context.SpanId, childSpan.ParentSpanId);
        }
Пример #16
0
        public void StartSpanFromCurrentRecordedActivity()
        {
            var activity = new Activity(SpanName)
                           .SetIdFormat(ActivityIdFormat.W3C)
                           .Start();

            activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded;

            var span = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTracerConfiguration, Resource.Empty)
                       .SetSpanKind(SpanKind.Internal)
                       .SetCreateChild(false)
                       .StartSpan();

            Assert.True(span.Context.IsValid);
            Assert.Equal(activity.TraceId, span.Context.TraceId);
            Assert.Equal(activity.SpanId, span.Context.SpanId);
            Assert.True(((Span)span).ParentSpanId == default);
            Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0);
            activity.Stop();
        }
        public void DateSpecificRetry_CorrectDelayDuration()
        {
            var traceId         = "123";
            var retryDuration   = TimeSpan.FromSeconds(10);
            var retryDurationMs = retryDuration.TotalMilliseconds;
            var errorMargin     = TimeSpan.FromMilliseconds(50).TotalMilliseconds;

            var spanBatch = SpanBatchBuilder.Create()
                            .WithTraceId(traceId)
                            .WithSpan(SpanBuilder.Create("TestSpan").Build())
                            .Build();

            var config = new TelemetryConfiguration().WithAPIKey("12345");

            var dataSender = new SpanDataSender(config);

            //Mock out the communication layer
            dataSender.WithHttpHandlerImpl((serializedJson) =>
            {
                var response                = new HttpResponseMessage((System.Net.HttpStatusCode) 429);
                var retryOnSpecificTime     = DateTimeOffset.Now + retryDuration;
                response.Headers.RetryAfter = new System.Net.Http.Headers.RetryConditionHeaderValue(retryOnSpecificTime);
                return(Task.FromResult(response));
            });

            var capturedDelays = new List <int>();

            dataSender.WithDelayFunction((delay) =>
            {
                capturedDelays.Add(delay);
                return(Task.Delay(0));
            });

            var response = dataSender.SendDataAsync(spanBatch).Result;

            Assert.AreEqual(NewRelicResponseStatus.Failure, response.ResponseStatus);
            Assert.AreEqual(config.MaxRetryAttempts, capturedDelays.Count);
            Assert.AreEqual(System.Net.HttpStatusCode.RequestTimeout, response.HttpStatusCode);
            Assert.IsTrue(capturedDelays.All(x => x >= retryDurationMs - errorMargin && x <= retryDurationMs + errorMargin),
                          "Expected duration out of range");
        }
Пример #18
0
        protected virtual SpanBuilder UpdateSpan(Span target, TextChange normalizedChange)
        {
            string      newContent = normalizedChange.ApplyChange(target);
            SpanBuilder newSpan    = new SpanBuilder(target);

            newSpan.ClearSymbols();
            foreach (ISymbol sym in Tokenizer(newContent))
            {
                sym.OffsetStart(target.Start);
                newSpan.Accept(sym);
            }
            if (target.Next != null)
            {
                SourceLocation newEnd = SourceLocationTracker.CalculateNewLocation(
                    target.Start,
                    newContent
                    );
                target.Next.ChangeStart(newEnd);
            }
            return(newSpan);
        }
        public void StartSpanInScopeOfCurrentActivity()
        {
            var parentActivity = new Activity(SpanName).Start();

            parentActivity.TraceStateString = "k1=v1,k2=v2";

            var childSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                            .SetSpanKind(SpanKind.Internal)
                            .StartSpan();

            Assert.True(childSpan.Context.IsValid);
            Assert.Equal(parentActivity.TraceId, childSpan.Context.TraceId);
            Assert.Equal(parentActivity.SpanId, ((Span)childSpan).ParentSpanId);

            var activity = ((Span)childSpan).Activity;

            Assert.Equal(parentActivity, Activity.Current);
            Assert.Equal(activity.Parent, parentActivity);

            Assert.Equal("k1=v1,k2=v2", childSpan.Context.Tracestate.ToString());
        }
Пример #20
0
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            var spanContext = _spanContextExtractor
                              .Extract(WebOperationContext.Current?.IncomingRequest);

            spanContext.Sample(_sampler);

            var spanBuilder = new SpanBuilder(spanContext);

            spanBuilder.Start()
            .Tag("action", request.Headers.Action)
            .Kind(SpanKind.Server)
            .WithLocalEndpoint(new Endpoint
            {
                ServiceName = _localEndpointName
            });

            _spanContextAccessor.SaveContext(spanContext);

            return(spanBuilder);
        }
        public void StartChildSpan()
        {
            var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                           .SetSpanKind(SpanKind.Internal)
                           .SetNoParent()
                           .StartSpan();

            Assert.True(rootSpan.Context.IsValid);
            Assert.True(rootSpan.IsRecordingEvents);
            Assert.True(rootSpan.Context.TraceOptions.IsSampled);

            var childSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                            .SetSpanKind(Trace.SpanKind.Internal)
                            .SetParent(rootSpan)
                            .StartSpan();

            Assert.True(childSpan.Context.IsValid);
            Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId);
            Assert.Equal(rootSpan.Context.SpanId, ((Span)childSpan).ToSpanData().ParentSpanId);
            Assert.Equal(((Span)rootSpan).TimestampConverter, ((Span)childSpan).TimestampConverter);
        }
        public void SendANonEmptySpanBatch()
        {
            var traceId = "123";

            var spanBatch = SpanBatchBuilder.Create()
                            .WithTraceId(traceId)
                            .WithSpan(SpanBuilder.Create("TestSpan").Build())
                            .Build();

            var dataSender = new SpanDataSender(new TelemetryConfiguration().WithAPIKey("123456"));

            dataSender.WithHttpHandlerImpl((serializedJson) =>
            {
                var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
                return(Task.FromResult(response));
            });

            var response = dataSender.SendDataAsync(spanBatch).Result;

            Assert.AreEqual(NewRelicResponseStatus.Success, response.ResponseStatus);
        }
        public void StartSpan_ExplicitNoParent()
        {
            var span = new SpanBuilder(SpanName, spanBuilderOptions)
                       .SetSpanKind(SpanKind.Internal)
                       .SetNoParent()
                       .StartSpan();

            Assert.True(span.Context.IsValid);
            Assert.True(span.IsRecordingEvents);
            Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0);
            var spanData = ((Span)span).ToSpanData();

            Assert.True(spanData.ParentSpanId == default);

            var activity = ((Span)span).Activity;

            Assert.Null(Activity.Current);
            Assert.Equal(activity.TraceId, span.Context.TraceId);
            Assert.Equal(activity.SpanId, span.Context.SpanId);
            Assert.Empty(span.Context.Tracestate.Entries);
        }
        public void StartRemoteSpan()
        {
            var spanContext =
                SpanContext.Create(
                    TraceId.GenerateRandomId(randomHandler),
                    SpanId.GenerateRandomId(randomHandler),
                    TraceOptions.Default, Tracestate.Empty);

            var span = new SpanBuilder(SpanName, spanBuilderOptions)
                       .SetSpanKind(SpanKind.Internal)
                       .SetParent(spanContext)
                       .SetRecordEvents(true)
                       .StartSpan();

            Assert.True(span.Context.IsValid);
            Assert.Equal(spanContext.TraceId, span.Context.TraceId);
            Assert.False(span.Context.TraceOptions.IsSampled);
            var spanData = ((Span)span).ToSpanData();

            Assert.Equal(spanContext.SpanId, spanData.ParentSpanId);
        }
        public void StartRemoteChildSpan_WithSpecifiedSampler()
        {
            var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                           .SetSpanKind(SpanKind.Internal)
                           .SetSampler(Samplers.AlwaysSample)
                           .SetNoParent()
                           .StartSpan();

            Assert.True(rootSpan.Context.IsValid);
            Assert.True(rootSpan.Context.TraceOptions.IsSampled);
            // Apply given sampler before default sampler for spans with remote parent.
            var childSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                            .SetSpanKind(SpanKind.Internal)
                            .SetSampler(Samplers.NeverSample)
                            .SetParent(rootSpan.Context)
                            .StartSpan();

            Assert.True(childSpan.Context.IsValid);
            Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId);
            Assert.False(childSpan.Context.TraceOptions.IsSampled);
        }
        protected override SyntaxTreeNode RewriteBlock(BlockBuilder parent, Block block)
        {
            // Collect the content of this node
            var builder = new StringBuilder();

            for (var i = 0; i < block.Children.Count; i++)
            {
                var childSpan = (Span)block.Children[i];
                builder.Append(childSpan.Content);
            }

            // Create a new span containing this content
            var span = new SpanBuilder();

            span.EditHandler = new SpanEditHandler(HtmlTokenizer.Tokenize);
            Debug.Assert(block.Children.Count > 0);
            var start = ((Span)block.Children[0]).Start;

            FillSpan(span, start, builder.ToString());
            return(span.Build());
        }
        public void StartChildSpan_WithSpecifiedSampler()
        {
            var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                           .SetSpanKind(SpanKind.Internal)
                           .SetSampler(Samplers.AlwaysSample)
                           .SetNoParent()
                           .StartSpan();

            Assert.True(rootSpan.Context.IsValid);
            Assert.True((rootSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0);
            // Apply the given sampler for child spans.

            var childSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                            .SetSpanKind(SpanKind.Internal)
                            .SetSampler(Samplers.NeverSample)
                            .SetParent(rootSpan)
                            .StartSpan();

            Assert.True(childSpan.Context.IsValid);
            Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId);
            Assert.True((childSpan.Context.TraceOptions & ActivityTraceFlags.Recorded) == 0);
        }
Пример #28
0
        public Span Span(SpanKind kind, params ISymbol[] symbols)
        {
            var builder = new SpanBuilder();

            builder.Kind = kind;

            foreach (var symbol in symbols)
            {
                builder.Accept(symbol);
            }

            var span = builder.Build();

            if (_last != null)
            {
                span.Previous = _last;
                _last.Next    = span;
            }
            _last = span;

            return(span);
        }
        public void StartSpan_WithLinkFromActivity()
        {
            var activityLink = new Activity("foo").Start();

            activityLink.Stop();

            var span = new SpanBuilder(SpanName, spanBuilderOptions)
                       .SetSpanKind(SpanKind.Internal)
                       .AddLink(activityLink)
                       .StartSpan();

            var spanData = ((Span)span).ToSpanData();
            var links    = spanData.Links.Links.ToArray();

            Assert.Single(links);

            Assert.Equal(activityLink.TraceId, links[0].Context.TraceId);
            Assert.Equal(activityLink.SpanId, links[0].Context.SpanId);
            Assert.Equal(activityLink.ActivityTraceFlags, links[0].Context.TraceOptions);
            Assert.Empty(links[0].Context.Tracestate.Entries);
            Assert.Equal(0, links[0].Attributes.Count);
        }
        public void StartSpanNullParent()
        {
            var span = new SpanBuilder(SpanName, spanBuilderOptions)
                       .SetSpanKind(SpanKind.Internal)
                       .SetNoParent()
                       .StartSpan();

            Assert.True(span.Context.IsValid);
            Assert.True(span.IsRecordingEvents);
            Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0);
            var spanData = ((Span)span).ToSpanData();

            Assert.True(spanData.ParentSpanId == default);
            Assert.InRange(spanData.StartTimestamp, PreciseTimestamp.GetUtcNow().AddSeconds(-1), PreciseTimestamp.GetUtcNow().AddSeconds(1));
            Assert.Equal(SpanName, spanData.Name);

            var activity = ((Span)span).Activity;

            Assert.Null(Activity.Current);
            Assert.Equal(activity.TraceId, span.Context.TraceId);
            Assert.Equal(activity.SpanId, span.Context.SpanId);
        }
        public void StartSpan_CurrentSpanParent()
        {
            var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions)
                           .SetParent(
                SpanContext.Create(
                    ActivityTraceId.CreateRandom(),
                    ActivitySpanId.CreateRandom(),
                    ActivityTraceFlags.None,
                    Tracestate.Builder.Set("k1", "v1").Build()))
                           .StartSpan();

            using (tracer.WithSpan(rootSpan))
            {
                var childSpan = (Span) new SpanBuilder(SpanName, spanBuilderOptions)
                                .StartSpan();

                Assert.True(childSpan.Context.IsValid);
                Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId);
                Assert.Equal(rootSpan.Context.SpanId, childSpan.ParentSpanId);
                Assert.Equal("k1=v1", childSpan.Context.Tracestate.ToString());
            }
        }
        public override void VisitSpan(Span span)
        {
            if (span.Kind == SpanKind.Markup)
            {
                string content = span.Content;

                content = _minifier.Minify(content);

                // We replace the content with the minified markup
                // and then let the CSharp/VB generator do their jobs.
                var builder = new SpanBuilder {
                    CodeGenerator = span.CodeGenerator, EditHandler = span.EditHandler, Kind = span.Kind, Start = span.Start
                };
                var symbol = new MarkupSymbol {
                    Content = content
                };
                builder.Accept(symbol);
                span.ReplaceWith(builder);
            }

            base.VisitSpan(span);
        }
Пример #33
0
        public void HttpRequest([Property(Name = "Request")] HttpRequestMessage request)
        {
            var patterns = _options.IgnoredRoutesRegexPatterns;

            if (patterns == null || patterns.Any(x => Regex.IsMatch(request.RequestUri.AbsolutePath, x)))
            {
                return;
            }
            var spanBuilder = new SpanBuilder($"httpclient {request.Method} {request.RequestUri.AbsolutePath}");
            var spanContext = _tracer.Tracer.GetEntrySpan()?.SpanContext;

            if (spanContext != null)
            {
                spanBuilder.AsChildOf(spanContext);
            }
            var span = _tracer.Start(spanBuilder);

            span.Tags.Client().Component("HttpClient")
            .HttpMethod(request.Method.Method)
            .HttpUrl(request.RequestUri.OriginalString)
            .HttpHost(request.RequestUri.Host)
            .HttpPath(request.RequestUri.PathAndQuery)
            .PeerAddress(request.RequestUri.OriginalString)
            .PeerHostName(request.RequestUri.Host)
            .PeerPort(request.RequestUri.Port);

            _tracer.Tracer.Inject(span.SpanContext, request.Headers, (c, k, v) => c.Add(k, v));
            span.Log(LogField.CreateNew().ClientSend());
            if (request.Method == HttpMethod.Post && _options.TraceHttpContent && request.Content != null)
            {
                var result = request.Content.ReadAsStringAsync().Result;
                if (!string.IsNullOrWhiteSpace(result))
                {
                    span.Tags.Add("http.request", _tbbrRegex.Replace(result, ""));
                }
            }

            _tracer.Tracer.SetExitSpan(span);
        }
 public void Double(double a, double b, string format)
 {
     var value    = a / b;
     var expected = value.ToString(format, CultureInfo.InvariantCulture);
     {
         Span <char> span    = stackalloc char[500];
         var         builder = new SpanBuilder(span);
         builder.Append(value);
         Assert.Equal(expected, builder.ToString());
     }
     {
         Span <char> span    = stackalloc char[500];
         var         builder = new SpanBuilder(span);
         Assert.True(builder.TryAppend(value));
         Assert.Equal(expected, builder.ToString());
     }
     {
         Span <char> span    = stackalloc char[expected.Length - 1];
         var         builder = new SpanBuilder(span);
         Assert.False(builder.TryAppend(value));
     }
 }
Пример #35
0
        void Simplify(ref SpanBuilder builder, string source)
        {
            var currentCulture = CultureInfo.CurrentCulture;
            var src            = source.AsSpan();
            var isDelimiter    = false;
            var srcLength      = src.Length;
            var lastIndex      = srcLength - 1;

            for (var i = 0; i < srcLength; ++i)
            {
                var ch = currentCulture.TextInfo.ToLower(src[i]);
                if (_map.TryGetValue(ch, out var replacement))
                {
                    builder.Append(replacement);
                    isDelimiter = false;
                }
                else
                {
                    if (!IsSimple(ch))
                    {
                        ch = Delimiter;
                    }
                    if (Delimiter == ch)
                    {
                        if (builder.Length != 0 && i < lastIndex && !isDelimiter)
                        {
                            builder.Append(ch);
                            isDelimiter = true;
                        }
                    }
                    else
                    {
                        builder.Append(ch);
                        isDelimiter = false;
                    }
                }
            }
        }
Пример #36
0
        protected override SyntaxTreeNode RewriteBlock(BlockBuilder parent, Block block)
        {
            var newBlock = new BlockBuilder(block);
            newBlock.Children.Clear();
            var ws = block.Children.FirstOrDefault() as Span;
            IEnumerable<SyntaxTreeNode> newNodes = block.Children;
            if (ws.Content.All(Char.IsWhiteSpace))
            {
                // Add this node to the parent
                var builder = new SpanBuilder(ws);
                builder.ClearSymbols();
                FillSpan(builder, ws.Start, ws.Content);
                parent.Children.Add(builder.Build());

                // Remove the old whitespace node
                newNodes = block.Children.Skip(1);
            }

            foreach (SyntaxTreeNode node in newNodes)
            {
                newBlock.Children.Add(node);
            }
            return newBlock.Build();
        }
Пример #37
0
 public Span(SpanBuilder builder)
 {
     ReplaceWith(builder);
 }
Пример #38
0
 public abstract void BuildSpan(SpanBuilder span, SourceLocation start, string content);
Пример #39
0
 public override void BuildSpan(SpanBuilder span, SourceLocation start, string content)
 {
     throw new NotImplementedException();
 }
Пример #40
0
        public void ReplaceWith(SpanBuilder builder)
        {
            Kind = builder.Kind;
            Symbols = builder.Symbols;
            EditHandler = builder.EditHandler;
            ChunkGenerator = builder.ChunkGenerator ?? SpanChunkGenerator.Null;
            _start = builder.Start;
            _content = null;

            // Since we took references to the values in SpanBuilder, clear its references out
            builder.Reset();
        }
Пример #41
0
 protected void FillSpan(SpanBuilder builder, SourceLocation start, string content)
 {
     _markupSpanFactory(builder, start, content);
 }
Пример #42
0
        private static Span CreateMarkupAttribute(SpanBuilder builder, bool isBoundNonStringAttribute)
        {
            Debug.Assert(builder != null);

            // If the attribute was requested by a tag helper but the corresponding property was not a string,
            // then treat its value as code. A non-string value can be any C# value so we need to ensure the
            // SyntaxTreeNode reflects that.
            if (isBoundNonStringAttribute)
            {
                builder.Kind = SpanKind.Code;
            }

            return builder.Build();
        }
Пример #43
0
        private static Block RebuildChunkGenerators(Block block, bool isBound)
        {
            var builder = new BlockBuilder(block);

            // Don't want to rebuild unbound dynamic attributes. They need to run through the conditional attribute
            // removal system at runtime. A conditional attribute at the parse tree rewriting level is defined by
            // having at least 1 child with a DynamicAttributeBlockChunkGenerator.
            if (!isBound &&
                block.Children.Any(
                    child => child.IsBlock &&
                    ((Block)child).ChunkGenerator is DynamicAttributeBlockChunkGenerator))
            {
                // The parent chunk generator must be removed because it's normally responsible for conditionally
                // generating the attribute prefix (class=") and suffix ("). The prefix and suffix concepts aren't
                // applicable for the TagHelper use case since the attributes are put into a dictionary like object as
                // name value pairs.
                builder.ChunkGenerator = ParentChunkGenerator.Null;

                return builder.Build();
            }

            var isDynamic = builder.ChunkGenerator is DynamicAttributeBlockChunkGenerator;

            // We don't want any attribute specific logic here, null out the block chunk generator.
            if (isDynamic || builder.ChunkGenerator is AttributeBlockChunkGenerator)
            {
                builder.ChunkGenerator = ParentChunkGenerator.Null;
            }

            for (var i = 0; i < builder.Children.Count; i++)
            {
                var child = builder.Children[i];

                if (child.IsBlock)
                {
                    // The child is a block, recurse down into the block to rebuild its children
                    builder.Children[i] = RebuildChunkGenerators((Block)child, isBound);
                }
                else
                {
                    var childSpan = (Span)child;
                    ISpanChunkGenerator newChunkGenerator = null;
                    var literalGenerator = childSpan.ChunkGenerator as LiteralAttributeChunkGenerator;

                    if (literalGenerator != null)
                    {
                        if (literalGenerator.ValueGenerator == null || literalGenerator.ValueGenerator.Value == null)
                        {
                            newChunkGenerator = new MarkupChunkGenerator();
                        }
                        else
                        {
                            newChunkGenerator = literalGenerator.ValueGenerator.Value;
                        }
                    }
                    else if (isDynamic && childSpan.ChunkGenerator == SpanChunkGenerator.Null)
                    {
                        // Usually the dynamic chunk generator handles creating the null chunk generators underneath
                        // it. This doesn't make sense in terms of tag helpers though, we need to change null code
                        // generators to markup chunk generators.

                        newChunkGenerator = new MarkupChunkGenerator();
                    }

                    // If we have a new chunk generator we'll need to re-build the child
                    if (newChunkGenerator != null)
                    {
                        var childSpanBuilder = new SpanBuilder(childSpan)
                        {
                            ChunkGenerator = newChunkGenerator
                        };

                        builder.Children[i] = childSpanBuilder.Build();
                    }
                }
            }

            return builder.Build();
        }
Пример #44
0
        private static TryParseResult TryParseBlock(
            string tagName,
            Block block,
            IEnumerable<TagHelperDescriptor> descriptors,
            ErrorSink errorSink)
        {
            // TODO: Accept more than just spans: https://github.com/aspnet/Razor/issues/96.
            // The first child will only ever NOT be a Span if a user is doing something like:
            // <input @checked />

            var childSpan = block.Children.First() as Span;

            if (childSpan == null || childSpan.Kind != SpanKind.Markup)
            {
                errorSink.OnError(
                    block.Start,
                    RazorResources.FormatTagHelpers_CannotHaveCSharpInTagDeclaration(tagName),
                    block.Length);

                return null;
            }

            var builder = new BlockBuilder(block);

            // If there's only 1 child it means that it's plain text inside of the attribute.
            // i.e. <div class="plain text in attribute">
            if (builder.Children.Count == 1)
            {
                return TryParseSpan(childSpan, descriptors, errorSink);
            }

            var nameSymbols = childSpan
                .Symbols
                .OfType<HtmlSymbol>()
                .SkipWhile(symbol => !HtmlMarkupParser.IsValidAttributeNameSymbol(symbol)) // Skip prefix
                .TakeWhile(nameSymbol => HtmlMarkupParser.IsValidAttributeNameSymbol(nameSymbol))
                .Select(nameSymbol => nameSymbol.Content);

            var name = string.Concat(nameSymbols);
            if (string.IsNullOrEmpty(name))
            {
                errorSink.OnError(
                    childSpan.Start,
                    RazorResources.FormatTagHelpers_AttributesMustHaveAName(tagName),
                    childSpan.Length);

                return null;
            }

            // Have a name now. Able to determine correct isBoundNonStringAttribute value.
            var result = CreateTryParseResult(name, descriptors);

            var firstChild = builder.Children[0] as Span;
            if (firstChild != null && firstChild.Symbols[0] is HtmlSymbol)
            {
                var htmlSymbol = firstChild.Symbols[firstChild.Symbols.Count - 1] as HtmlSymbol;
                switch (htmlSymbol.Type)
                {
                    // Treat NoQuotes and DoubleQuotes equivalently. We purposefully do not persist NoQuotes
                    // ValueStyles at code generation time to protect users from rendering dynamic content with spaces
                    // that can break attributes.
                    // Ex: <tag my-attribute=@value /> where @value results in the test "hello world".
                    // This way, the above code would render <tag my-attribute="hello world" />.
                    case HtmlSymbolType.Equals:
                    case HtmlSymbolType.DoubleQuote:
                        result.AttributeValueStyle = HtmlAttributeValueStyle.DoubleQuotes;
                        break;
                    case HtmlSymbolType.SingleQuote:
                        result.AttributeValueStyle = HtmlAttributeValueStyle.SingleQuotes;
                        break;
                    default:
                        result.AttributeValueStyle = HtmlAttributeValueStyle.Minimized;
                        break;
                }
            }

            // Remove first child i.e. foo="
            builder.Children.RemoveAt(0);

            // Grabbing last child to check if the attribute value is quoted.
            var endNode = block.Children.Last();
            if (!endNode.IsBlock)
            {
                var endSpan = (Span)endNode;

                // In some malformed cases e.g. <p bar="false', the last Span (false' in the ex.) may contain more
                // than a single HTML symbol. Do not ignore those other symbols.
                var symbolCount = endSpan.Symbols.Count();
                var endSymbol = symbolCount == 1 ? (HtmlSymbol)endSpan.Symbols.First() : null;

                // Checking to see if it's a quoted attribute, if so we should remove end quote
                if (endSymbol != null && IsQuote(endSymbol))
                {
                    builder.Children.RemoveAt(builder.Children.Count - 1);
                }
            }

            // We need to rebuild the chunk generators of the builder and its children (this is needed to
            // ensure we don't do special attribute chunk generation since this is a tag helper).
            block = RebuildChunkGenerators(builder.Build(), result.IsBoundAttribute);

            // If there's only 1 child at this point its value could be a simple markup span (treated differently than
            // block level elements for attributes).
            if (block.Children.Count() == 1)
            {
                var child = block.Children.First() as Span;
                if (child != null)
                {
                    // After pulling apart the block we just have a value span.
                    var spanBuilder = new SpanBuilder(child);

                    result.AttributeValueNode =
                        CreateMarkupAttribute(spanBuilder, result.IsBoundNonStringAttribute);

                    return result;
                }
            }

            var isFirstSpan = true;

            result.AttributeValueNode = ConvertToMarkupAttributeBlock(
                block,
                (parentBlock, span) =>
                {
                    // If the attribute was requested by a tag helper but the corresponding property was not a
                    // string, then treat its value as code. A non-string value can be any C# value so we need
                    // to ensure the SyntaxTreeNode reflects that.
                    if (result.IsBoundNonStringAttribute)
                    {
                        // For bound non-string attributes, we'll only allow a transition span to appear at the very
                        // beginning of the attribute expression. All later transitions would appear as code so that
                        // they are part of the generated output. E.g.
                        // key="@value" -> MyTagHelper.key = value
                        // key=" @value" -> MyTagHelper.key =  @value
                        // key="1 + @case" -> MyTagHelper.key = 1 + @case
                        // key="@int + @case" -> MyTagHelper.key = int + @case
                        // key="@(a + b) -> MyTagHelper.key = a + b
                        // key="4 + @(a + b)" -> MyTagHelper.key = 4 + @(a + b)
                        if (isFirstSpan && span.Kind == SpanKind.Transition)
                        {
                            // do nothing.
                        }
                        else
                        {
                            var spanBuilder = new SpanBuilder(span);

                            if (parentBlock.Type == BlockType.Expression &&
                                (spanBuilder.Kind == SpanKind.Transition ||
                                spanBuilder.Kind == SpanKind.MetaCode))
                            {
                                // Change to a MarkupChunkGenerator so that the '@' \ parenthesis is generated as part of the output.
                                spanBuilder.ChunkGenerator = new MarkupChunkGenerator();
                            }

                            spanBuilder.Kind = SpanKind.Code;
                            span = spanBuilder.Build();
                        }
                    }

                    isFirstSpan = false;

                    return span;
                });

            return result;
        }
Пример #45
0
        // This method handles cases when the attribute is a simple span attribute such as
        // class="something moresomething".  This does not handle complex attributes such as
        // class="@myclass". Therefore the span.Content is equivalent to the entire attribute.
        private static TryParseResult TryParseSpan(
            Span span,
            IEnumerable<TagHelperDescriptor> descriptors,
            ErrorSink errorSink)
        {
            var afterEquals = false;
            var builder = new SpanBuilder
            {
                ChunkGenerator = span.ChunkGenerator,
                EditHandler = span.EditHandler,
                Kind = span.Kind
            };

            // Will contain symbols that represent a single attribute value: <input| class="btn"| />
            var htmlSymbols = span.Symbols.OfType<HtmlSymbol>().ToArray();
            var capturedAttributeValueStart = false;
            var attributeValueStartLocation = span.Start;

            // Default to DoubleQuotes. We purposefully do not persist NoQuotes ValueStyle to stay consistent with the
            // TryParseBlock() variation of attribute parsing.
            var attributeValueStyle = HtmlAttributeValueStyle.DoubleQuotes;

            // The symbolOffset is initialized to 0 to expect worst case: "class=". If a quote is found later on for
            // the attribute value the symbolOffset is adjusted accordingly.
            var symbolOffset = 0;
            string name = null;

            // Iterate down through the symbols to find the name and the start of the value.
            // We subtract the symbolOffset so we don't accept an ending quote of a span.
            for (var i = 0; i < htmlSymbols.Length - symbolOffset; i++)
            {
                var symbol = htmlSymbols[i];

                if (afterEquals)
                {
                    // We've captured all leading whitespace, the attribute name, and an equals with an optional
                    // quote/double quote. We're now at: " asp-for='|...'" or " asp-for=|..."
                    // The goal here is to capture all symbols until the end of the attribute. Note this will not
                    // consume an ending quote due to the symbolOffset.

                    // When symbols are accepted into SpanBuilders, their locations get altered to be offset by the
                    // parent which is why we need to mark our start location prior to adding the symbol.
                    // This is needed to know the location of the attribute value start within the document.
                    if (!capturedAttributeValueStart)
                    {
                        capturedAttributeValueStart = true;

                        attributeValueStartLocation = span.Start + symbol.Start;
                    }

                    builder.Accept(symbol);
                }
                else if (name == null && HtmlMarkupParser.IsValidAttributeNameSymbol(symbol))
                {
                    // We've captured all leading whitespace prior to the attribute name.
                    // We're now at: " |asp-for='...'" or " |asp-for=..."
                    // The goal here is to capture the attribute name.

                    var symbolContents = htmlSymbols
                        .Skip(i) // Skip prefix
                        .TakeWhile(nameSymbol => HtmlMarkupParser.IsValidAttributeNameSymbol(nameSymbol))
                        .Select(nameSymbol => nameSymbol.Content);

                    // Move the indexer past the attribute name symbols.
                    i += symbolContents.Count() - 1;

                    name = string.Concat(symbolContents);
                    attributeValueStartLocation = SourceLocation.Advance(attributeValueStartLocation, name);
                }
                else if (symbol.Type == HtmlSymbolType.Equals)
                {
                    // We've captured all leading whitespace and the attribute name.
                    // We're now at: " asp-for|='...'" or " asp-for|=..."
                    // The goal here is to consume the equal sign and the optional single/double-quote.

                    // The coming symbols will either be a quote or value (in the case that the value is unquoted).

                    SourceLocation symbolStartLocation;

                    // Skip the whitespace preceding the start of the attribute value.
                    do
                    {
                        i++; // Start from the symbol after '='.
                    } while (i < htmlSymbols.Length &&
                        (htmlSymbols[i].Type == HtmlSymbolType.WhiteSpace ||
                        htmlSymbols[i].Type == HtmlSymbolType.NewLine));

                    // Check for attribute start values, aka single or double quote
                    if (i < htmlSymbols.Length && IsQuote(htmlSymbols[i]))
                    {
                        if (htmlSymbols[i].Type == HtmlSymbolType.SingleQuote)
                        {
                            attributeValueStyle = HtmlAttributeValueStyle.SingleQuotes;
                        }

                        symbolStartLocation = htmlSymbols[i].Start;

                        // If there's a start quote then there must be an end quote to be valid, skip it.
                        symbolOffset = 1;
                    }
                    else
                    {
                        // We are at the symbol after equals. Go back to equals to ensure we don't skip past that symbol.
                        i--;

                        symbolStartLocation = symbol.Start;
                    }

                    attributeValueStartLocation =
                        span.Start +
                        symbolStartLocation +
                        new SourceLocation(absoluteIndex: 1, lineIndex: 0, characterIndex: 1);

                    afterEquals = true;
                }
                else if (symbol.Type == HtmlSymbolType.WhiteSpace)
                {
                    // We're at the start of the attribute, this branch may be hit on the first iterations of
                    // the loop since the parser separates attributes with their spaces included as symbols.
                    // We're at: "| asp-for='...'" or "| asp-for=..."
                    // Note: This will not be hit even for situations like asp-for  ="..." because the core Razor
                    // parser currently does not know how to handle attributes in that format. This will be addressed
                    // by https://github.com/aspnet/Razor/issues/123.

                    attributeValueStartLocation = SourceLocation.Advance(attributeValueStartLocation, symbol.Content);
                }
            }

            // After all symbols have been added we need to set the builders start position so we do not indirectly
            // modify each symbol's Start location.
            builder.Start = attributeValueStartLocation;

            if (name == null)
            {
                // We couldn't find a name, if the original span content was whitespace it ultimately means the tag
                // that owns this "attribute" is malformed and is expecting a user to type a new attribute.
                // ex: <myTH class="btn"| |
                if (!string.IsNullOrWhiteSpace(span.Content))
                {
                    errorSink.OnError(
                        span.Start,
                        RazorResources.TagHelperBlockRewriter_TagHelperAttributeListMustBeWellFormed,
                        span.Content.Length);
                }

                return null;
            }

            var result = CreateTryParseResult(name, descriptors);

            // If we're not after an equal then we should treat the value as if it were a minimized attribute.
            Span attributeValue = null;
            if (afterEquals)
            {
                attributeValue = CreateMarkupAttribute(builder, result.IsBoundNonStringAttribute);
            }
            else
            {
                attributeValueStyle = HtmlAttributeValueStyle.Minimized;
            }

            result.AttributeValueNode = attributeValue;
            result.AttributeValueStyle = attributeValueStyle;
            return result;
        }
Пример #46
0
 public void Change(Action<SpanBuilder> changes)
 {
     var builder = new SpanBuilder(this);
     changes(builder);
     ReplaceWith(builder);
 }