-
Notifications
You must be signed in to change notification settings - Fork 208
Programmatic configuration for TelemetryConfiguration #461
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
Conversation
|
@gavlyukovskiy Thank you very much for your contribution towards enabling spring boot support with Application Insights. Amazing work! I have added reviewers to your pull request and we will review it. Lets have a conversation around this and we shall take it from there. On a brief overview I feel this is a good concept. |
SergeyKanzhelev
left a comment
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 left a comment. Maybe I do not understand the whole context - will be happy to learn more
| * Telemetry configuration must not be set twice explicitly or through calling {@link TelemetryConfiguration#getActive()}. | ||
| * | ||
| * @param telemetryConfiguration preconfigured instance of Telemetry Configuration | ||
| */ |
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.
We found it messy to allow to replace the configuration object. As you mentioned in comments one of the modules may get a hold of an object and will not pick up an update. Would it be better to update properties of an object instead?
With dependency injection we would simply initialize singleton of dependency injection with the value of telemetryconfiguration.active
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.
That's why I added throw to be sure that configuration is initialized only once and no module is initialized with wrong TelemetryConfiguration. Probably configuration could be changed once context is loaded but I'm afraid that some module can get properties from the TelemetryConfiguration when those properties are not set yet - like WebRequestTrackingFilter#registerWebApp that is executed only once.
| */ | ||
| public static void setActive(TelemetryConfiguration telemetryConfiguration) { | ||
| synchronized (s_lock) { | ||
| if (initialized) { |
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.
Public APIs do not throw in Application Insights SDK
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 agree with Sergey's point here. Throwing an exception in public API will crash the customers application and prevent it from starting. It is not a desired behavior.
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 would agree with you about runtime exceptions, but this one is startup exception, where, from my point of view, is better to get exception when something goes wrong rather than found that telemetry is not working after application is started. But if this is a strong sdk convention, I can just log error into logs.
dhaval24
left a comment
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 have added some common observations and comments. We can discuss this in detail.
| */ | ||
| public static void setActive(TelemetryConfiguration telemetryConfiguration) { | ||
| synchronized (s_lock) { | ||
| if (initialized) { |
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 agree with Sergey's point here. Throwing an exception in public API will crash the customers application and prevent it from starting. It is not a desired behavior.
| public static void setActive(TelemetryConfiguration telemetryConfiguration) { | ||
| synchronized (s_lock) { | ||
| if (initialized) { | ||
| throw new IllegalStateException("Telemetry configuration is already initialized. " + |
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.
Can we some how prevent this behavior programaticallly? If some one tries to call setActive() twice the second call is ignored?
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.
Answered in previous thread, this is probably an option, but I wouldn't implement it like that, it is too dangerous and hard to debug if something goes wrong, it should not be initialized more than once.
| name = telemetryConfiguration.getApplicationName(); | ||
| } | ||
| else if (CommonUtils.isNullOrEmpty(contextPath)) { | ||
| URL[] jarPaths = ((URLClassLoader) (this.getClass().getClassLoader())).getURLs(); |
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 an issue with JDK 9. The default class loader of JDK 9 is not an instance of URLClassLoader but is instead called "App-Classloader". This call to getURLs() would fail here. Do we have a work around for this ? Have you tried this on a Spring Boot Project with JDK 9?
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 haven't tried it on JDK 9, but probably ClassLoader#getResources/ClassLoader#getSystemResources will do the job.
| if (CommonUtils.isNullOrEmpty(contextPath)) { | ||
| TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.getActive(); | ||
| if (telemetryConfiguration.getApplicationName() != null) { | ||
| name = telemetryConfiguration.getApplicationName(); |
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.
Do we need a check here if someone has tried setting application name as 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.
Thanks, I will add check into TelemetryConfiguration#setApplicationName that name is not null or empty.
|
I created repo with sample project here it shows how it is easy to start with starter in spring boot application. |
Fix #359, revisit #411.
Adds a way to configure TelemetryConfiguration from outside application insights library.
It is a must for spring boot integration because you can retrieve configuration only from spring context itself.
Whereas the same can be achieved by creating yet another
@Configurationclass, just likeInterceptorRegistry, and asking user to import that one, it also can be accomplished by creating a spring boot starter with our full control of context initialization order.I've prepared such starter that links with my forked version of sdk and once is added, requires only single property
azure.application-insights.instrumentation-keyto be set to integrate spring boot application with Application Insights.As well allows you to use spring context to manage
TelemetryConfigurationcomponents - you can define any telemetry module, channel or sampler as@Beanand it will be used insideTelemetryConfiguration. Also it adds nice spring boot feature such like configuration metadata -when IDE shows you the list of available configuration properties.
Conceptually all changes are backward compatible and only concern is that all modules that are using
TelemetryConfiguration#getActive()must be initialized afterTelemetryConfigurationis created by spring context, which is not possible for logger appenders, that's why I added lazy initialization inside logback appender (log4j and log4j2 can be modified in the same way) which leads to loss of initial log messages. If you think it is critical I can implement some kind of a buffer that will hold telemetry events until configuration is initialized.You can look at my starter project to find more details. Also I can upload my sample project that uses forked version of sdk and the starter.