.NET Standard 2.0 logging NLOG gives System.TypeInitializationException - nlog

I did 2 projects to test out NLog on a .NET Framework 4.6.1 standard console app and on .NET Standard 2.0 Library. My intention is to port as much code as I can to .NET Standard 2.0 for future multiplatform compatibility.
Both share the same code but the .NET Standard version produces an exception.
Here's the code
Console.WriteLine("Writing log");
Logger _errorLog = LogManager.GetLogger("ErrorsLogger");
Logger _tradesLog = LogManager.GetLogger("TradesLogger");
_errorLog.Error("This is the log message!!!");
Console.WriteLine("End log");
Console.Read();
Here's the App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
</configSections>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="ErrorsLogger" xsi:type="File" fileName="ErrorsLog.txt" />
<target name="TradesLogger" xsi:type="File" fileName="TradesLog.txt" />
</targets>
<rules>
<logger name="ErrorsLogger" minlevel="Info" writeTo="ErrorsLogger" />
<logger name="TradesLogger" minlevel="Info" writeTo="TradesLogger" />
</rules>
</nlog>
</configuration>
I get the log fine in the .NET 4.6.1 Console app and produces the expected log file with the log message in it.
If I run the .NET Standard 2.0 library through some Microsoft Unit Test project I get this exception when it tries to call _errorLog.GetLogger
UnitTestProject.UnitTest1.TestMethod1 threw exception:
System.TypeInitializationException: The type initializer for
'NLog.LogManager' threw an exception. --->
System.TypeInitializationException: The type initializer for
'NLog.LogFactory' threw an exception. --->
System.MissingMethodException: Method not found:
'System.AppDomainSetup System.AppDomain.get_SetupInformation()'.
EDIT:
Nuget NLOG Version: 4.4.12
Exception thrown in a non static method:
About the non static method to get a better exception:
The exception is thrown at the GetLogger("X") level, which is a non static constructor. The initialization routine crashes even before trying to log something.
In addition, I get a WARNING (yellow exclamation mark) in the error list saying:
Warning The 'configuration' element is not declared.
Adding internal logging doesn't produce any output. This is the configuration i have used, starting from their Internal logging guide:
InternalLogger.LogLevel = LogLevel.Trace;
InternalLogger.LogFile = #"C:\temp\int.txt";
InternalLogger.LogToConsole = true;
InternalLogger.LogToConsoleError = true;
InternalLogger.LogWriter = new StringWriter(new StringBuilder());
InternalLogger.LogToTrace = true;
LogManager.ThrowConfigExceptions = true;
LogManager.ThrowExceptions = true;
Logger logger = LogManager.GetLogger("foo");
I'm administrator and Visual Studio 2017 is started as administrator and I have permission to write in C:\temp ad .NET 4.6.1 console application is able to write in that folder and it's in the same project.
The internal log file is empty and the Unit test project runs the test successfully.
I have no clue of what is happening. No error is thrown now.
Any suggestion to debug the issue is welcome.
An ISSUE on GitHub is already opened.
HERE is a test solution that I made to show you (PASSWORD: logging123). Now that I've updated to Nlog 4.5 you will see that the .NET framework solution throws an error trying to get an old version of Nlog (that I've never referenced) and that .NET Core unit test solution works but doesn't produce any file.

I was experiencing the same issue though I was running .NET 4.7. I updated my NLog package from 4.4.12 to 4.5.0-rc04 and it worked. Knowing its pre-release you may want to be cautions about putting it on live environment though.

Your zipped solution is password protected, so now it is just me guessing, but it looks like you are using app.config to hold nlog.config.
Pretty sure app.config are not being used by NetCoreApps. Try to put your Nlog-config in a separate file called nlog.config and make sure it is Copy Always (In Visual Studio File Properties).

Related

Logging With NLog In Azure WebJobs

I've got an NLog configuration which works just fine for my web app (ASP.NET Core).
Now I'm trying to add NLog to my webjobs, but I can't figure out how to do it.
In Program.cs within the webjob project, I need to somehow inject IHostingEnvironment and ILoggerFactory (Both of which I inject into the StartUp constructor of the web app).
Once I know how to do that, I should be able to finish off the configuration.
If that's not possible, what alternatives do I have?
I'm not keen to use the TextWriter class passed into the webjob methods, as I imagine it would be difficult to extract the logs and route them to where I ultimately want it to go.
Following are steps of using NLog in WebJob.
Step 1, install NLog.Config package for your WebJob.
Install-Package NLog.Config
Step 2, add rules and targets to NLog.config files. Following is the sample of writing logs to a file.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile" xsi:type="File" fileName="file.txt" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logfile" />
</rules>
</nlog>
Step 3, get logger instance using LogManager class.
private static Logger logger = LogManager.GetLogger("MyLog");
Step 4, after got the logger instance, you could write log using following code.
logger.Trace("Sample trace message");
logger.Debug("Sample debug message");

NLog with DNX Core 5.0

I am attempting to implement NLog logging using ASP.Net 5 and MVC 6. Be default, both DNX 451 and DNX Core 50 are included in the project template.
I am attempting to implement NLog Logging by following the example here.
However, in the sample app, there is the following line -
#if !DNXCORE50
factory.AddNLog(new global::NLog.LogFactory());
#endif
And if I run the app, this line never gets hit because the mvc application has dnx core 50 installed by default.
Is there any loggers that are available for DNX Core 50? If not, what purpose does dnx core serve in the default mvc app - is it actually needed?
Edit: If I remove the #if !DNXCORE50.... line above, I get a the following error -
DNX Core 5.0 error - The type or namespace name 'NLog' could not be found in the global namespace'
DNX Core 5.0 is only necessary if you want the cloud-optimized cross-platform version of the .Net framework; if you still plan on using the MVC app within only a Windows environment, you can remove your dnxcore50 framework reference from your project.json.
NLog for .NET Core (DNX environment) is currently available in version 4.4.0-alpha1.
Steps:
Create NLog.config
<?xml version="1.0" encoding="utf-8" ?>
<targets>
<target xsi:type="ColoredConsole" name="ToConsole" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="ToConsole" />
</rules>
Load and parse configuration
private static ILogger _logger;
public static void LoggerSetup()
{
var reader = XmlReader.Create("NLog.config");
var config = new XmlLoggingConfiguration(reader, null); //filename is not required.
LogManager.Configuration = config;
_logger = LogManager.GetCurrentClassLogger();
}
public static void Main(string[] args)
{
LoggerSetup();
// Log anything you want
}
When dealing with the MVC tooling in MVC6 (dnx stuff), the answer to this is very fluid.
In order to get NLog to work with my web app, I had to do a couple steps:
-> Big thanks to two NLog discussions(here and here)
I just needed to add the configuration setup in my Startup.cs's constructor:
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
// Set up logging configuration
// from: https://github.com/NLog/NLog/issues/641
// and: https://github.com/NLog/NLog/issues/1172
var reader = XmlTextReader.Create(File.OpenRead(Path.Combine(builder.GetBasePath(),"NLog.config"))); //stream preferred above byte[] / string.
LogManager.Configuration = new XmlLoggingConfiguration(reader, null); //filename is not required.
log.Info("NLogger starting");
Configuration = builder.Build();
}
I consider this a bit of a stop-gap as Microsoft is introducing a new Logging interface (that I hope will end up being like SLF4J.org is in Java). Unfortunately, documentation on that is a bit thin at the time I'm writing this. NLog is working diligently on getting themselves an implementation of the new dnx ILoggingProvider interface.
Additional information about my project setup
My NLog.config file is located in the project root folder, next to
the project.json and appsettings.json. I had to do a little digging
inside AddJsonFile() to see how they handled pathing.
I used yeoman.io and their aspnet generator to set up the web project.
Version of NLog, thanks to Lukasz Pyrzyk above:
"NLog": "4.4.0-alpha1"

Configuration exception thrown when ServiceStack RegisterLicense method is called

When invoking this method, Licensing.RegisterLicense(licenseKey);, I get a initialization exception with the following inner error:
Message=Unrecognized configuration section DbProviderFactories. (C:\Actevis\Development\Actevis.Cloud\SqlLiteTestBed\bin\Debug\SqlLiteTestBed.vshost.exe.Config line 16)
Here is the offending config section:
<DbProviderFactories>
<remove invariant="System.Data.SQLite" />
<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
</DbProviderFactories>
I have tried adding an appsetting section to the app.config file but the same error still appears. Since the DbProviderFactories are not present in the app.config file I assume that the section is injected by ServiceStack.
I am trying to use ServiceStack.Ormlite.SQLite32. This is the nuget package that was installed. I have copied the license file a few times to make sure that there was not problem there.
Thanks
Thanks for your reply. I was able to figure out what was happening:
When installing the ServiceStack.Ormlite.Sqlite32 package, Entity framework and EntityFramework for SQLServer is also installed. There seems to be an issue when using Sqlite and EntryFramework for Sql Server together. I deleted all the entity framework related DGG's from the project and removed the sections from the app.config file. This has fixed the problem.
The issue is that you're Web.config is invalid and the error gets thrown when first trying to access the Web.config, which is what ServiceStack does when it looks for the servicestack:license app setting.
Note: the <DbProviderFactories> should be declared inside <system.data> tags:
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite" />
<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
</DbProviderFactories>
</system.data>
This was caused by the Web.config.transforms in the dependent System.Data.SQLite.x86 package. This could also be a bug in NuGet's web.config.transform as the rule says to add it under <system.data>...</system.data> but it's being added to the top-level creating an invalid Web.config configuration.
The entire config isn't needed for OrmLite so can be removed. I've also reached out to the SQLite maintainer to notify him about this issue so hopefully will be resolved in future issues.
Whilst I'm looking at making changes to OrmLite's Sqlite packages to embed the dlls and remove the dependency to the Sqlite packages that's causing this error.

log4net config settings

I am into the development of a core dll where I have a class library.I want to use log4net to enable logging for exceptions. I have an app.config file in the class library where i have given the settings for the log4net.However when I test the class library the log4net does'nt create logs until i add the app.config in the calling project inspite of the fact that i had added [assembly: log4net.Config.XmlConfigurator(Watch = true)] in the class libary's assemblyinfo.cs and I am using log4net.ILog logger = log4net.LogManager.GetLogger(typeof(ErrorHandler)) where ErrorHandler is the name of my class library's class where log4net's calling functions are handled.Any ideas on what is going wrong?
Secondly, what I want to acheive is the users of my dll will just pass the location where they want to create logs and whether they want to create logs in event viewer or log files from their app.config? They will not handle any other setting of log4net.
Any suggestions or code snippets for the first issue and the second problem?
Only the "main" app.config is active for a .Net application. Your library config file is simply ignored. Either you transfer your settings to the main config file or you use an external config file for log4net. You configure it then for instance like this (assuming you call it log4net.config):
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
Please note that the structure of the config file is a bit different:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="YourAppender" type="..." >
....
</appender>
<root>
<level value="ALL" />
<appender-ref ref="YourAppender" />
</root>
</log4net>
As for your second problem: I am not sure how flexible this has to be. Is it just switching from file appender to event log appender? Depending on your answer you may consider two prepare to configuration files (e.g. file.log4net and eventlog.log4net) and read the configuration as needed (in that case you cannot use the attribute: you call the Configure() method directly) or if your requirements are more complex you might even end up configuring log4net programatically.

Asp.net application error running with Sitecore 6.4.1

I have Sitecore as site root (which is running ok) and under it I need to have a bunch of asp.net applications running.
So far, created a virtual directory for the child application, turned it into an app. But as soon as I browse the child app it comes with this error message.
Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS0246: The type or namespace name 'Sitecore' could not be found (are you missing a using directive or an assembly reference?)
Source Error:
Line 3264: </providers>
Line 3265: </roleManager>
Line 3266: <profile defaultProvider="sql" enabled="true" inherits="Sitecore.Security.UserProfile, Sitecore.Kernel">
Line 3267: <providers>
Line 3268: <clear/>
It seems that the child asp.net app is inheriting Sitecore settings which are coming from Sitecore web.config.
Any ideas?
This should be possible. You'll have to author a web.config for that non-Sitecore application in virtual directory, and overwrite the sections under <system.web> and <system.webserver> which reference Sitecore classes. This includes:
httpModules / httpHandlers (for these you should "remove all" and add those of that web app)
security section (put the default ASP.NET provider classes back)
in Sitecore main web.config add the path of this web app to IgnoreUrlPrefixes setting to let Sitecore know it should not handle requests to those
It might be something else, but you should get the general idea.
This answer is similar to Yan, but is different enough for a separate answer. Hope it helps.
Go into IIS and select the Child Application. Select Modules. Remove all the Sitecore related modules that are present. Don't worry, the parent Sitecore app will still retain these modules.
When you do this, you are actually changing the child app web.config, so you will see the elements removed in the web.config file like so.
<remove name="SitecoreConfigWatcher" />
<remove name="SitecoreHttpModule" />
You also may have to clear out some other inherited settings.
<profile enabled="false"><providers><clear/></providers></profile>
<roleManager enabled="false"><providers><clear /></providers></roleManager>

Resources