-
Notifications
You must be signed in to change notification settings - Fork 126
Support plugin configuration via environment variables #192
Support plugin configuration via environment variables #192
Conversation
✅ Build jaeger-client-cpp 53 completed (commit efce16d8c7 by @johanneswuerbach) |
src/jaegertracing/TracerFactory.cpp
Outdated
"Failed to construct tracer: Jaeger was not build with yaml support."; | ||
return opentracing::make_unexpected( | ||
std::make_error_code(std::errc::not_supported)); | ||
auto tracerConfig = jaegertracing::Config(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this feels unintuitive - the configuration
is silently ignored in favor of default config? Maybe it should at least have a null check and still error our if not null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, does C++ have some standard way to document functions? This one could use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this feels unintuitive - the configuration is silently ignored in favor of default config?
I reverted now to the old behaviour of erroring out when no config is provided as it feels out of scope of this PR to change that.
does C++ have some standard way to document functions?
I haven't done C++ in a long time so I would need on your knowledge, but looking at the other files I don't see any documentation.
42e2ee2
to
d01d182
Compare
✅ Build jaeger-client-cpp 60 completed (commit 874a14bc58 by @johanneswuerbach) |
errorMessage = "`service_name` not provided"; | ||
return opentracing::make_unexpected( | ||
opentracing::invalid_configuration_error); | ||
} | ||
if (!serviceNameNode.IsScalar()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what this was testing, why is it no longer needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was manually verifying the integrity of the yaml, which should be done by the parsing itself
d01d182
to
5ec2883
Compare
@yurishkuro thanks for the feedback, I addressed your comments. |
✅ Build jaeger-client-cpp 61 completed (commit 36e8a5b57d by @johanneswuerbach) |
5ec2883
to
788f49c
Compare
getting build errors
|
❌ Build jaeger-client-cpp 62 failed (commit bda18a4d74 by @johanneswuerbach) |
5663937
to
ca95345
Compare
@yurishkuro sorry my C++ knowledge is really rusty, any pointers how to properly access the returned tracer instance in the last test to get the service name? |
❌ Build jaeger-client-cpp 63 failed (commit 97658a1323 by @johanneswuerbach) |
❌ Build jaeger-client-cpp 64 failed (commit ac46bdf7fa by @johanneswuerbach) |
7d78e8b
to
86f9fca
Compare
❌ Build jaeger-client-cpp 65 failed (commit 54b0de66e0 by @johanneswuerbach) |
86f9fca
to
4c6fd45
Compare
❌ Build jaeger-client-cpp 66 failed (commit 01e5ead72f by @johanneswuerbach) |
❌ Build jaeger-client-cpp 67 failed (commit 322395b309 by @johanneswuerbach) |
4c6fd45
to
510aa96
Compare
ASSERT_TRUE(tracerMaybe); | ||
|
||
auto tracer = tracerMaybe.value(); | ||
const auto jaegerTracer = std::dynamic_pointer_cast<Tracer>(tracer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yurishkuro any hints how I could the jaeger tracer instance here instead of the opentracing::tracer?
The dynamic pointer cast seems not to work, but I don't understand why :-(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not really, but maybe @mdouaihy could suggest something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mdouaihy I tried:
TEST(TracerFactory, testConfigAndEnvironment)
{
testutils::EnvVariable::setEnv("JAEGER_SERVICE_NAME", "");
const char* config = R"(
{
"service_name": "test"
})";
testutils::EnvVariable::setEnv("JAEGER_SERVICE_NAME", "AService");
TracerFactory tracerFactory;
std::string errorMessage;
auto tracerMaybe = tracerFactory.MakeTracer(config, errorMessage);
ASSERT_EQ(errorMessage, "");
ASSERT_TRUE(tracerMaybe);
const auto tracer =
std::static_pointer_cast<jaegertracing::Tracer>(tracerMaybe.value());
ASSERT_EQ(std::string("test"), tracer->serviceName());
}
but this segfaults. Any pointers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is failing because the the returned tracer is not a Jaeger Tracer but a NoopTracer.
the reason is the environment variable JAEGER_DISABLED being set to true in ConfigTest.
I think that we should clear the set variables in those tests at the end of the test to avoid polluting other tests executions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also note that you'll have to change the configuration of the Sampler and the Reporter to avoid trying to reach a remote address that doesn't exist.
❌ Build jaeger-client-cpp 68 failed (commit 558eaf66d9 by @johanneswuerbach) |
Hello, I find the change a bit unintuitive: the factory is not respecting the configuration the caller provides. Instead, it's reading a global configuration (env variable) instead of just using the configuration provided. Any reason why not filling the configuration as need before calling the factory? |
Most other jaeger clients are already configurable using environment variables https://www.jaegertracing.io/docs/1.15/client-features/ and we use JAEGER_AGENT_HOST inside kubernetes to inject the agent IP into each pod https://www.jaegertracing.io/docs/1.15/operator/#installing-the-agent-as-daemonset While the cpp client itself allows to be configured via environment variables, we only use the plugin via To inject now the IP we could generate the config, or change the plugin to also respect the common environment variables. I found the second option cleaner and opened this PR, but happy for any other recommendations. |
510aa96
to
2c631e2
Compare
2c631e2
to
e1c8555
Compare
@mdouaihy, the If I understand opentracing/opentracing-cpp#45 (comment) correctly the factory seems also be mainly used for dynamic loading, so I'm not sure modifying only dynamic load would be sufficient? |
✅ Build jaeger-client-cpp 72 completed (commit 465215b007 by @johanneswuerbach) |
@johanneswuerbach, there is no need to change the makeTracer method. You can add a property to TracerFactory and an argument to the constructor (in DynamicLoad.cpp/makeTracerFactory) |
4853525
to
e0fd882
Compare
@mdouaihy is something like e0fd882 what you had in mind? It looks like environment variable now take always precedent over the file, is that desired or should I add checks to https://github.com/jaegertracing/jaeger-client-cpp/blob/master/src/jaegertracing/Config.cpp#L37 to validate they are only used when nothing is configured yet? The downside is obviously that this would change behaviour of the current, but unreleased |
✅ Build jaeger-client-cpp 73 completed (commit 04b8217493 by @johanneswuerbach) |
✅ Build jaeger-client-cpp 74 completed (commit ae79f85b82 by @johanneswuerbach) |
Hello @johanneswuerbach, indeed, that's what I had in mind. One small suggestion: maybe we can pass readFromEnv as a constructor parameter (and have a default value for it for backward compatibility). What do you think? For the precedence of the environment over the config, I dont think we should change the behavior of |
do you have any news about this PR? |
e0fd882
to
363dc6e
Compare
✅ Build jaeger-client-cpp 115 completed (commit e29e7b5a82 by @johanneswuerbach) |
363dc6e
to
dc583ad
Compare
Sorry for the delay @mdouaihy, I rebased this PR, but are not sure about your suggestions.
I'm not sure what this means? In this PR I actually prefer the environment variable values now over the config values as |
✅ Build jaeger-client-cpp 116 completed (commit 28014836c3 by @johanneswuerbach) |
Concerning my point @yurishkuro, are you confortable with this behavior or shall we reverse it? |
Signed-off-by: Johannes Würbach <johannes.wuerbach@googlemail.com>
dc583ad
to
43075a2
Compare
@mdouaihy thanks for the pointers, all leaks addressed. |
✅ Build jaeger-client-cpp 117 completed (commit 72e6db93c6 by @johanneswuerbach) |
@@ -41,7 +41,8 @@ static int makeTracerFactory(const char* opentracingVersion, | |||
return opentracing::incompatible_library_versions_error.value(); | |||
} | |||
|
|||
*tracerFactory = new (std::nothrow) jaegertracing::TracerFactory{}; | |||
const auto jaegerTracerFactory = new (std::nothrow) jaegertracing::TracerFactory(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a fan of this API. Without looking up the definition, what does ctor(true)
mean?
In the other languages we simply provide a fromEnv() initializer. Not only it is explicit, but it also decouples factory initialization and reading env, e.g. it is very common to first initialize the factory with some default configuration, and then allow it to be overwritten by env. Here it looks like env vars are read immediately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was originally implemented like that, but @mdouaihy recommended the ctor approach #192 (comment)
I don’t have an opinion and happily change it to your preference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may be mistaken about the role of TracerFactory. If it's a loading mechanism similar to Java's service loader, then it's probably ok to apply env right in the ctor. While I don't like the bool argument, it's ok for a non-user-facing class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yurishkuro, In order to create a tracer, a tracer factory is first created and then MakeTracer method is called to create a tracer.
In MakeTracer, a yaml config file sent as argument. Properties of the tracer are read and a Tracer is configured and built
We would like to read also the env variables. Now since this is a behavioral change, we would like to make this behavior activatable.
The problem is that we cannot change the signature of MakeTracer. it's a public method. the only way is activate this behavior via a parameter passed to the factory at construction time.
@yurishkuro @mdouaihy would it be possible to get a new official release including this change? That would be amazing 🎉 |
waiting for the build to pass #227 |
released in 0.6.0 |
…#192) Signed-off-by: Johannes Würbach <johannes.wuerbach@googlemail.com>
…#192) Signed-off-by: Johannes Würbach <johannes.wuerbach@googlemail.com>
Which problem is this PR solving?
Support using the environment variables added in #181 when using the plugin. E.g. as part of https://github.com/opentracing-contrib/nginx-opentracing/
Short description of the changes
The plugin entry point now tries to parse the yaml file and loads environment variables if they are defined. Once all configuration methods performed, validate that the service name is not empty.