Closed Silvenga closed 2 months ago
Thanks for opening this issue. We'll be fixing that.
Also got mentioned here: https://github.com/getsentry/sentry-dotnet/pull/2655#issuecomment-1933675566
@Silvenga this is by design. It's one of the changes we made in the 4.0 release.
If you want to disable Sentry, you should provide the disabled DSN (which is string.Empty
rather than null
).
If you want to conditionally disable Sentry, that could be done by altering your call to UseSentry
slightly - see here for an example.
@jamescrosswell regarding this approach - https://github.com/getsentry/sentry-dotnet/pull/2655#issuecomment-1933675566
How would this be configured?
To be clear, we are talking about not using the IConfiguration system.
Unless you are saying that when the Action<SentryAspNetCoreOptions>
is called that Sentry has already pulled the DSN from the environment?
Ugh, no this isn't great either way.
If you are using multiple independent Sentry integrations e.g. NLog and ASP.NET Core, then one of them MUST specify a default empty string. But what if you conditionally enable one of the integrations e.g. ASP.NET, but keep the other one e.g. NLog (as it's much harder to disable conditionally) - if you don't setup the ASP.NET, then the NLog side will throw instead.
Sentry should default the DSN to be an empty string and throw on null - not default at null and throw on null.
If you are using multiple independent Sentry integrations e.g. NLog and ASP.NET Core, then one of them MUST specify a default empty string.
Yes, we did have to headscratch about that as well... which we resolved by adding non-initialising overrides.
Sentry should default the DSN to be an empty string and throw on null - not default at null and throw on null.
That would be one design. The issue we have with that is that new users of Sentry (who don't know anything about DSNs) will often forget to set the DSN and Sentry inexplicably doesn't work for them... no error messages, nothing. That's not a great first experience with the product. We figured if someone has just "forgotten" to configure the SDK correctly, we should be throwing an exception. On the other hand, users who know what they're doing can always explicitly/deliberately disable Sentry using the Disabled DSN.
@jamescrosswell regarding this approach - #2655 (comment)
How would this be configured?
That comment is where I'm confused -
Unless you are saying that when the Action
is called that Sentry has already pulled the DSN from the environment?
which we resolved by https://github.com/getsentry/sentry-dotnet/pull/2928.
How should be do this when configuring NLog via the XML file? We want NLog to configure Sentry if it's the only integration, if the Sentry environment is set.
We need Sentry to not throw, when generically added to different applications. Some are web applications, while others might be service workers.
How should be do this when configuring NLog via the XML file? We want NLog to configure Sentry if it's the only integration, if the Sentry environment is set.
InitializeSdk
is just another property on the options:
https://github.com/getsentry/sentry-dotnet/blob/2285a7f3b805136ab858d4f61e456f30b8a1e2c4/src/Sentry.Serilog/SentrySerilogOptions.cs#L12
So this can be configured via Configuration Bindings as well. You can set it to true or to false via XML, a JSON file, and Environment Variable or via code.
I think everything you're talking about should be possible then. If you think you've found an edge case, I'd love to see it, in which case could you put together a small demo illustrating the problem?
I am wondering whether we need to make the same changes to NLog that we made to SeriLog... I don't recall having made any changes to the NLog library around the time we fixed all this... but it does look like it's there:
I think everything you're talking about should be possible then
RE: https://docs.sentry.io/platforms/dotnet/guides/nlog/
The SDK needs to be initialized only once. If a DSN is made available to this integration, by default it will initialize the SDK. If you do not wish to initialize the SDK via this integration, set the InitializeSdk flag to false. Not providing a DSN or leaving it as null instructs the integration not to initialize the SDK and unless another integration initializes it or you call SentrySdk.Init, the SDK will stay disabled.
NLog is configured with a XML file, there isn't a way to conditionally set the DSN to empty string if no other integration configured Sentry or Sentry didn't pick up the environment variable.
Yes, NLog can be configured with code, but that's a non-standard approach as NLog treats logging as a cross-cutting concern that may not actually be controlled by the developer.
At the end of the day, it is expected to be able to use multiple Sentry integrations at the same time. To avoid temporal coupling, each integration should self configure, if initialized first. With this change, developers now have to know about every integration that can possibly initialize the SDK, and ensure only one of them does, AND that integration can set a empty string on the DSN. I currently expect to be able to swap different integrations in and out, and everything should work. But not on 4.X - where we now need custom code in the first place the SDK can be configured.
NLog is configured with a XML file
Yeah but when you initialize Sentry with NLog, Sentry has to get it's settings from somewhere right? Do those come from the XML file? If so, we can configure InitializeSdk
there in the same way that all the other Sentry settings get configured.
I think we might be talking past one another. If you can give me a small sample project (just new something up and add Sentry + NLog), I can take a look at it. Alternatively I can do the same (I created one yesterday to look into another issue, so I could share that).
I think we might be talking past one another.
Yeah, I agree. This isn't a purely functional problem in my mind, but also a design problem - increasing the complexity of using Sentry on larger projects and across many teams, to help the beginner out. I get it, Microsoft has been pushing for the same - with an compiler generated Main method and such - but I think the community agrees that this approach only works on trivial projects.
Here's an example of a basic NLog setup. The application crashes on startup with 4.X, but not with 3.X.
https://github.com/Silvenga/sentry-nlog-repro
Imagine deploying this code, ideally, I would configure an environment variable that only exists in the environments that care about Sentry.
ideally, I would configure an environment variable that only exists in the environments that care about Sentry.
OK that makes sense. Thanks for the demo project @Silvenga!
So you don't want to set it in the XML... and if you disable it in the config then any DSN from the environment variable would be ignored, because the config files take precedence.
In this case there's a fallback mechanism that we can use, which is to set an attribute on the assembly: https://github.com/getsentry/sentry-dotnet/blob/0aed96926720b59f20c6c3e781dce68df99c9e27/src/Sentry/Internal/SettingLocator.cs#L33-L47
So if you add a file to the project (typically called AssembyInfo.cs
) with the following contents, you'll end up with the same behaviour as you had in 3.x (which is that if no DSN is provided anywhere, you get a disabled DSN by default):
using Sentry;
[assembly: Dsn(SentryConstants.DisableSdkDsnValue)]
If you do want to enable Sentry on a particular machine, just set the DSN in an environment variable. If you don't set it, this means Sentry will be disabled.
So you don't want to set it in the XML... and if you disable it in the config then any DSN from the environment variable would be ignored, because the config files take precedence.
The problem is that we CAN'T set it in the XML.
So if you add a file to the project
GetEntryAssembly
can be incredibly iffy, noting under .NET Framework, e.g. https://stackoverflow.com/questions/4277692/getentryassembly-for-web-applications.
How would you propose handing the ASP.NET case?
@Silvenga what do you think about this approach: https://github.com/getsentry/sentry-dotnet/pull/2655#issuecomment-1935550978
Though I personally think that code in ServiceLocator should be changed so that env variable can override empty string.
@Silvenga what do you think about this approach: #2655 (comment)
I don't think that would work, given this may not be a ASP.NET Core app.
Though I personally think that code in ServiceLocator should be changed so that env variable can override empty string.
I think I agree with you there. It would be more consistent with how things are done in ASP.NET Core:
Using the default configuration, the EnvironmentVariablesConfigurationProvider loads configuration from environment variable key-value pairs after reading appsettings.json, appsettings.{Environment}.json, and user secrets. Therefore, key values read from the environment override values read from appsettings.json, appsettings.{Environment}.json, and user secrets.
This probably needs some discussion though as there are probably loads of customers out there who have configured their environments based on the current behaviour... so I think it'd be a breaking change.
@bitsandfoxes @bruno-garcia
Considering this closed as we've restored the behaviour in 4.1.1
with https://github.com/getsentry/sentry-dotnet/pull/3147
Please feel free to reopen this if you're still running into issues.
Thanks, 4.1.1 allowed me to upgrade with minor tweaks. I now pass empty string in code and then can dynamically enable sending by setting SENTRY_DSN
env var, like in 3.x.
Package
Sentry
.NET Flavor
.NET
.NET Version
8.0.0
OS
Any (not platform specific)
SDK Version
8.0.0
Self-Hosted Sentry Version
No response
Steps to Reproduce
When starting Sentry with no DSN configured (say, locally), Sentry now throws an exception.
Expected Result
No exception should be thrown when no DSN is specified - be it null or empty string. Having no DSN should disable the Sentry SDK (where possible).
Actual Result