public void SubmitsMetrics()
        {
            int agentPort = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");

            SetEnvironmentVariable("OTEL_RUNTIME_METRICS_ENABLED", "1");

            using var agent = new MockTracerAgent(agentPort, useStatsd: true);
            Output.WriteLine($"Assigning port {agent.StatsdPort} for the statsdPort.");

            using var processResult = RunSampleAndWaitForExit(agent.Port, agent.StatsdPort);
            var requests = agent.StatsdRequests;

            // Check if we receive 2 kinds of metrics:
            // - exception count is gathered using common .NET APIs
            // - contention count is gathered using platform-specific APIs

            var exceptionRequestsCount = requests.Count(r => r.Contains("runtime.dotnet.exceptions.count"));

            Assert.True(exceptionRequestsCount > 0, "No exception metrics received. Metrics received: " + string.Join("\n", requests));

            // Check if .NET Framework or .NET Core 3.1+
            if (!EnvironmentHelper.IsCoreClr() ||
                (Environment.Version.Major == 3 && Environment.Version.Minor == 1) ||
                Environment.Version.Major >= 5)
            {
                var contentionRequestsCount = requests.Count(r => r.Contains("runtime.dotnet.threads.contention_count"));

                Assert.True(contentionRequestsCount > 0, "No contention metrics received. Metrics received: " + string.Join("\n", requests));
            }

            Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");
        }
コード例 #2
0
        public void WebClient()
        {
            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"WebClient Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(1);
                    Assert.True(spans.Count > 0, "expected at least one span." + System.Environment.NewLine + "IMPORTANT: Make sure Datadog.Trace.ClrProfiler.Managed.dll and its dependencies are in the GAC.");

                    var traceId      = GetHeader(processResult.StandardOutput, HttpHeaderNames.TraceId);
                    var parentSpanId = GetHeader(processResult.StandardOutput, HttpHeaderNames.ParentId);

                    // inspect the top-level span, underlying spans can be HttpMessageHandler in .NET Core
                    var firstSpan = spans.First();
                    Assert.Equal("http.request", firstSpan.Name);
                    Assert.Equal("Samples.HttpMessageHandler-http-client", firstSpan.Service);
                    Assert.Equal(SpanTypes.Http, firstSpan.Type);
                    Assert.Equal(nameof(WebRequest), firstSpan.Tags[Tags.InstrumentationName]);

                    var lastSpan = spans.Last();
                    Assert.Equal(lastSpan.TraceId.ToString(CultureInfo.InvariantCulture), traceId);
                    Assert.Equal(lastSpan.SpanId.ToString(CultureInfo.InvariantCulture), parentSpanId);
                }
        }
コード例 #3
0
        public void HttpClient()
        {
            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"HttpClient Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(1);
                    Assert.True(spans.Count > 0, "expected at least one span");

                    var traceId      = GetHeader(processResult.StandardOutput, HttpHeaderNames.TraceId);
                    var parentSpanId = GetHeader(processResult.StandardOutput, HttpHeaderNames.ParentId);

                    var firstSpan = spans.First();
                    Assert.Equal("http.request", firstSpan.Name);
                    Assert.Equal("Samples.HttpMessageHandler-http-client", firstSpan.Service);
                    Assert.Equal(SpanTypes.Http, firstSpan.Type);
                    Assert.Equal(nameof(HttpMessageHandler), firstSpan.Tags[Tags.InstrumentationName]);

                    var lastSpan = spans.Last();
                    Assert.Equal(lastSpan.TraceId.ToString(CultureInfo.InvariantCulture), traceId);
                    Assert.Equal(lastSpan.SpanId.ToString(CultureInfo.InvariantCulture), parentSpanId);
                }
        }
コード例 #4
0
        public void RenamesService(bool enableCallTarget, bool enableInlining)
        {
            SetCallTargetSettings(enableCallTarget, enableInlining);

            int          expectedSpanCount     = EnvironmentHelper.IsCoreClr() ? 36 : 32;
            const string expectedOperationName = "http.request";
            const string expectedServiceName   = "my-custom-client";

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                    Assert.Equal(expectedSpanCount, spans.Count);

                    foreach (var span in spans)
                    {
                        Assert.Equal(expectedOperationName, span.Name);
                        Assert.Equal(expectedServiceName, span.Service);
                        Assert.Equal(SpanTypes.Http, span.Type);
                        Assert.Equal("HttpMessageHandler", span.Tags[Tags.InstrumentationName]);
                        Assert.False(span.Tags?.ContainsKey(Tags.Version), "External service span should not have service version tag.");
                    }
                }
        }
コード例 #5
0
        public void TracingDisabled_DoesNotSubmitsTraces(bool enableCallTarget)
        {
            SetCallTargetSettings(enableCallTarget);

            const string expectedOperationName = "http.request";

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"TracingDisabled Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(1, 3000, operationName: expectedOperationName);
                    Assert.Equal(0, spans.Count);

                    var traceId        = StringUtil.GetHeader(processResult.StandardOutput, HttpHeaderNames.TraceId);
                    var parentSpanId   = StringUtil.GetHeader(processResult.StandardOutput, HttpHeaderNames.ParentId);
                    var tracingEnabled = StringUtil.GetHeader(processResult.StandardOutput, HttpHeaderNames.TracingEnabled);

                    Assert.Null(traceId);
                    Assert.Null(parentSpanId);
                    Assert.Equal("false", tracingEnabled);
                }
        }
コード例 #6
0
        public void RenamesService()
        {
            int expectedSpanCount = EnvironmentHelper.IsCoreClr() ? 71 : 27; // .NET Framework automatic instrumentation doesn't cover Async / TaskAsync operations

            var ignoreAsync = EnvironmentHelper.IsCoreClr() ? string.Empty : "IgnoreAsync ";

            const string expectedOperationName = "http.request";
            const string expectedServiceName   = "my-custom-client";

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"{ignoreAsync}Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                    Assert.Equal(expectedSpanCount, spans.Count);

                    foreach (var span in spans)
                    {
                        Assert.Equal(expectedOperationName, span.Name);
                        Assert.Equal(expectedServiceName, span.Service);
                        Assert.Equal(SpanTypes.Http, span.Type);
                        Assert.Matches("WebRequest|HttpMessageHandler", span.Tags[Tags.InstrumentationName]);
                        Assert.False(span.Tags?.ContainsKey(Tags.Version), "External service span should not have service version tag.");
                    }
                }
        }
コード例 #7
0
        public void WhenDisabled_DoesntSendTelemetry()
        {
            const string expectedOperationName = "http.request";
            const int    expectedSpanCount     = 1;
            const string serviceVersion        = "1.0.0";

            int agentPort = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            using var agent = new MockTracerAgent(agentPort);

            SetServiceVersion(serviceVersion);
            int telemetryPort = TcpPortProvider.GetOpenPort();

            using var telemetry = new MockTelemetryAgent <TelemetryData>(telemetryPort);

            SetEnvironmentVariable("DD_INSTRUMENTATION_TELEMETRY_ENABLED", "false");
            SetEnvironmentVariable("DD_TRACE_TELEMETRY_URL", $"http://localhost:{telemetry.Port}");
            SetEnvironmentVariable("DD_API_KEY", "INVALID_KEY_FOR_TESTS");

            int httpPort = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");
            using (ProcessResult processResult = RunSampleAndWaitForExit(agent, arguments: $"Port={httpPort}"))
            {
                Assert.True(processResult.ExitCode == 0, $"Process exited with code {processResult.ExitCode}");

                var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                Assert.Equal(expectedSpanCount, spans.Count);
            }

            // Shouldn't have any, but wait for 5s
            telemetry.WaitForLatestTelemetry(x => true);
            telemetry.Telemetry.Should().BeEmpty();
        }
コード例 #8
0
        protected async Task AssertWebServerSpan(
            string path,
            MockTracerAgent agent,
            int httpPort,
            HttpStatusCode expectedHttpStatusCode,
            bool isError,
            string expectedErrorType,
            string expectedErrorMessage,
            string expectedSpanType,
            string expectedOperationName,
            string expectedResourceName,
            string expectedServiceVersion,
            IDictionary <string, string> expectedTags = null)
        {
            IImmutableList <MockTracerAgent.Span> spans;

            using (var httpClient = new HttpClient())
            {
                // disable tracing for this HttpClient request
                httpClient.DefaultRequestHeaders.Add(HttpHeaderNames.TracingEnabled, "false");
                var testStart = DateTime.UtcNow;
                var response  = await httpClient.GetAsync($"http://localhost:{httpPort}" + path);

                var content = await response.Content.ReadAsStringAsync();

                Output.WriteLine($"[http] {response.StatusCode} {content}");
                Assert.Equal(expectedHttpStatusCode, response.StatusCode);

                spans = agent.WaitForSpans(
                    count: 1,
                    minDateTime: testStart,
                    operationName: expectedOperationName);

                Assert.True(spans.Count == 1, "expected one span");
            }

            MockTracerAgent.Span span = spans[0];

            // base properties
            Assert.Equal(expectedSpanType, span.Type);
            Assert.Equal(expectedOperationName, span.Name);
            Assert.Equal(expectedResourceName, span.Resource);

            // errors
            Assert.Equal(isError, span.Error == 1);
            Assert.Equal(expectedErrorType, span.Tags.GetValueOrDefault(Tags.ErrorType));
            Assert.Equal(expectedErrorMessage, span.Tags.GetValueOrDefault(Tags.ErrorMsg));

            // other tags
            Assert.Equal(SpanKinds.Server, span.Tags.GetValueOrDefault(Tags.SpanKind));
            Assert.Equal(expectedServiceVersion, span.Tags.GetValueOrDefault(Tags.Version));

            if (expectedTags is not null)
            {
                foreach (var expectedTag in expectedTags)
                {
                    Assert.Equal(expectedTag.Value, span.Tags.GetValueOrDefault(expectedTag.Key));
                }
            }
        }
コード例 #9
0
        public void Telemetry_IsSentOnAppClose()
        {
            const string expectedOperationName = "http.request";
            const int    expectedSpanCount     = 1;
            const string serviceVersion        = "1.0.0";

            int agentPort = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            using var agent = new MockTracerAgent(agentPort);

            SetServiceVersion(serviceVersion);
            using var telemetry = this.ConfigureTelemetry();

            int httpPort = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");
            using (ProcessResult processResult = RunSampleAndWaitForExit(agent, arguments: $"Port={httpPort}"))
            {
                Assert.True(processResult.ExitCode == 0, $"Process exited with code {processResult.ExitCode}");

                var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                Assert.Equal(expectedSpanCount, spans.Count);
            }

            var data = telemetry.AssertIntegrationEnabled(IntegrationId.HttpMessageHandler);

            data.Application.ServiceVersion.Should().Be(serviceVersion);
            data.Application.ServiceName.Should().Be("Samples.Telemetry");
        }
        public void SubmitsTraces(bool enableCallTarget)
        {
            SetCallTargetSettings(enableCallTarget);

            int          expectedSpanCount     = 25;
            const string expectedOperationName = "http.request";
            const string expectedServiceName   = "Samples.WebRequest.NetFramework20-http-client";

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                    Assert.Equal(expectedSpanCount, spans.Count);

                    foreach (var span in spans)
                    {
                        Assert.Equal(expectedOperationName, span.Name);
                        Assert.Equal(expectedServiceName, span.Service);
                        Assert.Equal(SpanTypes.Http, span.Type);
                        Assert.Equal("WebRequest", span.Tags[Tags.InstrumentationName]);
                        Assert.False(span.Tags?.ContainsKey(Tags.Version), "External service span should not have service version tag.");
                    }

                    PropagationTestHelpers.AssertPropagationEnabled(spans.First(), processResult);
                }
        }
コード例 #11
0
        public void SubmitsTraces(string packageVersion)
        {
            int agentPort = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (var processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"{TestPrefix}", packageVersion: packageVersion))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    // note: ignore the INFO command because it's timing is unpredictable (on Linux?)
                    var spans = agent.WaitForSpans(11)
                                .Where(s => s.Type == "redis" && s.Resource != "INFO")
                                .OrderBy(s => s.Start)
                                .ToList();

                    var host = Environment.GetEnvironmentVariable("SERVICESTACK_REDIS_HOST") ?? "localhost:6379";
                    var port = host.Substring(host.IndexOf(':') + 1);
                    host = host.Substring(0, host.IndexOf(':'));

                    foreach (var span in spans)
                    {
                        Assert.Equal("redis.command", span.Name);
                        Assert.Equal("Samples.ServiceStack.Redis-redis", span.Service);
                        Assert.Equal(SpanTypes.Redis, span.Type);
                        Assert.Equal(host, span.Tags.GetValueOrDefault("out.host"));
                        Assert.Equal(port, span.Tags.GetValueOrDefault("out.port"));
                    }

                    var expected = new TupleList <string, string>
                    {
                        { "ROLE", "ROLE" },
                        { "SET", $"SET {TestPrefix}ServiceStack.Redis.INCR 0" },
                        { "PING", "PING" },
                        { "DDCUSTOM", "DDCUSTOM COMMAND" },
                        { "ECHO", "ECHO Hello World" },
                        { "SLOWLOG", "SLOWLOG GET 5" },
                        { "INCR", $"INCR {TestPrefix}ServiceStack.Redis.INCR" },
                        { "INCRBYFLOAT", $"INCRBYFLOAT {TestPrefix}ServiceStack.Redis.INCR 1.25" },
                        { "TIME", "TIME" },
                        { "SELECT", "SELECT 0" },
                    };

                    for (int i = 0; i < expected.Count; i++)
                    {
                        var e1 = expected[i].Item1;
                        var e2 = expected[i].Item2;

                        var a1 = i < spans.Count
                                 ? spans[i].Resource
                                 : string.Empty;
                        var a2 = i < spans.Count
                                 ? spans[i].Tags.GetValueOrDefault("redis.raw_command")
                                 : string.Empty;

                        Assert.True(e1 == a1, $@"invalid resource name for span #{i}, expected ""{e1}"", actual ""{a1}""");
                        Assert.True(e2 == a2, $@"invalid raw command for span #{i}, expected ""{e2}"" != ""{a2}""");
                    }
                }
        }
コード例 #12
0
        public void SubmitsTraces()
        {
            int agentPort      = TcpPortProvider.GetOpenPort();
            int aspNetCorePort = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (Process process = StartSample(agent.Port, arguments: null, packageVersion: string.Empty, aspNetCorePort: aspNetCorePort))
                {
                    var wh = new EventWaitHandle(false, EventResetMode.AutoReset);

                    process.OutputDataReceived += (sender, args) =>
                    {
                        if (args.Data != null)
                        {
                            if (args.Data.Contains("Now listening on:") || args.Data.Contains("Unable to start Kestrel"))
                            {
                                wh.Set();
                            }

                            Output.WriteLine($"[webserver][stdout] {args.Data}");
                        }
                    };
                    process.BeginOutputReadLine();

                    process.ErrorDataReceived += (sender, args) =>
                    {
                        if (args.Data != null)
                        {
                            Output.WriteLine($"[webserver][stderr] {args.Data}");
                        }
                    };
                    process.BeginErrorReadLine();

                    // wait for server to start
                    wh.WaitOne(5000);

                    SubmitRequests(aspNetCorePort);
                    var graphQLValidateSpans = agent.WaitForSpans(_expectedGraphQLValidateSpanCount, operationName: _graphQLValidateOperationName, returnAllOperations: false)
                                               .GroupBy(s => s.SpanId)
                                               .Select(grp => grp.First())
                                               .OrderBy(s => s.Start);
                    var graphQLExecuteSpans = agent.WaitForSpans(_expectedGraphQLExecuteSpanCount, operationName: _graphQLExecuteOperationName, returnAllOperations: false)
                                              .GroupBy(s => s.SpanId)
                                              .Select(grp => grp.First())
                                              .OrderBy(s => s.Start);

                    if (!process.HasExited)
                    {
                        process.Kill();
                    }

                    var spans = graphQLValidateSpans.Concat(graphQLExecuteSpans).ToList();
                    SpanTestHelpers.AssertExpectationsMet(_expectations, spans);
                }
        }
コード例 #13
0
        public void SubmitsTraces(string packageVersion, bool enableCallTarget)
        {
            SetCallTargetSettings(enableCallTarget);

            int agentPort = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (var processResult = RunSampleAndWaitForExit(agent.Port, packageVersion: packageVersion))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode} and exception: {processResult.StandardError}");

                    var spans = agent.WaitForSpans(3, 500);
                    Assert.True(spans.Count >= 3, $"Expecting at least 3 spans, only received {spans.Count}");

                    var rootSpan = spans.Single(s => s.ParentId == null);

                    // Check for manual trace
                    Assert.Equal("Main()", rootSpan.Name);
                    Assert.Equal("Samples.MongoDB", rootSpan.Service);
                    Assert.Null(rootSpan.Type);

                    int spansWithResourceName = 0;

                    foreach (var span in spans)
                    {
                        if (span == rootSpan)
                        {
                            continue;
                        }

                        if (span.Service == "Samples.MongoDB-mongodb")
                        {
                            Assert.Equal("mongodb.query", span.Name);
                            Assert.Equal(SpanTypes.MongoDb, span.Type);
                            Assert.False(span.Tags?.ContainsKey(Tags.Version), "External service span should not have service version tag.");

                            if (span.Resource != null && span.Resource != "mongodb.query")
                            {
                                spansWithResourceName++;
                                Assert.True(span.Tags?.ContainsKey(Tags.MongoDbQuery), $"No query found on span {span}");
                            }
                        }
                        else
                        {
                            // These are manual traces
                            Assert.Equal("Samples.MongoDB", span.Service);
                            Assert.True("1.0.0" == span.Tags?.GetValueOrDefault(Tags.Version), span.ToString());
                        }
                    }

                    Assert.False(spansWithResourceName == 0, "Extraction of the command failed on all spans");
                }
        }
        public void MethodArgumentsInstrumentation(int numberOfArguments, bool fastPath)
        {
            SetCallTargetSettings(enableCallTarget: true);
            SetEnvironmentVariable("OTEL_INTEGRATIONS", Path.Combine(EnvironmentHelper.GetSampleProjectDirectory(), "integrations.json"));
            int agentPort = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (var processResult = RunSampleAndWaitForExit(agentPort, arguments: numberOfArguments.ToString()))
                {
                    Assert.True(processResult.ExitCode == 0, $"Process exited with code {processResult.ExitCode}");

                    string beginMethodString = $"ProfilerOK: BeginMethod\\({numberOfArguments}\\)";
                    if (!fastPath)
                    {
                        beginMethodString = $"ProfilerOK: BeginMethod\\(Array\\)";
                    }

                    int beginMethodCount = Regex.Matches(processResult.StandardOutput, beginMethodString).Count;
                    int endMethodCount   = Regex.Matches(processResult.StandardOutput, "ProfilerOK: EndMethod\\(").Count;
                    int exceptionCount   = Regex.Matches(processResult.StandardOutput, "Exception thrown.").Count;

                    string[] typeNames = new string[]
                    {
                        ".VoidMethod",
                        ".ReturnValueMethod",
                        ".ReturnReferenceMethod",
                        ".ReturnGenericMethod<string>",
                        ".ReturnGenericMethod<int>",
                        ".ReturnGenericMethod",
                    };

                    if (numberOfArguments == 0)
                    {
                        // On number of arguments = 0 the throw exception on integrations async continuation runs.
                        // So we have 1 more case with an exception being reported from the integration.
                        Assert.Equal(43, beginMethodCount);
                        Assert.Equal(43, endMethodCount);
                        Assert.Equal(11, exceptionCount);
                    }
                    else
                    {
                        Assert.Equal(42, beginMethodCount);
                        Assert.Equal(42, endMethodCount);
                        Assert.Equal(10, exceptionCount);
                    }

                    foreach (var typeName in typeNames)
                    {
                        Assert.Contains(typeName, processResult.StandardOutput);
                    }
                }
        }
コード例 #15
0
        protected async Task AssertAspNetSpanOnly(
            string path,
            MockTracerAgent agent,
            int httpPort,
            HttpStatusCode expectedHttpStatusCode,
            bool isError,
            string expectedErrorType,
            string expectedErrorMessage,
            string expectedSpanType,
            string expectedResourceName,
            string expectedServiceVersion)
        {
            IImmutableList <MockTracerAgent.Span> spans;

            using (var httpClient = new HttpClient())
            {
                // disable tracing for this HttpClient request
                httpClient.DefaultRequestHeaders.Add(HttpHeaderNames.TracingEnabled, "false");
                var testStart = DateTime.UtcNow;
                var response  = await httpClient.GetAsync($"http://localhost:{httpPort}" + path);

                var content = await response.Content.ReadAsStringAsync();

                Output.WriteLine($"[http] {response.StatusCode} {content}");
                Assert.Equal(expectedHttpStatusCode, response.StatusCode);

                spans = agent.WaitForSpans(
                    count: 1,
                    minDateTime: testStart,
                    operationName: "aspnet.request",
                    returnAllOperations: true);

                Assert.True(spans.Count == 1, $"expected two span, saw {spans.Count}");
            }

            MockTracerAgent.Span span = spans[0];

            // base properties
            Assert.Equal(expectedResourceName, span.Resource);
            Assert.Equal(expectedSpanType, span.Type);

            // errors
            Assert.Equal(isError, span.Error == 1);
            Assert.Equal(expectedErrorType, span.Tags.GetValueOrDefault(Tags.ErrorType));
            Assert.Equal(expectedErrorMessage, span.Tags.GetValueOrDefault(Tags.ErrorMsg));

            // other tags
            Assert.Equal(SpanKinds.Server, span.Tags.GetValueOrDefault(Tags.SpanKind));
            Assert.Equal(expectedServiceVersion, span.Tags.GetValueOrDefault(Tags.Version));
        }
コード例 #16
0
        public void SubmitsTraces()
        {
            var prefix = $"{BuildParameters.Configuration}.{BuildParameters.TargetFramework}.";

            using (var agent = new MockTracerAgent(AgentPort))
                using (var processResult = RunSampleAndWaitForExit(AgentPort, arguments: $"ServiceStack {prefix}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(11).Where(s => s.Type == "redis").OrderBy(s => s.Start).ToList();
                    var host  = Environment.GetEnvironmentVariable("REDIS_HOST") ?? "localhost";

                    foreach (var span in spans)
                    {
                        Assert.Equal(RedisHelper.OperationName, span.Name);
                        Assert.Equal($"Samples.RedisCore-{RedisHelper.ServiceName}", span.Service);
                        Assert.Equal(SpanTypes.Redis, span.Type);
                        Assert.Equal(host, span.Tags.Get <string>("out.host"));
                        Assert.Equal("6379", span.Tags.Get <string>("out.port"));
                    }

                    var expected = new TupleList <string, string>
                    {
                        { "INFO", "INFO" },
                        { "ROLE", "ROLE" },
                        { "SET", $"SET {prefix}ServiceStack.Redis.INCR 0" },
                        { "PING", "PING" },
                        { "DDCUSTOM", "DDCUSTOM COMMAND" },
                        { "ECHO", "ECHO Hello World" },
                        { "SLOWLOG", "SLOWLOG GET 5" },
                        { "INCR", $"INCR {prefix}ServiceStack.Redis.INCR" },
                        { "INCRBYFLOAT", $"INCRBYFLOAT {prefix}ServiceStack.Redis.INCR 1.25" },
                        { "TIME", "TIME" },
                        { "SELECT", "SELECT 0" },
                    };

                    for (int i = 0; i < expected.Count; i++)
                    {
                        var e1 = expected[i].Item1;
                        var e2 = expected[i].Item2;

                        var a1 = i < spans.Count ? spans[i].Resource : string.Empty;
                        var a2 = i < spans.Count ? spans[i].Tags.Get <string>("redis.raw_command") : string.Empty;

                        Assert.True(e1 == a1, $"invalid resource name for span {i}, {e1} != {a1}");
                        Assert.True(e2 == a2, $"invalid raw command for span {i}, {e2} != {a2}");
                    }
                }
        }
コード例 #17
0
        public void TryStartIis(TestHelper helper)
        {
            lock (this)
            {
                if (_iisExpress == null)
                {
                    var initialAgentPort = TcpPortProvider.GetOpenPort();
                    Agent = new MockTracerAgent(initialAgentPort);

                    HttpPort = TcpPortProvider.GetOpenPort();

                    _iisExpress = helper.StartIISExpress(Agent.Port, HttpPort);
                }
            }
        }
コード例 #18
0
        public void SubmitsTraces(bool enableCallTarget)
        {
            SetCallTargetSettings(enableCallTarget);

            Output.WriteLine("Starting WcfTests.SubmitsTraces. Starting the Samples.Wcf requires ADMIN privileges");

            var expectedSpanCount = 4;

            const string     expectedOperationName = "wcf.request";
            const string     expectedServiceName   = "Samples.Wcf";
            HashSet <string> expectedResourceNames = new HashSet <string>()
            {
                "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue",
                "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue",
                "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT",
                "WcfSample/ICalculator/Add"
            };

            int agentPort = TcpPortProvider.GetOpenPort();
            int wcfPort   = 8585;

            using (var agent = new MockTracerAgent(agentPort))
                using (var processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"WSHttpBinding Port={wcfPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode} and exception: {processResult.StandardError}");

                    var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                    Assert.True(spans.Count >= expectedSpanCount, $"Expecting at least {expectedSpanCount} spans, only received {spans.Count}");

                    foreach (var span in spans)
                    {
                        // Validate server fields
                        Assert.Equal(expectedServiceName, span.Service);
                        Assert.Equal(ServiceVersion, span.Tags[Tags.Version]);
                        Assert.Equal(expectedOperationName, span.Name);
                        Assert.Equal(SpanTypes.Web, span.Type);
                        Assert.Equal(SpanKinds.Server, span.Tags[Tags.SpanKind]);

                        // Validate resource name
                        Assert.Contains(span.Resource, expectedResourceNames);

                        // Test HTTP tags
                        Assert.Equal("POST", span.Tags[Tags.HttpMethod]);
                        Assert.Equal("http://localhost:8585/WcfSample/CalculatorService", span.Tags[Tags.HttpUrl]);
                        Assert.Equal($"localhost:{wcfPort}", span.Tags[Tags.HttpRequestHeadersHost]);
                    }
                }
        }
コード例 #19
0
        public void HttpClient_SubmitsTraces(bool enableCallTarget, InstrumentationOptions instrumentation, bool enableSocketsHandler)
        {
            ConfigureInstrumentation(enableCallTarget, instrumentation, enableSocketsHandler);

            var expectedAsyncCount = CalculateExpectedAsyncSpans(instrumentation, enableCallTarget);
            var expectedSyncCount  = CalculateExpectedSyncSpans(instrumentation);

            var expectedSpanCount = expectedAsyncCount + expectedSyncCount;

            const string expectedOperationName = "http.request";
            const string expectedServiceName   = "Samples.HttpMessageHandler-http-client";

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                    Assert.Equal(expectedSpanCount, spans.Count);

                    foreach (var span in spans)
                    {
                        Assert.Equal(expectedOperationName, span.Name);
                        Assert.Equal(expectedServiceName, span.Service);
                        Assert.Equal(SpanTypes.Http, span.Type);
                        Assert.Equal("HttpMessageHandler", span.Tags[Tags.InstrumentationName]);
                        Assert.False(span.Tags?.ContainsKey(Tags.Version), "External service span should not have service version tag.");

                        if (span.Tags[Tags.HttpStatusCode] == "502")
                        {
                            Assert.Equal(1, span.Error);
                        }
                    }

                    var firstSpan    = spans.First();
                    var traceId      = StringUtil.GetHeader(processResult.StandardOutput, HttpHeaderNames.TraceId);
                    var parentSpanId = StringUtil.GetHeader(processResult.StandardOutput, HttpHeaderNames.ParentId);

                    Assert.Equal(firstSpan.TraceId.ToString(CultureInfo.InvariantCulture), traceId);
                    Assert.Equal(firstSpan.SpanId.ToString(CultureInfo.InvariantCulture), parentSpanId);
                }
        }
コード例 #20
0
        public void TryStartIis(TestHelper helper)
        {
            lock (this)
            {
                if (_iisExpress == null)
                {
                    var initialAgentPort = TcpPortProvider.GetOpenPort();
                    Agent = new MockTracerAgent(initialAgentPort);

                    HttpPort = TcpPortProvider.GetOpenPort();

                    // start IIS Express and give it a few seconds to boot up
                    _iisExpress = helper.StartIISExpress(Agent.Port, HttpPort);
                    Thread.Sleep(TimeSpan.FromSeconds(3));
                }
            }
        }
コード例 #21
0
        public void DoesNotCrashInBadConfiguration(string targetFramework)
        {
            // Set bad configuration
            SetEnvironmentVariable("DD_DOTNET_TRACER_HOME", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, framework: targetFramework))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");
                }
        }
コード例 #22
0
        public void MetricsDisabled()
        {
            int agentPort = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");

            SetEnvironmentVariable("DD_RUNTIME_METRICS_ENABLED", "0");

            using var agent = new MockTracerAgent(agentPort, useStatsd: true);
            Output.WriteLine($"Assigning port {agent.StatsdPort} for the statsdPort.");

            using var processResult = RunSampleAndWaitForExit(agent.Port, agent.StatsdPort);
            var requests = agent.StatsdRequests;

            Assert.True(requests.Count == 0, "Received metrics despite being disabled. Metrics received: " + string.Join("\n", requests));
            Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");
        }
コード例 #23
0
        public void SubmitsTraces()
        {
            using (var agent = new MockTracerAgent(9002))
                using (ProcessResult processResult = RunSampleAndWaitForExit(9002))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(1);
                    Assert.True(spans.Count > 0, "expected at least one span");
                    foreach (var span in spans)
                    {
                        Assert.Equal("sql-server.query", span.Name);
                        Assert.Equal($"Samples.SqlServer-sql-server", span.Service);
                        Assert.Equal(SpanTypes.Sql, span.Type);
                    }
                }
        }
コード例 #24
0
        public void SubmitsTraces()
        {
            if (Environment.OSVersion.Platform != PlatformID.Win32Windows)
            {
                return;
            }

            using (var agent = new MockTracerAgent(AgentPort))
            {
                using (var iis = StartIISExpress(AgentPort, Port))
                {
                    try
                    {
                        var request = WebRequest.Create($"http://localhost:{Port}/");
                        using (var response = (HttpWebResponse)request.GetResponse())
                            using (var stream = response.GetResponseStream())
                                using (var reader = new StreamReader(stream))
                                {
                                    Output.WriteLine($"[http] {response.StatusCode} {reader.ReadToEnd()}");
                                }
                    }
                    catch (WebException wex)
                    {
                        Output.WriteLine($"[http] exception: {wex}");
                        if (wex.Response is HttpWebResponse response)
                        {
                            using (var stream = response.GetResponseStream())
                                using (var reader = new StreamReader(stream))
                                {
                                    Output.WriteLine($"[http] {response.StatusCode} {reader.ReadToEnd()}");
                                }
                        }
                    }
                }

                var spans = agent.WaitForSpans(1);
                Assert.True(spans.Count > 0, "expected at least one span");
                foreach (var span in spans)
                {
                    Assert.Equal("aspnet-mvc.request", span.Name);
                    Assert.Equal(SpanTypes.Web, span.Type);
                    Assert.Equal("GET home.index", span.Resource);
                }
            }
        }
コード例 #25
0
        public void SubmitsTraces()
        {
            int agentPort = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(1);
                    Assert.True(spans.Count > 0, "expected at least one span");
                    foreach (var span in spans)
                    {
                        Assert.Equal("postgres.query", span.Name);
                        Assert.Equal("Samples.Npgsql-postgres", span.Service);
                        Assert.Equal(SpanTypes.Sql, span.Type);
                    }
                }
        }
コード例 #26
0
        public void SubmitsTraces()
        {
            using (var agent = new MockTracerAgent())
            {
                using (var process = StartSample("SqlServer"))
                {
                    process.WaitForExit();
                }

                var spans = agent.GetSpans();
                Assert.True(spans.Count > 1);
                foreach (var span in spans)
                {
                    Assert.Equal("sqlserver.query", span.Name);
                    Assert.Equal("Samples.SqlServer", span.Service);
                    Assert.Equal("sql", span.Type);
                }
            }
        }
コード例 #27
0
        public void DoesNotCrashInBadConfiguration()
        {
            // Set bad configuration
            SetEnvironmentVariable("DD_DOTNET_TRACER_HOME", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

            Assert.False(typeof(Instrumentation).Assembly.GlobalAssemblyCache, "Datadog.Trace.ClrProfiler.Managed was loaded from the GAC. Ensure that the assembly and its dependencies are not installed in the GAC when running this test.");

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"HttpClient Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");
                }
        }
コード例 #28
0
        public void SubmitsTraces(bool enableCallTarget)
        {
            SetCallTargetSettings(enableCallTarget);

            int expectedSpanCount = EnvironmentHelper.IsCoreClr() ? 71 : 27; // .NET Framework automatic instrumentation doesn't cover Async / TaskAsync operations

            var ignoreAsync = EnvironmentHelper.IsCoreClr() ? string.Empty : "IgnoreAsync ";

            const string expectedOperationName = "http.request";
            const string expectedServiceName   = "Samples.WebRequest-http-client";

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            Output.WriteLine($"Assigning port {agentPort} for the agentPort.");
            Output.WriteLine($"Assigning port {httpPort} for the httpPort.");

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"{ignoreAsync}Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(expectedSpanCount, operationName: expectedOperationName);
                    Assert.Equal(expectedSpanCount, spans.Count);

                    foreach (var span in spans)
                    {
                        Assert.Equal(expectedOperationName, span.Name);
                        Assert.Equal(expectedServiceName, span.Service);
                        Assert.Equal(SpanTypes.Http, span.Type);
                        Assert.True(string.Equals(span.Tags[Tags.InstrumentationName], "WebRequest") || string.Equals(span.Tags[Tags.InstrumentationName], "HttpMessageHandler"));
                        Assert.False(span.Tags?.ContainsKey(Tags.Version), "External service span should not have service version tag.");
                    }

                    var firstSpan    = spans.First();
                    var traceId      = StringUtil.GetHeader(processResult.StandardOutput, HttpHeaderNames.TraceId);
                    var parentSpanId = StringUtil.GetHeader(processResult.StandardOutput, HttpHeaderNames.ParentId);

                    Assert.Equal(firstSpan.TraceId.ToString(CultureInfo.InvariantCulture), traceId);
                    Assert.Equal(firstSpan.SpanId.ToString(CultureInfo.InvariantCulture), parentSpanId);
                }
        }
コード例 #29
0
        public void TracingDisabled_DoesNotSubmitsTraces(bool enableCallTarget, InstrumentationOptions instrumentation, bool enableSocketsHandler)
        {
            ConfigureInstrumentation(enableCallTarget, instrumentation, enableSocketsHandler);

            const string expectedOperationName = "http.request";

            int agentPort = TcpPortProvider.GetOpenPort();
            int httpPort  = TcpPortProvider.GetOpenPort();

            using (var agent = new MockTracerAgent(agentPort))
                using (ProcessResult processResult = RunSampleAndWaitForExit(agent.Port, arguments: $"TracingDisabled Port={httpPort}"))
                {
                    Assert.True(processResult.ExitCode >= 0, $"Process exited with code {processResult.ExitCode}");

                    var spans = agent.WaitForSpans(1, 2000, operationName: expectedOperationName);
                    Assert.Equal(0, spans.Count);

                    PropagationTestHelpers.AssertPropagationDisabled(processResult);
                }
        }
コード例 #30
0
        public void SubmitsTraces()
        {
            using (var agent = new MockTracerAgent(AgentPort))
            {
                using (var iis = StartIISExpress(AgentPort, Port))
                {
                    try
                    {
                        var request = WebRequest.Create($"http://localhost:{Port}/api/environment");
                        using (var response = (HttpWebResponse)request.GetResponse())
                            using (var stream = response.GetResponseStream())
                                using (var reader = new StreamReader(stream))
                                {
                                    Output.WriteLine($"[http] {response.StatusCode} {reader.ReadToEnd()}");
                                }
                    }
                    catch (WebException wex)
                    {
                        Output.WriteLine($"[http] exception: {wex}");
                        if (wex.Response is HttpWebResponse response)
                        {
                            using (var stream = response.GetResponseStream())
                                using (var reader = new StreamReader(stream))
                                {
                                    Output.WriteLine($"[http] {response.StatusCode} {reader.ReadToEnd()}");
                                }
                        }
                    }
                }

                var spans = agent.GetSpans();

                Assert.True(spans.Count > 0, "expected at least one span");
                foreach (var span in spans)
                {
                    Assert.Equal("aspnet_web.query", span.Name);
                    Assert.Equal("web", span.Type);
                    Assert.Equal("GET api/environment", span.Resource);
                }
            }
        }