Skip to content
This repository was archived by the owner on Apr 28, 2022. It is now read-only.

Commit b17b37a

Browse files
authored
Replace JAEGER_SAMPLER_MANAGER_HOST_PORT with JAEGER_SAMPLING_ENDPOINT (#165)
* Replace JAEGER_SAMPLER_MANAGER_HOST_PORT with JAEGER_SAMPLING_ENDPOINT * Readded support for deprecated JAEGER_SAMPLER_MANAGER_HOST_PORT * Adjusted tests for real-world sampler results
1 parent 23c6cfd commit b17b37a

8 files changed

+118
-48
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ JAEGER_REPORTER_LOG_SPANS | no | Whether the reporter should also log the spans
7979
JAEGER_REPORTER_MAX_QUEUE_SIZE | no | The reporter's maximum queue size
8080
JAEGER_REPORTER_FLUSH_INTERVAL | no | The reporter's flush interval (ms)
8181
JAEGER_SAMPLER_TYPE | no | The sampler type
82-
JAEGER_SAMPLER_PARAM | no | The sampler parameter (number)
83-
JAEGER_SAMPLER_MANAGER_HOST_PORT | no | The host name and port when using the remote controlled sampler
82+
JAEGER_SAMPLER_PARAM | no | The sampler parameter (double)
83+
JAEGER_SAMPLER_MANAGER_HOST_PORT | no | (DEPRECATED) The host name and port when using the remote controlled sampler
84+
JAEGER_SAMPLING_ENDPOINT | no | The url for the remote sampling conf when using sampler type remote. Default is http://127.0.0.1:5778/sampling
8485
JAEGER_TAGS | no | A comma separated list of `name = value` tracer level tags, which get added to all reported spans. The value can also refer to an environment variable using the format `${envVarName:default}`, where the `:default` is optional, and identifies a value to be used if the environment variable cannot be found
8586
JAEGER_TRACEID_128BIT | no | Whether to use 128bit TraceID instead of 64bit
8687

src/Jaeger/Configuration.cs

+51-21
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ public class Configuration
8787
/// </summary>
8888
public const string JaegerSamplerManagerHostPort = JaegerPrefix + "SAMPLER_MANAGER_HOST_PORT";
8989

90+
/// <summary>
91+
/// The url for the remote sampling conf when using sampler type remote.
92+
/// </summary>
93+
public const string JaegerSamplingEndpoint = JaegerPrefix + "SAMPLING_ENDPOINT";
94+
9095
/// <summary>
9196
/// The service name.
9297
/// </summary>
@@ -161,7 +166,7 @@ public static Configuration FromIConfiguration(ILoggerFactory loggerFactory, ICo
161166
{
162167
ILogger logger = loggerFactory.CreateLogger<Configuration>();
163168

164-
return new Configuration(GetProperty(JaegerServiceName, configuration), loggerFactory)
169+
return new Configuration(GetProperty(JaegerServiceName, logger, configuration), loggerFactory)
165170
.WithTracerTags(TracerTagsFromIConfiguration(logger, configuration))
166171
.WithTraceId128Bit(GetPropertyAsBool(JaegerTraceId128Bit, logger, configuration).GetValueOrDefault(false))
167172
.WithReporter(ReporterConfiguration.FromIConfiguration(loggerFactory, configuration))
@@ -312,10 +317,16 @@ public class SamplerConfiguration
312317

313318
/// <summary>
314319
/// HTTP host:port of the sampling manager that can provide sampling strategy to this service.
315-
/// Optional.
316320
/// </summary>
321+
[Obsolete("Please use SamplingEndpoint instead!")]
317322
public string ManagerHostPort { get; private set; }
318323

324+
/// <summary>
325+
/// The URL of the sampling manager that can provide sampling strategy to this service.
326+
/// Optional.
327+
/// </summary>
328+
public string SamplingEndpoint { get; private set; }
329+
319330
public SamplerConfiguration(ILoggerFactory loggerFactory)
320331
{
321332
_loggerFactory = loggerFactory;
@@ -327,11 +338,14 @@ public SamplerConfiguration(ILoggerFactory loggerFactory)
327338
public static SamplerConfiguration FromIConfiguration(ILoggerFactory loggerFactory, IConfiguration configuration)
328339
{
329340
ILogger logger = loggerFactory.CreateLogger<Configuration>();
330-
341+
342+
#pragma warning disable CS0618 // Supress warning on obsolete method: WithManagerHostPort
331343
return new SamplerConfiguration(loggerFactory)
332-
.WithType(GetProperty(JaegerSamplerType, configuration))
344+
.WithType(GetProperty(JaegerSamplerType, logger, configuration))
333345
.WithParam(GetPropertyAsDouble(JaegerSamplerParam, logger, configuration))
334-
.WithManagerHostPort(GetProperty(JaegerSamplerManagerHostPort, configuration));
346+
.WithManagerHostPort(GetProperty(JaegerSamplerManagerHostPort, logger, configuration, JaegerSamplingEndpoint))
347+
.WithSamplingEndpoint(GetProperty(JaegerSamplingEndpoint, logger, configuration));
348+
#pragma warning restore CS0618 // Supress warning on obsolete method: WithManagerHostPort
335349
}
336350

337351
/// <summary>
@@ -347,9 +361,12 @@ public static SamplerConfiguration FromEnv(ILoggerFactory loggerFactory)
347361

348362
public virtual ISampler GetSampler(string serviceName, IMetrics metrics)
349363
{
364+
#pragma warning disable CS0618 // Supress warning on obsolete property: ManagerHostPort
350365
string samplerType = StringOrDefault(Type, RemoteControlledSampler.Type);
351366
double samplerParam = Param.GetValueOrDefault(ProbabilisticSampler.DefaultSamplingProbability);
352367
string hostPort = StringOrDefault(ManagerHostPort, HttpSamplingManager.DefaultHostPort);
368+
string samplingEndpoint = StringOrDefault(SamplingEndpoint, "http://" + hostPort);
369+
#pragma warning disable CS0618 // Supress warning on obsolete property: ManagerHostPort
353370

354371
switch (samplerType)
355372
{
@@ -362,7 +379,7 @@ public virtual ISampler GetSampler(string serviceName, IMetrics metrics)
362379
case RemoteControlledSampler.Type:
363380
return new RemoteControlledSampler.Builder(serviceName)
364381
.WithLoggerFactory(_loggerFactory)
365-
.WithSamplingManager(new HttpSamplingManager(hostPort))
382+
.WithSamplingManager(new HttpSamplingManager(samplingEndpoint))
366383
.WithInitialSampler(new ProbabilisticSampler(samplerParam))
367384
.WithMetrics(metrics)
368385
.Build();
@@ -383,11 +400,18 @@ public SamplerConfiguration WithParam(double? param)
383400
return this;
384401
}
385402

403+
[Obsolete("Use WithSamplingEndpoint instead!")]
386404
public SamplerConfiguration WithManagerHostPort(string managerHostPort)
387405
{
388406
ManagerHostPort = managerHostPort;
389407
return this;
390408
}
409+
410+
public SamplerConfiguration WithSamplingEndpoint(string samplingEndpoint)
411+
{
412+
SamplingEndpoint = samplingEndpoint;
413+
return this;
414+
}
391415
}
392416

393417
/// <summary>
@@ -412,7 +436,7 @@ public static CodecConfiguration FromIConfiguration(ILoggerFactory loggerFactory
412436
ILogger logger = loggerFactory.CreateLogger<Configuration>();
413437

414438
CodecConfiguration codecConfiguration = new CodecConfiguration(loggerFactory);
415-
string propagation = GetProperty(JaegerPropagation, configuration);
439+
string propagation = GetProperty(JaegerPropagation, logger, configuration);
416440
if (propagation != null)
417441
{
418442
foreach (string format in propagation.Split(','))
@@ -706,13 +730,13 @@ public static SenderConfiguration FromIConfiguration(ILoggerFactory loggerFactor
706730
{
707731
ILogger logger = loggerFactory.CreateLogger<Configuration>();
708732

709-
string agentHost = GetProperty(JaegerAgentHost, configuration);
733+
string agentHost = GetProperty(JaegerAgentHost, logger, configuration);
710734
int? agentPort = GetPropertyAsInt(JaegerAgentPort, logger, configuration);
711735

712-
string collectorEndpoint = GetProperty(JaegerEndpoint, configuration);
713-
string authToken = GetProperty(JaegerAuthToken, configuration);
714-
string authUsername = GetProperty(JaegerUser, configuration);
715-
string authPassword = GetProperty(JaegerPassword, configuration);
736+
string collectorEndpoint = GetProperty(JaegerEndpoint, logger, configuration);
737+
string authToken = GetProperty(JaegerAuthToken, logger, configuration);
738+
string authUsername = GetProperty(JaegerUser, logger, configuration);
739+
string authPassword = GetProperty(JaegerPassword, logger, configuration);
716740

717741
return new SenderConfiguration(loggerFactory)
718742
.WithAgentHost(agentHost)
@@ -740,14 +764,20 @@ private static string StringOrDefault(string value, string defaultValue)
740764
return value != null && value.Length > 0 ? value : defaultValue;
741765
}
742766

743-
private static string GetProperty(string name, IConfiguration configuration)
767+
private static string GetProperty(string name, ILogger logger, IConfiguration configuration, string replacedBy = null)
744768
{
745-
return configuration[name];
769+
var value = configuration[name];
770+
if (replacedBy != null && value != null)
771+
{
772+
logger.LogWarning($"The entry {name} is obsolete. Use {replacedBy} instead!");
773+
}
774+
775+
return value;
746776
}
747777

748778
private static int? GetPropertyAsInt(string name, ILogger logger, IConfiguration configuration)
749779
{
750-
string value = GetProperty(name, configuration);
780+
string value = GetProperty(name, logger, configuration);
751781
if (!string.IsNullOrEmpty(value))
752782
{
753783
if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int intValue))
@@ -764,7 +794,7 @@ private static string GetProperty(string name, IConfiguration configuration)
764794

765795
private static double? GetPropertyAsDouble(string name, ILogger logger, IConfiguration configuration)
766796
{
767-
string value = GetProperty(name, configuration);
797+
string value = GetProperty(name, logger, configuration);
768798
if (!string.IsNullOrEmpty(value))
769799
{
770800
if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out double doubleValue))
@@ -795,7 +825,7 @@ private static string GetProperty(string name, IConfiguration configuration)
795825
/// </summary>
796826
private static bool? GetPropertyAsBool(string name, ILogger logger, IConfiguration configuration)
797827
{
798-
string value = GetProperty(name, configuration);
828+
string value = GetProperty(name, logger, configuration);
799829
if (!string.IsNullOrEmpty(value))
800830
{
801831
if (string.Equals(value, "1", StringComparison.Ordinal))
@@ -822,7 +852,7 @@ private static string GetProperty(string name, IConfiguration configuration)
822852
private static Dictionary<string, string> TracerTagsFromIConfiguration(ILogger logger, IConfiguration configuration)
823853
{
824854
Dictionary<string, string> tracerTagMaps = null;
825-
string tracerTags = GetProperty(JaegerTags, configuration);
855+
string tracerTags = GetProperty(JaegerTags, logger, configuration);
826856
if (!string.IsNullOrEmpty(tracerTags))
827857
{
828858
string[] tags = tracerTags.Split(',');
@@ -835,7 +865,7 @@ private static Dictionary<string, string> TracerTagsFromIConfiguration(ILogger l
835865
{
836866
tracerTagMaps = new Dictionary<string, string>();
837867
}
838-
tracerTagMaps[tagValue[0].Trim()] = ResolveValue(tagValue[1].Trim(), configuration);
868+
tracerTagMaps[tagValue[0].Trim()] = ResolveValue(tagValue[1].Trim(), logger, configuration);
839869
}
840870
else
841871
{
@@ -846,14 +876,14 @@ private static Dictionary<string, string> TracerTagsFromIConfiguration(ILogger l
846876
return tracerTagMaps;
847877
}
848878

849-
private static string ResolveValue(string value, IConfiguration configuration)
879+
private static string ResolveValue(string value, ILogger logger, IConfiguration configuration)
850880
{
851881
if (value.StartsWith("${") && value.EndsWith("}"))
852882
{
853883
string[] kvp = value.Substring(2, value.Length - 3).Split(':');
854884
if (kvp.Length > 0)
855885
{
856-
string propertyValue = GetProperty(kvp[0].Trim(), configuration);
886+
string propertyValue = GetProperty(kvp[0].Trim(), logger, configuration);
857887
if (propertyValue == null && kvp.Length > 1)
858888
{
859889
propertyValue = kvp[1].Trim();

src/Jaeger/Samplers/HttpSamplingManager.cs

+17-9
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,28 @@ namespace Jaeger.Samplers
88
{
99
public class HttpSamplingManager : ISamplingManager
1010
{
11-
public const string DefaultHostPort = "localhost:5778";
11+
public const string DefaultHostPort = "127.0.0.1:5778";
12+
public const string DefaultEndpoint = "http://" + DefaultHostPort + "/sampling";
1213

1314
private readonly IHttpClient _httpClient;
14-
private readonly string _hostPort;
15+
private readonly string _endpoint;
1516

16-
public HttpSamplingManager(string hostPort = DefaultHostPort)
17-
: this(new DefaultHttpClient(), hostPort)
17+
public HttpSamplingManager(string endpoint = DefaultEndpoint)
18+
: this(new DefaultHttpClient(), endpoint)
1819
{
1920
}
2021

21-
public HttpSamplingManager(IHttpClient httpClient, string hostPort = DefaultHostPort)
22+
public HttpSamplingManager(IHttpClient httpClient, string endpoint = DefaultEndpoint)
2223
{
2324
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
24-
_hostPort = hostPort ?? DefaultHostPort;
25+
_endpoint = endpoint ?? DefaultEndpoint;
26+
27+
// Workaround for obsolete HostPort notation.
28+
// UriBuilder needs the schema if host is not an IP and port is given:
29+
if (!_endpoint.StartsWith("http://") && !_endpoint.StartsWith("https://"))
30+
{
31+
_endpoint = "http://" + _endpoint;
32+
}
2533
}
2634

2735
internal SamplingStrategyResponse ParseJson(string json)
@@ -31,15 +39,15 @@ internal SamplingStrategyResponse ParseJson(string json)
3139

3240
public async Task<SamplingStrategyResponse> GetSamplingStrategyAsync(string serviceName)
3341
{
34-
string url = "http://" + _hostPort + "/?service=" + Uri.EscapeDataString(serviceName);
35-
string jsonString = await _httpClient.MakeGetRequestAsync(url).ConfigureAwait(false);
42+
Uri uri = new UriBuilder(_endpoint) {Query = "service=" + Uri.EscapeDataString(serviceName)}.Uri;
43+
string jsonString = await _httpClient.MakeGetRequestAsync(uri.AbsoluteUri).ConfigureAwait(false);
3644

3745
return ParseJson(jsonString);
3846
}
3947

4048
public override string ToString()
4149
{
42-
return $"{nameof(HttpSamplingManager)}(HostPort={_hostPort})";
50+
return $"{nameof(HttpSamplingManager)}(Endpoint={_endpoint})";
4351
}
4452
}
4553
}

test/Jaeger.Tests/ConfigurationTests.cs

+20
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
using Jaeger.Metrics;
99
using Jaeger.Samplers;
1010
using Jaeger.Senders;
11+
using Jaeger.Util;
1112
using Microsoft.Extensions.Logging;
1213
using Microsoft.Extensions.Logging.Abstractions;
1314
using Microsoft.Extensions.Configuration;
15+
using NSubstitute;
16+
using NSubstitute.ReceivedExtensions;
1417
using OpenTracing;
1518
using OpenTracing.Noop;
1619
using OpenTracing.Propagation;
@@ -49,6 +52,7 @@ private void ClearProperties()
4952
ClearProperty(Configuration.JaegerSamplerType);
5053
ClearProperty(Configuration.JaegerSamplerParam);
5154
ClearProperty(Configuration.JaegerSamplerManagerHostPort);
55+
ClearProperty(Configuration.JaegerSamplingEndpoint);
5256
ClearProperty(Configuration.JaegerServiceName);
5357
ClearProperty(Configuration.JaegerTags);
5458
ClearProperty(Configuration.JaegerTraceId128Bit);
@@ -527,6 +531,22 @@ public void TestRateLimitingSampler()
527531
Assert.True(sampler is RateLimitingSampler);
528532
}
529533

534+
[Fact]
535+
public void TestDeprecatedSamplerManagerHostPort()
536+
{
537+
ILoggerFactory loggerFactory = Substitute.For<ILoggerFactory>();
538+
ILogger logger = Substitute.For<ILogger>();
539+
loggerFactory.CreateLogger<Configuration>().Returns(logger);
540+
541+
SetProperty(Configuration.JaegerSamplerManagerHostPort, HttpSamplingManager.DefaultHostPort);
542+
SamplerConfiguration samplerConfiguration = SamplerConfiguration.FromEnv(loggerFactory);
543+
ISampler sampler = samplerConfiguration.GetSampler("name",
544+
new MetricsImpl(NoopMetricsFactory.Instance));
545+
Assert.True(sampler is RemoteControlledSampler);
546+
loggerFactory.Received(1).CreateLogger<Configuration>();
547+
logger.Received(1).Log(LogLevel.Warning, Arg.Any<EventId>(), Arg.Any<object>(), null, Arg.Any<Func<object, Exception, string>>());
548+
}
549+
530550
internal class TestTextMap : ITextMap
531551
{
532552
private Dictionary<string, string> _values = new Dictionary<string, string>();

test/Jaeger.Tests/Samplers/HttpSamplingManagerTests.cs

+16-5
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,25 @@ public class HttpSamplingManagerTests
2222
public HttpSamplingManagerTests()
2323
{
2424
_httpClient = Substitute.For<IHttpClient>();
25-
_undertest = new HttpSamplingManager(_httpClient, "www.example.com");
25+
_undertest = new HttpSamplingManager(_httpClient, "http://www.example.com/sampling");
26+
}
27+
28+
[Fact]
29+
public async Task TestAllowHostPortSyntax()
30+
{
31+
var instance = new HttpSamplingManager(_httpClient, "example.com:80");
32+
_httpClient.MakeGetRequestAsync("http://example.com/?service=clairvoyant")
33+
.Returns("{\"strategyType\":\"PROBABILISTIC\",\"probabilisticSampling\":{\"samplingRate\":0.001},\"rateLimitingSampling\":null}");
34+
35+
SamplingStrategyResponse response = await instance.GetSamplingStrategyAsync("clairvoyant");
36+
Assert.NotNull(response.ProbabilisticSampling);
2637
}
2738

2839
[Fact]
2940
public async Task TestGetSamplingStrategy()
3041
{
31-
_httpClient.MakeGetRequestAsync("http://www.example.com/?service=clairvoyant")
32-
.Returns("{\"strategyType\":0,\"probabilisticSampling\":{\"samplingRate\":0.001},\"rateLimitingSampling\":null}");
42+
_httpClient.MakeGetRequestAsync("http://www.example.com/sampling?service=clairvoyant")
43+
.Returns("{\"strategyType\":\"PROBABILISTIC\",\"probabilisticSampling\":{\"samplingRate\":0.001},\"rateLimitingSampling\":null}");
3344

3445
SamplingStrategyResponse response = await _undertest.GetSamplingStrategyAsync("clairvoyant");
3546
Assert.NotNull(response.ProbabilisticSampling);
@@ -38,7 +49,7 @@ public async Task TestGetSamplingStrategy()
3849
[Fact]
3950
public async Task TestGetSamplingStrategyError()
4051
{
41-
_httpClient.MakeGetRequestAsync("http://www.example.com/?service=")
52+
_httpClient.MakeGetRequestAsync("http://www.example.com/sampling?service=")
4253
.Returns(new Func<CallInfo, string>(_ => { throw new InvalidOperationException(); }));
4354

4455
await Assert.ThrowsAsync<InvalidOperationException>(() => _undertest.GetSamplingStrategyAsync(""));
@@ -87,7 +98,7 @@ public void TestParsePerOperationSampling()
8798
[Fact]
8899
public async Task TestDefaultConstructor()
89100
{
90-
_httpClient.MakeGetRequestAsync("http://localhost:5778/?service=name")
101+
_httpClient.MakeGetRequestAsync("http://127.0.0.1:5778/sampling?service=name")
91102
.Returns(new Func<CallInfo, string>(_ => { throw new InvalidOperationException(); }));
92103

93104
HttpSamplingManager httpSamplingManager = new HttpSamplingManager(_httpClient);

test/Jaeger.Tests/Samplers/Resources/per_operation_sampling.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@
2121
"samplingRate": 0.001
2222
},
2323
"rateLimitingSampling": null,
24-
"strategyType": 0
24+
"strategyType": "PROBABILISTIC"
2525
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"strategyType": 0,
3-
"probabilisticSampling": {
4-
"samplingRate": 0.01
5-
},
6-
"rateLimitingSampling": null
2+
"strategyType": "PROBABILISTIC",
3+
"probabilisticSampling": {
4+
"samplingRate": 0.01
5+
},
6+
"rateLimitingSampling": null
77
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"strategyType": 1,
3-
"probabilisticSampling": null,
4-
"rateLimitingSampling": {
5-
"maxTracesPerSecond": 2.1
6-
}
2+
"strategyType": "RATE_LIMITING",
3+
"probabilisticSampling": null,
4+
"rateLimitingSampling": {
5+
"maxTracesPerSecond": 2.1
6+
}
77
}

0 commit comments

Comments
 (0)