Skip to content

Inject dd.{service|version|env} in logs #1579

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

Merged
merged 3 commits into from
Jun 18, 2020

Conversation

lpriima
Copy link
Contributor

@lpriima lpriima commented Jun 12, 2020

Injecting 3 new tags :

  • dd.service
  • dd.version
  • dd.env

in MDC of every thread for 3 supported logger interfaces .

Logger instrumentation is disabled by default. It can be enabled by -Ddd.logs.injection=true .

@lpriima lpriima requested a review from a team as a code owner June 12, 2020 11:25
throws InvocationTargetException, IllegalAccessException {
putMethod.invoke(null, Tags.DD_SERVICE, Config.get().getServiceName());
{
final Map<String, String> mergedSpanTags = Config.get().getMergedSpanTags();
Copy link
Contributor

@richardstartin richardstartin Jun 12, 2020

Choose a reason for hiding this comment

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

It's better not to separate Map.containsKey from Map.get because it involves two lookups. Instead it's better to get the value and check if it's not null. If this happens quite a lot the difference will add up - how often will this get called? If once per span, please make the change, otherwise don't worry about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It happens 1 time per instrumentation. 3 times total during agent startup. But I've changed it

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure, sorry, didn't get the full context from the PR alone.

Copy link
Contributor

@tylerbenson tylerbenson left a comment

Choose a reason for hiding this comment

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

I don't quite understand... How does this inject those tags into the MDC if no span/scope is created on a given thread?

@bantonsson
Copy link
Contributor

@tylerbenson As far as I understand, the MDC is implemented as an inheritable thread local, and this code puts the values in the root MDC that is created during initialization of the logging, which all subsequently created threads will inherit. That being said, if there have been threads created before this initialization, they will not receive the mappings in the MDC.

@tylerbenson
Copy link
Contributor

Ok, assuming that's how it works then fine. It would be nice to see if we could have tests validate that somehow? Eg, if you spawn a new thread and do a println without any span in scope, does it show these properties correctly?

@lpriima
Copy link
Contributor Author

lpriima commented Jun 17, 2020

@lpriima lpriima force-pushed the lpriima/dd.{service|version|env}_to_logs branch from b8bee9e to 14b30bf Compare June 17, 2020 23:03
@lpriima lpriima requested a review from tylerbenson June 17, 2020 23:33
Comment on lines +89 to +95
final Field mdcAdapterField = mdcClass.getDeclaredField("mdcAdapter");
mdcAdapterField.setAccessible(true);
final MDCAdapter mdcAdapterInstance = (MDCAdapter) mdcAdapterField.get(null);
final Field copyOnThreadLocalField =
mdcAdapterInstance.getClass().getDeclaredField("copyOnThreadLocal");
copyOnThreadLocalField.setAccessible(true);
copyOnThreadLocalField.set(mdcAdapterInstance, new ThreadLocalWithDDTagsInitValue());
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice if we could avoid all this reflection, but I don't think we can because of our shadow rename for SLF4j.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was trying several ways, how to do it more beautiful, but found nothing better than this
If they rename private field, test should fail.

@lpriima lpriima merged commit b7b2645 into master Jun 18, 2020
@lpriima lpriima deleted the lpriima/dd.{service|version|env}_to_logs branch June 18, 2020 23:30
@github-actions github-actions bot added this to the 0.56.0 milestone Jun 18, 2020
@@ -42,18 +44,30 @@ protected boolean defaultEnabled() {

@Override
public String[] helperClassNames() {
return new String[] {LogContextScopeListener.class.getName()};
return new String[] {
LogContextScopeListener.class.getName(), ThreadLocalWithDDTagsInitValue.class.getName(),
Copy link
Contributor

Choose a reason for hiding this comment

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

This creates extra class loads that we don't need.
While annoying it is better to do "foo.bar.QuuxClass" instead of QuuxClass.class.getName()

public class ThreadLocalWithDDTagsInitValue extends ThreadLocal<Map<String, String>> {
@Override
protected Map<String, String> initialValue() {
return LogContextScopeListener.LOG_CONTEXT_DD_TAGS;
Copy link
Contributor

Choose a reason for hiding this comment

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

I noticed this Map is immutable. Do we end up injecting this Map directly into the MDC?
If so, how does this work if the MDC is modified?

Copy link
Contributor

Choose a reason for hiding this comment

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

It results in throwing an exception like this:

	at java.util.Collections$UnmodifiableMap.put(Collections.java:1457)
	at ch.qos.logback.classic.util.LogbackMDCAdapter.put(LogbackMDCAdapter.java:110)
	at org.slf4j.MDC.put(MDC.java:147)
	at org.apache.log4j.MDC.put(MDC.java:25)
	at com.xxx.application.code(...)```

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