Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for OTEL_EXPORTER_JAEGER_AGENT_HOST and OTEL_EXPORTER_JAEGER_AGENT_PORT #2123

Merged
merged 12 commits into from
Jul 15, 2021

Conversation

pellared
Copy link
Member

@pellared pellared commented Jul 8, 2021

Partially addresses #1453.

This feature is important so that we can reuse the SDK in https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation

Changes

The JaegerExporterOptions defaults can be overriden using OTEL_EXPORTER_JAEGER_AGENT_HOST and OTEL_EXPORTER_JAEGER_AGENT_PORT envionmental variables as defined in the specification.

The implementation is similar to OTel Go, OTel Python, and other languages as well.

For significant contributions please make sure you have completed the following items:

TODO (next PRs)

  1. Update https://github.com/open-telemetry/opentelemetry-specification/blob/main/spec-compliance-matrix.md#environment-variables
  2. Address Add support for OTEL_EXPORTER_JAEGER_AGENT_HOST and OTEL_EXPORTER_JAEGER_AGENT_PORT #2123 (comment)

@pellared pellared requested a review from a team July 8, 2021 07:55
@codecov
Copy link

codecov bot commented Jul 8, 2021

Codecov Report

Merging #2123 (9387fd8) into main (56357fc) will decrease coverage by 0.04%.
The diff coverage is 71.42%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2123      +/-   ##
==========================================
- Coverage   85.04%   84.99%   -0.05%     
==========================================
  Files         187      187              
  Lines        6103     6124      +21     
==========================================
+ Hits         5190     5205      +15     
- Misses        913      919       +6     
Impacted Files Coverage Δ
...Jaeger/Implementation/JaegerExporterEventSource.cs 53.84% <57.14%> (+3.84%) ⬆️
...Telemetry.Exporter.Jaeger/JaegerExporterOptions.cs 84.21% <78.57%> (-15.79%) ⬇️
...emetry.Api/Internal/OpenTelemetryApiEventSource.cs 79.41% <0.00%> (-2.95%) ⬇️
...ZPages/Implementation/ZPagesExporterEventSource.cs 62.50% <0.00%> (+6.25%) ⬆️


public JaegerExporterOptions()
{
string agentHostEnvVar = Environment.GetEnvironmentVariable(OTelAgentHostEnvVarKey);
Copy link

Choose a reason for hiding this comment

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

I would move this section to a new method - eg SetOptionsViaEnvironmentVariables.

Copy link
Member Author

Choose a reason for hiding this comment

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

Waiting for feedback (e.g. upvotes) from others as this may be subjective. This would be the only call in this constructor so it might be seen as an unnecessary level of indirection.

I have no strong opinion here.

Initially, I thought of doing something like:

this.AgentHost = GetStringFromEnvironmentVariable(OTelAgentHostEnvVarKey, "localhost");
this.AgentPort = GetIntFromEnvironmentVariable(OTelAgentPortEnvVarKey, 6831, value => JaegerExporterEventSource.Log.FailedToParseEnvironmentVariable(OTelAgentPortEnvVarKey, value));

but it felt unnecessary complex

Copy link
Contributor

Choose a reason for hiding this comment

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

I kind of like these "general" methods but deferring until more usage seems reasonable.

Copy link
Member

Choose a reason for hiding this comment

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

Please wrap this inside try..catch incase user doesn't have permission to read, it'll throw.

Copy link
Member Author

Choose a reason for hiding this comment

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

Will do

Copy link
Member Author

Choose a reason for hiding this comment

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

Handled: 5909df2
@cijothomas Do we want to have another event for a generic Exception? Personally, I do not like it b/c we can catch e.g. an OutOfMemoryException.

Copy link
Member

Choose a reason for hiding this comment

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

this looks good.

@RassK
Copy link

RassK commented Jul 8, 2021

Should we add option to 'DisableEnvironmentVariablesRead' ? Currently it's a new feature that is forcefully on - so to avoid conflicts when there are multiple applications on the same server instance, there is a way to turn it off.

E: Code has anyway higher importance... but then every single env variable has to be manually neutralized. Which still would cause unwanted feature to be turned on.

@pellared
Copy link
Member Author

pellared commented Jul 8, 2021

Should we add option to 'DisableEnvironmentVariablesRead' ? Currently it's a new feature that is forcefully on - so to avoid conflicts when there are multiple applications on the same server instance, there is a way to turn it off.

From my experience (especially for cloud native apps) the env vars are set per process. IT is even possible it off in code by simply:

Environment.SetEnvironmentVariable("OTEL_EXPORTER_JAEGER_AGENT_HOST", null);
Environment.SetEnvironmentVariable("OTEL_EXPORTER_JAEGER_AGENT_PORT", null);

Comment on lines 27 to 28
private const string OTelAgentHostEnvVarKey = "OTEL_EXPORTER_JAEGER_AGENT_HOST";
private const string OTelAgentPortEnvVarKey = "OTEL_EXPORTER_JAEGER_AGENT_PORT";
Copy link
Member Author

Choose a reason for hiding this comment

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

do we want to have such keys as public static readonly?

Copy link
Member

Choose a reason for hiding this comment

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

My vote is to keep as constants. But I would make them internal const string so you could use them in your unit tests.

Copy link
Member Author

@pellared pellared Jul 8, 2021

Choose a reason for hiding this comment

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

For me using the hardcoded strings makes the test more readable. Especially that the env vars are defined by specs and won't likely change. Moreover it is a safeguard for against changing the const by mistake.

Therefore maybe let's keep it as it is? I tried to keep the code similar to OTEL_RESOURCE_ATTRIBUTES implementation:

Copy link
Member

Choose a reason for hiding this comment

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

IMO it is an SSOT (single source of truth) principle type of thing. If it does need to ever change, it should be in one spot. Those other spots are misbehaving 🤣 Here's a good one:

if (expectedStatusCode == StatusCode.Error)
{
Assert.Contains(jaegerSpan.Tags, t => t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName && t.VType == JaegerTagType.BOOL && (t.VBool ?? false));
}
else
{
Assert.DoesNotContain(jaegerSpan.Tags, t => t.Key == JaegerActivityExtensions.JaegerErrorFlagTagName);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed aad91eb

}
else
{
JaegerExporterEventSource.Log.FailedToParseEnvironmentVariable(OTelAgentPortEnvVarKey, agentPortEnvVar);
Copy link
Member

Choose a reason for hiding this comment

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

@cijothomas Should we actually throw here? I think typically we do for misconfiguration during startup.

Copy link
Member

Choose a reason for hiding this comment

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

My answer would be no.

It is currently unspecified according to the spec.

Looking at the other part of the spec, it seems the general spirit is that the SDK should handle environment variable in a graceful way (e.g. if some environment variable wouldn't make sense, fall back to the default value rather than fail the app).

I think the reason is that environment variable might be invasive (e.g. a child process might inherit environment variable, someone might set global environment variable unintentionally), and we don't want that to crash the app.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just wondering in the case of a typo how visible will be that? Are the host and port logged in case of error sending to a destination? Perhaps log the host, port (all the options in general) at startup so one can easily check the effective configuration?

Copy link
Member Author

@pellared pellared Jul 9, 2021

Choose a reason for hiding this comment

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

@cijothomas What do you think of logging the options as an event with EventLevel.Informational (or even EventLevel.Verbose) e.g. here:

?

Copy link
Member

Choose a reason for hiding this comment

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

As long as we don't log credential by default, I'm supportive (Information/Verbose both sound good to me) 😃

  • If the environment variable is something like OTEL_EXPORTER_JAEGER_AGENT_PASSWORD, we should not log it by default (or we should replace the password with something like ******).
  • If the user put credential in OTEL_EXPORTER_JAEGER_AGENT_PORT, it's their problem, we will log it (rather than trying to do some smart detection and guess if it could be credential).

Copy link
Member Author

@pellared pellared Jul 12, 2021

Choose a reason for hiding this comment

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

@reyang @cijothomas
Should I do it as a separate PR?
Personally, I see it as a separate feature and maybe it would be worth adding a dedicated point in the changelog for it.
I added a "TODO (next PRs)" section in the PR description.

Copy link
Member

Choose a reason for hiding this comment

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

+1 to doing it as a separate PR.

@pellared pellared requested review from reyang and CodeBlanch July 8, 2021 17:27
Copy link
Contributor

@pjanotti pjanotti left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@pjanotti pjanotti left a comment

Choose a reason for hiding this comment

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

@cijothomas
Copy link
Member

@pellared @pjanotti Is there a timeline you are looking to get this change as part of a stable release?
We are planning to release 1.1.0 stable today/monday, and the next planned stable release is in Nov 2021. So by default, this change will go in the 1.2.0 releasing Nov 2021.
https://github.com/open-telemetry/opentelemetry-dotnet/milestones

@pjanotti
Copy link
Contributor

pjanotti commented Jul 9, 2021

@cijothomas thanks for considering the release timelines. Auto-Instrumentation wouldn't be in a stable release soon so we will have to live with provisional releases between 1.1.0 and 1.2.0 while we migrate auto-instrumentation to the SDK.

@pellared
Copy link
Member Author

pellared commented Jul 12, 2021

@pellared could you please also update https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Exporter.Jaeger#readme to include the env vars.

@pjanotti Addressed: c82e761

PS.
@cijothomas @reyang Maybe it would be good to have a table of supported environmental variables in the "root" README? Especially that I have not seen any docs for OTEL_RESOURCE_ATTRIBUTES in this repository.

@cijothomas
Copy link
Member

@pellared could you please also update https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Exporter.Jaeger#readme to include the env vars.

@pjanotti Addressed: c82e761

PS.
@cijothomas @reyang Maybe it would be good to have a table of supported environmental variables in the "root" README? Especially that I have not seen any docs for OTEL_RESOURCE_ATTRIBUTES in this repository.

I think the root readme should be really small!
The resource env var support - can be documented in the SDK's readme page, as thats the project dealing with Resource feature/populating from env.

@cijothomas
Copy link
Member

To avoid adding last minute changes to the 1.1.0 release, this PR will be merged after 1.1.0 is shipped (later today).

Copy link
Member

@cijothomas cijothomas left a comment

Choose a reason for hiding this comment

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

Blocking, just to prevent accidental merge.

@pellared pellared requested a review from cijothomas July 14, 2021 15:55
@cijothomas
Copy link
Member

Ready to merge as 1.1.0 ship has sailed. Will wait till today evening to see if there are any feedbacks, and then merge.

Copy link
Member

@CodeBlanch CodeBlanch left a comment

Choose a reason for hiding this comment

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

LGTM

@cijothomas cijothomas merged commit a9fed42 into open-telemetry:main Jul 15, 2021
@pellared pellared deleted the jeager-env-vars branch July 15, 2021 05:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants