Skip to content

Commit

Permalink
Support Tracer tags and configuration via environment variables (jaeg…
Browse files Browse the repository at this point in the history
…ertracing#181)

* Support configuring client from environment variables (fix jaegertracing#178)

Signed-off-by: FR-MUREX-COM\mchaikhadouaihy <[email protected]>

* Apply Changes requested by @Yurishkhuro
1. When testing the config, start with a defined config instead of an empty one
2. Make sure fromEnv is harmful in case nothing is defined
3. Use literals to avoid fat-finger problem in the code
4. Avoid adding yet additional methods to the Tracer

Signed-off-by: FR-MUREX-COM\mchaikhadouaihy <[email protected]>

* Exclude sampler config.

Signed-off-by: FR-MUREX-COM\mchaikhadouaihy <[email protected]>
  • Loading branch information
mdouaihy authored and Patrick0308 committed Jul 21, 2021
1 parent b9463ba commit 07511d1
Show file tree
Hide file tree
Showing 16 changed files with 944 additions and 432 deletions.
849 changes: 425 additions & 424 deletions CMakeLists.txt

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,60 @@ The code can be re-generated with
$ git apply scripts/thrift-gen.patch
```

### Updating Agent Host and Port

The default host and port for Jaeger Agent is `127.0.0.1:6831`. When the application and Jaeger Agent are running in different containers on the same host, the application's notion of `localhost`/127.0.0.1 it restriced to its own container, so in this case it's usually necessary to override the Agent's host/port by updating your reporter configuration:

YAML configuration:

```yml
repoter:
localAgentHostPort: jaeger-agent:6831
```
NOTE: It is not recommended to use a remote host for UDP connections.
### Connecting directly to the Collector
In case the client should connect directly to the collector instead of going through an agent, it's necessary update the reporter configuration
```yml
repoter:
endpoint: http://${collectorhost}:${collectorport}/api/traces
```
Note that if both `localAgentHostPort` and `endpoint` are specified, the `endpoint` will be used.

### Updating Sampling Server URL

The default sampling collector URL is `http://127.0.0.1:5778/sampling`. Similar to UDP address above, you can use a different URL by updating the sampler configuration.

```yml
sampler:
samplingServerURL: http://jaeger-agent.local:5778
```

### Configuration via Environment

It's possible to populate the tracer configuration from the environement variables by calling `jaegertracing::Config::fromEnv`.

The following property names are currently available:

Property | Description
--- | ---
JAEGER_SERVICE_NAME | The service name
JAEGER_DISABLED _(not recommended)_ | Instructs the Configuration to return a no-op tracer
JAEGER_AGENT_HOST | The hostname for communicating with agent via UDP
JAEGER_AGENT_PORT | The port for communicating with agent via UDP
JAEGER_ENDPOINT | The traces endpoint, in case the client should connect directly to the Collector, like http://jaeger-collector:14268/api/traces
JAEGER_REPORTER_LOG_SPANS | Whether the reporter should also log the spans
JAEGER_REPORTER_MAX_QUEUE_SIZE | The reporter's maximum queue size
JAEGER_REPORTER_FLUSH_INTERVAL | The reporter's flush interval (ms)
JAEGER_SAMPLER_TYPE | The [sampler type](https://www.jaegertracing.io/docs/latest/sampling/#client-sampling-configuration)
JAEGER_SAMPLER_PARAM | The sampler parameter (number)
JAEGER_SAMPLER_MANAGER_HOST_PORT | The host name and port when using the remote controlled sampler
JAEGER_TAGS | 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

## License

[Apache 2.0 License](./LICENSE).
Expand Down
50 changes: 50 additions & 0 deletions src/jaegertracing/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,53 @@
*/

#include "jaegertracing/Config.h"
#include "jaegertracing/samplers/Config.h"
#include "jaegertracing/utils/EnvVariable.h"

namespace jaegertracing {

constexpr const char* Config::kJAEGER_SERVICE_NAME_ENV_PROP;
constexpr const char* Config::kJAEGER_TAGS_ENV_PROP;
constexpr const char* Config::kJAEGER_JAEGER_DISABLED_ENV_PROP;

void Config::fromEnv()
{
const auto disabled =
utils::EnvVariable::getBoolVariable(kJAEGER_JAEGER_DISABLED_ENV_PROP);
if (disabled.first) {
_disabled = disabled.second;
}

const auto serviceName =
utils::EnvVariable::getStringVariable(kJAEGER_SERVICE_NAME_ENV_PROP);
if (!serviceName.empty()) {
_serviceName = serviceName;
}

const auto tags =
utils::EnvVariable::getStringVariable(kJAEGER_TAGS_ENV_PROP);
if (!tags.empty()) {
std::string tag;
std::istringstream tagsStream(tags);
while (std::getline(tagsStream, tag, ',')) {

std::istringstream tagStream(tag);

std::string tagKey;
std::string tagValue;
if (std::getline(tagStream, tagKey, '=')) {
std::getline(tagStream, tagValue, '=');
if (std::getline(tagStream, tagValue, '=')) {
// error, should be logged somewhere
}
else {
_tags.emplace_back(tagKey, tagValue);
}
}
}
}
_reporter.fromEnv();
_sampler.fromEnv();
}

} // namespace jaegertracing
25 changes: 23 additions & 2 deletions src/jaegertracing/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define JAEGERTRACING_CONFIG_H

#include "jaegertracing/Constants.h"
#include "jaegertracing/Tag.h"
#include "jaegertracing/baggage/RestrictionsConfig.h"
#include "jaegertracing/propagation/HeadersConfig.h"
#include "jaegertracing/reporters/Config.h"
Expand All @@ -28,6 +29,11 @@ namespace jaegertracing {

class Config {
public:

static constexpr auto kJAEGER_SERVICE_NAME_ENV_PROP = "JAEGER_SERVICE_NAME";
static constexpr auto kJAEGER_TAGS_ENV_PROP = "JAEGER_TAGS";
static constexpr auto kJAEGER_JAEGER_DISABLED_ENV_PROP = "JAEGER_DISABLED";

#ifdef JAEGERTRACING_WITH_YAML_CPP

static Config parse(const YAML::Node& configYAML)
Expand All @@ -36,6 +42,9 @@ class Config {
return Config();
}

const auto serviceName =
utils::yaml::findOrDefault<std::string>(configYAML, "service_name", "");

const auto disabled =
utils::yaml::findOrDefault<bool>(configYAML, "disabled", false);
const auto samplerNode = configYAML["sampler"];
Expand All @@ -48,7 +57,7 @@ class Config {
const auto baggageRestrictions =
baggage::RestrictionsConfig::parse(baggageRestrictionsNode);
return Config(
disabled, sampler, reporter, headers, baggageRestrictions);
disabled, sampler, reporter, headers, baggageRestrictions, serviceName);
}

#endif // JAEGERTRACING_WITH_YAML_CPP
Expand All @@ -59,8 +68,12 @@ class Config {
const propagation::HeadersConfig& headers =
propagation::HeadersConfig(),
const baggage::RestrictionsConfig& baggageRestrictions =
baggage::RestrictionsConfig())
baggage::RestrictionsConfig(),
const std::string& serviceName = "",
const std::vector<Tag>& tags = std::vector<Tag>())
: _disabled(disabled)
, _serviceName(serviceName)
, _tags(tags)
, _sampler(sampler)
, _reporter(reporter)
, _headers(headers)
Expand All @@ -81,8 +94,16 @@ class Config {
return _baggageRestrictions;
}

const std::string& serviceName() const { return _serviceName; }

const std::vector<Tag>& tags() const { return _tags; }

void fromEnv();

private:
bool _disabled;
std::string _serviceName;
std::vector< Tag > _tags;
samplers::Config _sampler;
reporters::Config _reporter;
propagation::HeadersConfig _headers;
Expand Down
93 changes: 93 additions & 0 deletions src/jaegertracing/ConfigTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "jaegertracing/utils/YAML.h"
#include <gtest/gtest.h>

#include <cstdlib>

namespace jaegertracing {

#ifdef JAEGERTRACING_WITH_YAML_CPP
Expand Down Expand Up @@ -75,4 +77,95 @@ TEST(Config, testDefaultSamplingProbability)

#endif // JAEGERTRACING_WITH_YAML_CPP


void setEnv(const char *variable, const char *value) {
#ifdef WIN32
_putenv_s(variable, value);
#else
setenv(variable, value, true);
#endif
}

TEST(Config, testFromEnv)
{
std::vector<Tag> tags;
tags.emplace_back("hostname", std::string("foo"));
tags.emplace_back("my.app.version", std::string("1.2.3"));

Config config(false,
samplers::Config("probabilistic",
0.7,
"http://host34:57/sampling",
0,
samplers::Config::Clock::duration()),
reporters::Config(10,
std::chrono::milliseconds(100),
false,
"host35:77",
"http://host36:56568"),
propagation::HeadersConfig(),
baggage::RestrictionsConfig(),
"test-service",
tags);

config.fromEnv();

ASSERT_EQ(std::string("http://host36:56568"), config.reporter().endpoint());
ASSERT_EQ(std::string("host35:77"), config.reporter().localAgentHostPort());

ASSERT_EQ(10, config.reporter().queueSize());
ASSERT_EQ(std::chrono::milliseconds(100),
config.reporter().bufferFlushInterval());
ASSERT_EQ(false, config.reporter().logSpans());

ASSERT_EQ(.7, config.sampler().param());
ASSERT_EQ(std::string("probabilistic"), config.sampler().type());

setEnv("JAEGER_AGENT_HOST", "host33");
setEnv("JAEGER_AGENT_PORT", "45");
setEnv("JAEGER_ENDPOINT", "http://host34:56567");

setEnv("JAEGER_REPORTER_MAX_QUEUE_SIZE", "33");
setEnv("JAEGER_REPORTER_FLUSH_INTERVAL", "45");
setEnv("JAEGER_REPORTER_LOG_SPANS", "true");

setEnv("JAEGER_SAMPLER_PARAM", "33");
setEnv("JAEGER_SAMPLER_TYPE", "const");

setEnv("JAEGER_SERVICE_NAME", "AService");
setEnv("JAEGER_TAGS", "hostname=foobar,my.app.version=4.5.6");

config.fromEnv();

ASSERT_EQ(std::string("http://host34:56567"), config.reporter().endpoint());
ASSERT_EQ(std::string("host33:45"), config.reporter().localAgentHostPort());

ASSERT_EQ(33, config.reporter().queueSize());
ASSERT_EQ(std::chrono::milliseconds(45),
config.reporter().bufferFlushInterval());
ASSERT_EQ(true, config.reporter().logSpans());

ASSERT_EQ(33., config.sampler().param());
ASSERT_EQ(std::string("const"), config.sampler().type());

ASSERT_EQ(std::string("AService"), config.serviceName());

std::vector<Tag> expectedTags;
expectedTags.emplace_back("hostname", std::string("foo"));
expectedTags.emplace_back("my.app.version", std::string("1.2.3"));
expectedTags.emplace_back("hostname", std::string("foobar"));
expectedTags.emplace_back("my.app.version", std::string("4.5.6"));
ASSERT_EQ(expectedTags, config.tags());

ASSERT_EQ(false, config.disabled());

setEnv("JAEGER_DISABLED", "TRue"); // case-insensitive
setEnv("JAEGER_AGENT_PORT", "445");

config.fromEnv();
ASSERT_EQ(true, config.disabled());
ASSERT_EQ(std::string("host33:445"),
config.reporter().localAgentHostPort());
}

} // namespace jaegertracing
29 changes: 29 additions & 0 deletions src/jaegertracing/Tracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,33 @@ Tracer::analyzeReferences(const std::vector<OpenTracingRef>& references) const
return result;
}

std::shared_ptr<opentracing::Tracer>
Tracer::make(const std::string& serviceName,
const Config& config,
const std::shared_ptr<logging::Logger>& logger,
metrics::StatsFactory& statsFactory, int options)
{
if (serviceName.empty()) {
throw std::invalid_argument("no service name provided");
}

if (config.disabled()) {
return opentracing::MakeNoopTracer();
}

auto metrics = std::make_shared<metrics::Metrics>(statsFactory);
std::shared_ptr<samplers::Sampler> sampler(
config.sampler().makeSampler(serviceName, *logger, *metrics));
std::shared_ptr<reporters::Reporter> reporter(
config.reporter().makeReporter(serviceName, *logger, *metrics));
return std::shared_ptr<Tracer>(new Tracer(serviceName,
sampler,
reporter,
logger,
metrics,
config.headers(),
config.tags(),
options));
}

} // namespace jaegertracing
12 changes: 10 additions & 2 deletions src/jaegertracing/Tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ class Tracer : public opentracing::Tracer,

static constexpr auto kGen128BitOption = 1;

static std::shared_ptr<opentracing::Tracer> make(const Config& config)
{
return make(config.serviceName(),
config,
std::shared_ptr<logging::Logger>(logging::nullLogger()));
}

static std::shared_ptr<opentracing::Tracer>
make(const std::string& serviceName, const Config& config)
{
Expand All @@ -68,7 +75,6 @@ class Tracer : public opentracing::Tracer,
metrics::NullStatsFactory factory;
return make(serviceName, config, logger, factory);
}

static std::shared_ptr<opentracing::Tracer>
make(const std::string& serviceName,
const Config& config,
Expand All @@ -77,7 +83,6 @@ class Tracer : public opentracing::Tracer,
{
return make(serviceName, config, logger, statsFactory, 0);
}

static std::shared_ptr<opentracing::Tracer>
make(const std::string& serviceName,
const Config& config,
Expand Down Expand Up @@ -223,6 +228,7 @@ class Tracer : public opentracing::Tracer,
const std::shared_ptr<logging::Logger>& logger,
const std::shared_ptr<metrics::Metrics>& metrics,
const propagation::HeadersConfig& headersConfig,
const std::vector<Tag>& tags,
int options)
: _serviceName(serviceName)
, _hostIPv4(net::IPAddress::localIP(AF_INET))
Expand Down Expand Up @@ -254,6 +260,8 @@ class Tracer : public opentracing::Tracer,
_tags.push_back(Tag(kTracerIPTagKey, _hostIPv4.host()));
}

std::copy(tags.cbegin(), tags.cend(), std::back_inserter(_tags));

std::random_device device;
_randomNumberGenerator.seed(device());
}
Expand Down
3 changes: 1 addition & 2 deletions src/jaegertracing/TracerFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,9 @@ TracerFactory::MakeTracer(const char* configuration,
return opentracing::make_unexpected(
opentracing::invalid_configuration_error);
}
std::string serviceName = serviceNameNode.Scalar();

const auto tracerConfig = jaegertracing::Config::parse(yaml);
return jaegertracing::Tracer::make(serviceName, tracerConfig);
return jaegertracing::Tracer::make(tracerConfig);
#endif // JAEGERTRACING_WITH_YAML_CPP
} catch (const std::bad_alloc&) {
return opentracing::make_unexpected(
Expand Down
Loading

0 comments on commit 07511d1

Please sign in to comment.