Skip to content

[Tracer] Rework exporter settings#2686

Closed
pierotibou wants to merge 6 commits into
masterfrom
pierre/rework-exporter-settings
Closed

[Tracer] Rework exporter settings#2686
pierotibou wants to merge 6 commits into
masterfrom
pierre/rework-exporter-settings

Conversation

@pierotibou

@pierotibou pierotibou commented Apr 14, 2022

Copy link
Copy Markdown
Contributor

Summary of changes

First, this is a subset of #2455. I did another one as I thought it would be easier to follow up the changes. Also note that I'm trying to make the review easier if you do it commit by commit.
Then, here are the changes so far:

  • Add more tests
  • Change the order of precedence of the settings to put the URL back on top
  • Added a few validation checks (eg the URI is well formed), allowed fallbacking and added validation warnings
  • Changing a property recomputes the strategy. This one is a bit tricky as we keep the precedence. So if a URL had been set by config, and the user changes the socket path, then it won't change anything.

Reason for change

The main reason is that we introduced a bug by breaking the order of precedence of the parameters. BTW, this order is now documented here. But this implementation has many flaws:

  • Setting a unix:// URI after a http uri would just break as we're not changing the transport strategy
  • Setting TracesUnixDomainSocketPath, MetricsUnixDomainSocketPath, MetricsPipeName, TracesPipeName properties is useless if you hadn't given an equivalent configuration through environment. Indeed, we don't recompute the strategy when we set those.

Implementation details

In this PR, I'm not changing the way it works. Thus, all the computation stilll happen in ExporterSettings. Doing so to avoid breaking changes in behavior.

Minor detail, I've pushed commit 5332cf0 in order to prevent an issue in partial trust environment. As we don't support it, I think I can revert it, but we'd need to drop the Sandbox tests in that case. FYI, here the issue was Cannot change initonly field outside its .ctor. I've verified with PEVerify that the issue has been solved (though the code is even uglier, so I'd be happy to revert)

Test coverage

I've done TDD. So I've added tests that match the target behavior. Added them in the first commit marking the ones that fail. And commit by commit I remove the comments.

Other details

Fixes #2426

Next steps

  • Shall we set TracesUnixDomainSocketPath if a path has been provided by URL?
  • Switch to a builder template in 3.0

@andrewlock

This comment has been minimized.

@pierotibou
pierotibou force-pushed the pierre/rework-exporter-settings branch 2 times, most recently from a9fc4c6 to a55547d Compare April 15, 2022 11:04
@andrewlock

This comment has been minimized.

@andrewlock

This comment has been minimized.

Add the URL as the first parameter to consider
Check Uri before creation and allow fallbacks
Adds validation warnings
Changing the Uri through the property now recomputes the strategy

Change the tests as well to order them by order of precedence
But didn't add as much tests as in my previous PR (yet)
@pierotibou
pierotibou force-pushed the pierre/rework-exporter-settings branch from 7e2cf43 to a0a1063 Compare April 15, 2022 21:31
@pierotibou
pierotibou force-pushed the pierre/rework-exporter-settings branch from a0a1063 to b7f3ae5 Compare April 15, 2022 22:52
@pierotibou
pierotibou marked this pull request as ready for review April 15, 2022 22:58
@pierotibou
pierotibou requested a review from a team as a code owner April 15, 2022 22:58
@pierotibou pierotibou added type:bug area:tracer The core tracer library (Datadog.Trace, does not include OpenTracing, native code, or integrations) type:refactor labels Apr 15, 2022
@andrewlock

This comment has been minimized.

@pierotibou
pierotibou force-pushed the pierre/rework-exporter-settings branch from b7f3ae5 to 5332cf0 Compare April 18, 2022 21:32
@andrewlock

Copy link
Copy Markdown
Member

Code Coverage Report 📊

✔️ Merging #2686 into master will not change line coverage
✔️ Merging #2686 into master will not change branch coverage
⛔ Merging #2686 into master will will increase complexity by 56

master #2686 Change
Lines 13609 / 18627 13571 / 18690
Lines % 73% 73% 0% ✔️
Branches 7873 / 11125 7860 / 11167
Branches % 71% 70% 0% ✔️
Complexity 12431 12487 56

View the full report for further details:

Datadog.Trace Breakdown ✔️

master #2686 Change
Lines % 73% 73% 0% ✔️
Branches % 71% 70% 0% ✔️
Complexity 12431 12487 56

The following classes have significant coverage changes.

File Line coverage change Branch coverage change Complexity change
Datadog.Trace.Telemetry.JsonWebRequestTelemetryTransport -27% -57% 0 ✔️
Datadog.Trace.Ci.GitInfo -17% -11% 0 ✔️
Datadog.Trace.Configuration.ExporterSettings -4% ⚠️ -6% 43
Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaCommon -1% ⚠️ 15% ✔️ 11
Datadog.Trace.Ci.CIVisibility 7% ✔️ 7% ✔️ 0 ✔️

View the full reports for further details:

@andrewlock

Copy link
Copy Markdown
Member

Benchmarks Report 🐌

Benchmarks for #2686 compared to master:

  • 9 benchmarks are faster, with geometric mean 1.180
  • All benchmarks have the same allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.AgentWriterBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #2686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.AgentWriterBenchmark.WriteAndFlushEnrichedTraces‑net472 1.286 1,180,268.56 917,805.89

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net472 1.18ms 6.29μs 35.6μs 0 0 0 3.16 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 818μs 4.72μs 38μs 0 0 0 2.57 KB
#2686 WriteAndFlushEnrichedTraces net472 922μs 4.86μs 23.3μs 0 0 0 3.16 KB
#2686 WriteAndFlushEnrichedTraces netcoreapp3.1 741μs 4.02μs 25.7μs 0 0 0 2.57 KB
Benchmarks.Trace.AppSecBodyBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #2686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.AppSecBodyBenchmark.BodyExtractorSimpleBody‑net472 1.135 482.25 424.79
Benchmarks.Trace.AppSecBodyBenchmark.AllCycleMoreComplexBody‑net472 1.119 325.03 290.52

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master AllCycleSimpleBody net472 332ns 1.52ns 5.9ns 0.0519 0 0 329 B
master AllCycleSimpleBody netcoreapp3.1 400ns 2.08ns 9.75ns 0.00454 0 0 328 B
master AllCycleMoreComplexBody net472 327ns 1.31ns 5.06ns 0.0482 0 0 305 B
master AllCycleMoreComplexBody netcoreapp3.1 394ns 1.93ns 8.64ns 0.00432 0 0 304 B
master BodyExtractorSimpleBody net472 482ns 1.97ns 7.36ns 0.0568 0 0 361 B
master BodyExtractorSimpleBody netcoreapp3.1 464ns 2.17ns 8.13ns 0.00372 0 0 272 B
master BodyExtractorMoreComplexBody net472 27μs 146ns 840ns 1.18 0.0131 0 7.62 KB
master BodyExtractorMoreComplexBody netcoreapp3.1 23.1μs 130ns 842ns 0.0895 0 0 6.75 KB
#2686 AllCycleSimpleBody net472 305ns 1.68ns 10.2ns 0.052 0 0 329 B
#2686 AllCycleSimpleBody netcoreapp3.1 383ns 2.01ns 10.1ns 0.00457 0 0 328 B
#2686 AllCycleMoreComplexBody net472 291ns 1.38ns 5.34ns 0.0482 0 0 305 B
#2686 AllCycleMoreComplexBody netcoreapp3.1 374ns 1.81ns 7ns 0.00424 0 0 304 B
#2686 BodyExtractorSimpleBody net472 430ns 2.28ns 14.8ns 0.057 0 0 361 B
#2686 BodyExtractorSimpleBody netcoreapp3.1 446ns 2.32ns 11.1ns 0.00378 0 0 272 B
#2686 BodyExtractorMoreComplexBody net472 23.9μs 95.1ns 392ns 1.18 0.0119 0 7.62 KB
#2686 BodyExtractorMoreComplexBody netcoreapp3.1 20.9μs 107ns 477ns 0.0928 0 0 6.75 KB
Benchmarks.Trace.AspNetCoreBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #2686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.AspNetCoreBenchmark.SendRequest‑netcoreapp3.1 1.134 342,424.35 302,044.84

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendRequest net472 0ns 0ns 0ns 0 0 0 0 b
master SendRequest netcoreapp3.1 343μs 1.62μs 7.08μs 0.179 0 0 19.74 KB
#2686 SendRequest net472 0ns 0ns 0ns 0 0 0 0 b
#2686 SendRequest netcoreapp3.1 300μs 1.62μs 9.32μs 0.147 0 0 19.74 KB
Benchmarks.Trace.DbCommandBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #2686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.DbCommandBenchmark.ExecuteNonQuery‑net472 1.169 2,026.12 1,733.17

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteNonQuery net472 2.02μs 11.4ns 70.9ns 0.0943 0 0 594 B
master ExecuteNonQuery netcoreapp3.1 1.69μs 8.97ns 44.8ns 0.00883 0 0 632 B
#2686 ExecuteNonQuery net472 1.74μs 10.1ns 78.7ns 0.0938 0 0 594 B
#2686 ExecuteNonQuery netcoreapp3.1 1.51μs 8.12ns 41.4ns 0.00889 0 0 632 B
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master CallElasticsearch net472 2.82μs 13.5ns 52.2ns 0.126 0 0 803 B
master CallElasticsearch netcoreapp3.1 1.87μs 8.79ns 35.2ns 0.0106 0 0 792 B
master CallElasticsearchAsync net472 3.5μs 20.2ns 169ns 0.146 0 0 939 B
master CallElasticsearchAsync netcoreapp3.1 1.96μs 7.14ns 25.8ns 0.0126 0 0 912 B
#2686 CallElasticsearch net472 2.72μs 13.9ns 68ns 0.127 0 0 803 B
#2686 CallElasticsearch netcoreapp3.1 1.68μs 7.88ns 30.5ns 0.0112 0 0 792 B
#2686 CallElasticsearchAsync net472 3.1μs 13.8ns 66.4ns 0.149 0.00155 0 939 B
#2686 CallElasticsearchAsync netcoreapp3.1 1.92μs 8.71ns 34.8ns 0.0124 0 0 912 B
Benchmarks.Trace.GraphQLBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #2686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync‑net472 1.131 3,618.94 3,200.85

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteAsync net472 3.66μs 17.1ns 130ns 0.165 0 0 1.06 KB
master ExecuteAsync netcoreapp3.1 2.21μs 12.8ns 102ns 0.0147 0 0 1.03 KB
#2686 ExecuteAsync net472 3.21μs 15.7ns 64.9ns 0.168 0.00158 0 1.06 KB
#2686 ExecuteAsync netcoreapp3.1 2.01μs 7.42ns 27.8ns 0.0147 0 0 1.03 KB
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendAsync net472 7.57μs 42.8ns 280ns 0.356 0 0 2.28 KB
master SendAsync netcoreapp3.1 4.97μs 17.3ns 64.6ns 0.0314 0 0 2.21 KB
#2686 SendAsync net472 6.96μs 37.2ns 197ns 0.36 0 0 2.28 KB
#2686 SendAsync netcoreapp3.1 4.8μs 19.5ns 75.4ns 0.0309 0 0 2.21 KB
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net472 3.74μs 20.2ns 121ns 0.228 0 0 1.45 KB
master EnrichedLog netcoreapp3.1 3.29μs 17.3ns 91.5ns 0.0223 0 0 1.53 KB
#2686 EnrichedLog net472 3.35μs 15.8ns 61.4ns 0.228 0 0 1.45 KB
#2686 EnrichedLog netcoreapp3.1 3.19μs 17.5ns 132ns 0.0207 0 0 1.53 KB
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net472 301μs 1.62μs 8.57μs 0.437 0.146 0 4.33 KB
master EnrichedLog netcoreapp3.1 238μs 1.16μs 4.76μs 0 0 0 4.21 KB
#2686 EnrichedLog net472 284μs 940ns 3.64μs 0.423 0.141 0 4.33 KB
#2686 EnrichedLog netcoreapp3.1 227μs 463ns 1.6μs 0 0 0 4.21 KB
Benchmarks.Trace.NLogBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #2686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.NLogBenchmark.EnrichedLog‑net472 1.221 9,041.15 7,405.58 several?

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net472 9.04μs 47.5ns 251ns 0.506 0 0 3.23 KB
master EnrichedLog netcoreapp3.1 7.06μs 37.2ns 193ns 0.0517 0 0 3.6 KB
#2686 EnrichedLog net472 7.41μs 36.6ns 155ns 0.504 0 0 3.23 KB
#2686 EnrichedLog netcoreapp3.1 7.15μs 29.6ns 111ns 0.0498 0 0 3.6 KB
Benchmarks.Trace.RedisBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #2686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.RedisBenchmark.SendReceive‑net472 1.202 2,881.07 2,396.76 several?

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendReceive net472 2.88μs 16.9ns 165ns 0.158 0 0 1.01 KB
master SendReceive netcoreapp3.1 2.05μs 9.83ns 38.1ns 0.0142 0 0 1.01 KB
#2686 SendReceive net472 2.41μs 12.7ns 63.5ns 0.16 0 0 1.01 KB
#2686 SendReceive netcoreapp3.1 2.02μs 6.02ns 21.7ns 0.0142 0 0 1.01 KB
Benchmarks.Trace.SerilogBenchmark - Faster 🎉 Same allocations ✔️

Faster 🎉 in #2686

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.SerilogBenchmark.EnrichedLog‑net472 1.237 7,275.28 5,882.86

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net472 7.29μs 36.1ns 153ns 0.292 0 0 1.87 KB
master EnrichedLog netcoreapp3.1 5.84μs 28.6ns 125ns 0.0187 0 0 1.49 KB
#2686 EnrichedLog net472 5.96μs 32.4ns 174ns 0.291 0 0 1.87 KB
#2686 EnrichedLog netcoreapp3.1 5.18μs 14.1ns 51ns 0.0209 0 0 1.49 KB
Benchmarks.Trace.SpanBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net472 1.01μs 3.63ns 14ns 0.0716 0 0 457 B
master StartFinishSpan netcoreapp3.1 947ns 5.08ns 25.9ns 0.00644 0 0 456 B
master StartFinishScope net472 1.15μs 5.87ns 27.5ns 0.0842 0 0 538 B
master StartFinishScope netcoreapp3.1 1.16μs 5.11ns 19.8ns 0.00782 0 0 576 B
#2686 StartFinishSpan net472 961ns 4.97ns 23.3ns 0.0719 0 0 457 B
#2686 StartFinishSpan netcoreapp3.1 876ns 4.18ns 16.7ns 0.00622 0 0 456 B
#2686 StartFinishScope net472 1.08μs 3.41ns 12.8ns 0.0843 0 0 538 B
#2686 StartFinishScope netcoreapp3.1 1.05μs 6.06ns 50.7ns 0.00797 0 0 576 B
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunOnMethodBegin net472 1.37μs 5.12ns 17.7ns 0.0839 0 0 538 B
master RunOnMethodBegin netcoreapp3.1 1.22μs 6.28ns 39.7ns 0.00791 0 0 576 B
#2686 RunOnMethodBegin net472 1.36μs 6.64ns 27.4ns 0.0841 0 0 538 B
#2686 RunOnMethodBegin netcoreapp3.1 1.22μs 6.21ns 30.4ns 0.00835 0 0 576 B

@andrewlock andrewlock left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I regret suggesting this as the way to go

[Fact] // Fails for now because of the 20 000
public void TracesPipeName()
{
var param = "/var/path";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you may want to use a Windows file path here for testing, as that's what's used in practice AFAIK e.g. @"C:\temp\someval"

public void MetricsUnixDomainSocketPath()
{
var param = "/var/path";
var settings = new ExporterSettings() { MetricsUnixDomainSocketPath = param };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT we don't have a test here for the "non-metrics" UDS? we have http +

  • named pipes
  • named pipes metrics
  • UDS metrics

EDIT: oh wait, lower down?

Comment on lines +277 to +279
Assert.Equal(expected: TracesTransportType.Default, actual: settings.TracesTransport);
Assert.Equal(expected: expectedUri, actual: settings.AgentUri);
Assert.False(string.Equals(settings.AgentUri.Host, "localhost", StringComparison.OrdinalIgnoreCase));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we generally prefer the Should() style this days. No need to change them, just for the future!

Assert.Equal(expected: TracesTransportType.UnixDomainSocket, actual: settings.TracesTransport);
Assert.Equal(expected: socketPath, actual: settings.TracesUnixDomainSocketPath);
Assert.NotNull(settings.AgentUri);
Assert.False(string.Equals(settings.AgentUri.Host, "localhost", StringComparison.OrdinalIgnoreCase));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be explicitly checking the URI here is either socketPath or $"unix//{socketPath}". Same for the named pipe

// Check the parameters in order of precedence
// For some cases, we allow falling back on another configuration (eg invalid url as the application will need to be restarted to fix it anyway).
// For other cases (eg a configured unix domain socket path not found), we don't fallback as the problem could be fixed outside the application.
if (agentUri is not null)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe string.IsNullOrWhiteSpace(agentUri)?

DogStatsdPort = dogStatsdPort ?? DefaultDogstatsdPort;
metricsTransport = MetricsTransportType.UDP;
SetUdsAsTraceTransport(DefaultTracesUnixDomainSocket);
SetAgentUri(DefaultAgentHost, DefaultAgentPort);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this isn't right is it?🤔 We should set the Agent URI to DefaultTracesUnixDomainSocket?

TracesPipeName = source?.GetString(ConfigurationKeys.TracesPipeName);
private bool TrySetAgentUriAndTransport(string url)
{
if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out var uri))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If url starts with unix://, will this fail? 🤔?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, I've even added a UTest to make sure it works

Comment on lines +324 to +326
// Still build the Uri no matter what the transport as we send it in the http message
// TBH, I don't know if we should handle the case where we use agentHost or agentPort.
// Can user have configured both agenthost, agentport, and a UDS path (or an url or a pipe)?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have set UDS path, I think AgentUri should also be the UDS path. In #2688 we don't necessarily use the AgentUri directly in the request, so that's not a concern.

Comment on lines +10 to +13
public UnixDomainSocketConfig(string traces)
{
Traces = traces;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public UnixDomainSocketConfig(string traces)
{
Traces = traces;
}
public UnixDomainSocketConfig(string traces)
: base(traces, metrics: null)

Comment on lines +16 to +19
/// This class has many flaws that we shall change the pattern in our next major version. That said, as of now, here's how it works:
/// You can set configuration at construction or through properties.
/// There's an order of precedence between the configuration knobs (Uri is considered first for instance)
/// If you try to override through code a configuration, the order of precedence still prevails. Then, if you had set an Uri at construction, setting anything else through code will not have any effect.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should include this extra. It's brutally honest, but not what I expect in docs 😂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:tracer The core tracer library (Datadog.Trace, does not include OpenTracing, native code, or integrations) type:bug type:refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configuration parsing issue with UDS (DD_AGENT_HOST+DD_TRACE_AGENT_URL)

2 participants