-
Notifications
You must be signed in to change notification settings - Fork 407
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
Configure newrelic using custom config object (discussion) #149
Conversation
Extract index.js to bootstrap.js, encapsulate it in a function. Make index.js call this function directly, but users wanting to provide their own configuration can do so by requiring bootstrap.js instead.
Need to avoid this circular dependency when bootstrapping using custom configuration object.
Ok, so we found a solution which will satisfy all our requirements without any changes to node-newrelic. Pseudo-code for what we're doing:
Simple and clean. |
I wouldn't call overriding environment variables from within your app clean. I agree that you should be able to initialize newrelic by requiring it with an options object. |
Ok, I agree, I'll reopen so we can discuss it. |
Agreed. Bootstrapping from a config object would be ideal. I'm currently using a config module that allows me to configure options per environment, so I'd just use that to feed options to the newrelic module. The alternatives work, but are cumbersome :) |
I don't think it's unreasonable to pass a config object directly. There are a few things to consider:
I've put this as a feature request for now. It's reasonable, but I don't have an estimate yet for when we will integrate this. |
Thanks @groundwater. Regarding your point 1, this is only true if the same |
@joscarsson Unfortunately, that's not how Node's module cache works. In order for New Relic's low-level shims to work properly, they have to be loaded before any of the core modules that have asynchronous functions are required anywhere in your application. This is why New Relic's documentation is so insistent about |
@othiym23 Thanks for explaining. We are not processing configuration asynchronously (we use the |
@joscarsson The issue is not with New Relic for Node itself, but with the |
For more context on why New Relic for Node's configuration works this way, see issues #5, #20, #27, #52, and #81. I no longer work on New Relic for Node (or at New Relic, for that matter), so I'm just here to be helpful (and maybe stick up for my own prior design decisions), but I will say that I'm not sure that bikeshedding over how the module is configured is productive. Using |
So @othiym23, if the first thing you do is to require continuation-local-storage (or async-listener), everything would work? The shimming and so would be in place, then you'd do This would require the app to have continuation-local-storage / async-listener as dependencies. But if they do for other reasons, it would work fine to configure New Relic this way, right? |
@tgwizard You could, but that doesn't mean it's a good idea. If you're willing to take on the project of learning how all this stuff interacts (which, IMO, diminishes the value of New Relic as a black box that you add to your app to give you insight into how it's performing), you can certainly try whatever you want. However, that's going to make it harder for New Relic to support you, and may also affect your ability to trust the metrics you get out of it. Setting a few environment variables and sticking |
@othiym23 I agree with you. It is probably not a best solution for most applications. Seeing New Relic as a black box can be appropriate for some apps, and when configuration can easily and securely be set through environmentvariables externally to the app, or through the newrelic.js file, that would be best. But for those apps that have other configuration setups, perhaps running separate processes and apps from the same source, and actually are using continuation-local-storage for other purposes, I'd say it could be suitable. Still, three ways to configure the same things is probably not good or worth it. Environment variables and the newrelic.js file suffice. And given that breaking backwards compatibility isn't much fun, it wouldn't perhaps give that much to now replace newrelic.js with explicitly initializing New Relic. |
Instead of having a single If there is enough want/need I can put in a feature request to be able to use an envvar to specify the file exactly instead of just pointing at a directory with a I am generally opposed to passing in configuration to the agent, as the vast majority of cases can be handled via ENV or via the fact that |
This issue has been open for a few weeks now without any further feedback. We feel this PR isn't the best way to configure the agent, and there are alternative mechanisms for solving this issue. I am going to close this issue out now. If, as @wraithan mentioned, anyone feels there is a need for specifying which configuration file to use instead of defaulting to newrelic.js or using the NEW_RELIC_HOME env var, please speak up! Thanks! |
Sorry for not responding back. As I wrote in my second post in this PR we found a solution that works for us, but I reopened so we could have the discussion. Thanks to everyone commenting and participating! |
…/elasticsearch/axios-and-newrelic-1.6.0 chore(deps): bump axios and newrelic in /elasticsearch
updated test utils and use helper.getShim instead of local one
chore: removes skipping of tests on 13.4.13 and above
I'm opening this pull request mainly to start a discussion. I could have opened an issue, but in this case I think it is more constructive to actually provide some proof-of-concept code for what I am after.
So, in our application we have multiple processes/servers running from the same source code tree (so there will be several
app.js
run using different executions of thenode
binary, but only onenode_modules
folder). That means placing anewrelic.js
in the root of the application is not "good enough" in our case, because we want to provide different application names for the different applications.In
node-newrelic/lib/config.js
the following code block is found:That means we could make sure our
node
executions have their working directory set to whereapp.js
resides, and place onenewrelic.js
at each of these locations (because of theprocess.cwd()
above). Although I guess it will work, I haven't tried it, because it still does not satisfy all our requirements. We also want to be able to changeapp_name
depending on which environment we run on (for example, stage environment should report to App Name (Stage) whereas production should report to App Name).So what we are actually after is to be able to pass our own config object into newrelic directly, without using the
newrelic.js
file or environment variables. This gives several advantages:In our
app.js
, it will look like this:The commits in this pull request enable this functionality. It wraps the code in
node-newrelic/index.js
in a function innode-newrelic/bootstrap.js
. Theindex.js
directly calls this newbootstrap.js
function with an empty argument, meaning it will not use a custom configuration object so existing code will continue to function without changes.You actually had this somewhat prepared in
node-newrelic/lib/config.js
:and
The code in the new
bootstrap.js
utilizes thisinitialize(config)
function.The problem with this solution is the circular dependency between
logger
andconfig
. To get this to work, I had to disable therequire()
ofconfig
inlogger
. This dependency seems a bit strange as you have noticed yourselves too, innode-newrelic/lib/config.js
:And this comment in
node-newrelic/index.js
(bootstrap.js
in this pull request) is actually not correct any longer:The row above will never throw, as it will already have thrown when requiring the
logger
(as that depends onconfig
) on the first line in the filelogger = require(path.join(__dirname, 'lib', 'logger.js'))
. Is this intended?If the circular dependency was removed somehow, the pull request would pretty much work as is. As I understand it, the "only" thing configured in
logger
fromconfig
is loglevel and filepath if logging to file. Perhaps there could be defaults for this instead, or only allow these options to be configured from environment variables? Anything removing the dependency onconfig
would work.Or am I doing this whole thing wrong? Is there an easy solution for what I am after? If not, are you planning to support anything similar to the above? We really like newrelic, and this is the last piece for us to be able to use it in this system.