NLog no log output from a referenced project - c#

I am using NLog 4.5.11 in one Visual Studio 2017 solution. It has the nlog.config in the start up project, but the actual logging required is from another project, where NLog is referenced (but no nlog.config exists). Running this solution works fine, the NLog logs are being produced where I expect.
The second VS solution uses (references) both the start up project and the one with the logging. One note on this project is that it is an Excel Add-on. When I run (debug from VS) this second solution, I do NOT get the NLog logging that should have been triggered via the referenced projects' code and NLog logging. I do not get any errors, exceptions, or error files etc.
I have tried also installing the NuGet packages for NLog to the second solution. I also tried adding a copy of the nlog.config to it. I have looked in the build directory and the NLog dlls and config file are being copied there. I have also tried enabling the throwExceptions="true" and internalLogLevel="Trace".
I have been looking on SO and elsewhere, but I cannot find a solution or even how to debug it. All that ever happens is simply no output, which is really frustrating.
NLog.config
<?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"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="true"
internalLogLevel="Trace" internalLogFile="c:\temp\nlog-internal.log">
<variable name="appName" value="FSIS" />
<variable name="logDir" value="c:\temp\Rbnz.Fsis.Logging" />
<variable name="logDirArchive" value="c:\temp\Archive\Rbnz.Fsis.Logging" />
<targets async="true">
<target xsi:type="File"
name="default"
layout="${longdate} - ${level:uppercase=true}: ${message}${onexception:${newline}EXCEPTION\: ${exception:format=ToString}}"
fileName="${logDir}\${shortdate}.log"
keepFileOpen="false"
archiveFileName="${logDirArchive}\${shortdate}.{##}.log"
archiveNumbering="Sequence"
archiveEvery="Day"
maxArchiveFiles="30"
/>
</targets>
<rules>
<logger name="*" writeTo="default" minlevel="Debug" />
</rules>
</nlog>
Usage inside the code of the referenced project:
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
and later on, inside a method:
logger.Info("Start: CompileSeries()");
logger.Info("Done: CompileSeries()");
I expected that if NLog logging works for a project, then including that project as a reference in another project (in another solution), would trigger the same logging. Obviously I'm incorrect in this assumption.

Based on what you wrote, you have a First Solution that has two projects--a startup project that configures a logger object. That solution has a second project that references the startup project's logger object. Fine.
Now you have a Second Solution. In this solution, you simply reference the First Solution's startup project assembly and the First Solution's second project. Your Second Solution has its own project that's trying to access the logger exposed by the First Solution's referenced projects.
This issue is that your First Solution actually executes its startup project. Your Second Solution does not execute it--it simply references it. Therefore, your logger object isn't getting properly initialized by NLog.
The solution (generically) is to ensure that your logger object is initialized in your Second Solution just as it's initialized in your First Solution. If you want more specific guidance, show specifics as to how your First Solution's startup project initializes the logger object and I should be able to help you replicate that logic in the Second Solution.
Your conclusion that you cannot log from another solution is incorrect. It's all about proper object initialization.
I hope this helps.

Related

Using NLog with MSTest (.NET Core 2.0)

I have a solution I built using .NET 4.7. This solution has two projects:
A class library (.NET 4.7.2)
A Unit Test Project (.NET Framework)
I'm trying to migrate this solution to use .NET Standard | Core.
I have successfully transferred the class library to a .NET Standard 2.0 project. I have also transferred the Unit Test Project to a .NET Core 2.0 mstest project. Everything compiles. I can run my tests as expected. However, no logs are getting written via NLog.
In my .NET 4.7 version of the solution, when I ran the unit tests, an actual log file was written via NLog. However, in the new .NET Standard | Core implementation, this log file is not getting written. I have the following two files in my mstest project:
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>
nlog.config
<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogFile="c:\temp\console-example-internal.log"
internalLogLevel="Info" >
<targets>
<target name="myLogs" xsi:type="File" deleteOldFileOnStartup="true" fileName="${basedir}/logs/MyLogs.json" createDirs="true" keepFileOpen="true" encoding="utf-8" layout="${message}" />
<target name="traceLogs" xsi:type="File" deleteOldFileOnStartup="true" fileName="${basedir}/logs/trace.log" createDirs="true" keepFileOpen="true" encoding="utf-8" layout="[${longdate}] ${message}${exception:format=ToString}"></target>
</targets>
<rules>
<logger name="MyLogger" minlevel="Info" writeTo="myLogs" />
<logger name="TraceLogger" minlevel="Trace" writeTo="traceLogs" />
</rules>
</nlog>
In my mstest project, I've also added references to:
Microsoft.Extensions.DependencyInjection
NLog
NLog.Extensions.Logging
I followed the steps outlined here. Except, I didn't do anything beyond step 2. Do I need that stuff for a mstest project? If so, where? It seems like a lot of additional stuff for something that was already working.
When running unit tests, it's hard to find the nlog.config as implementations will move the DLLs (and most of the time not the nlog.config) to temporary folders.
It's recommend to configure NLog from code in an unit test project. (how-to here)
Another option is to load the NLog config file manually. You need to provide the path to nlog.config to the XmlLoggingConfiguration contructor:
LogManager.Configuration = new XmlLoggingConfiguration(pathToNLogConfig);
Off topic but related:
In the unit test it's recommend to write the eventlogs not to a file, but in memory, e.g. the Memory target. It makes the unit test more robust.

Configure SonarLint Analyzers properties

I've added the SonarLint C# Roslyn analyzer to a project (via the SonarAnalyzer for C# NuGet package) in Visual Studio. Is it possible to configure how the analyzer rules operate?
For example, the CodeComplexity analyser appears to have a Threshold property to which I'd like to set a different value.
I've found a couple of references to a SonarLint.xml file, but creating such a file and locating it at the solution level doesn't seem to have had any effect.
Here's the content of the SonarLint.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<AnalysisInput>
<Rules>
<Rule>
<Key>S3776</Key>
<Parameters>
<Parameter>
<Key>threshold</Key>
<Value>30</Value>
</Parameter>
</Parameters>
</Rule>
</Rules>
<Files>
</Files>
</AnalysisInput>
Include the SonarLint.xml file in the project and set the Build Action file property to AdditionalFiles.
Diving in to the SonarLint source code led me to this class, which makes use of the AnalyzerOptions class. This then led me to the documentation in the Roslyn repository about Additional Files.

XAML access user directory [duplicate]

My NLog targets is like this:
<targets>
<target xsi:type="Console" name="console"
layout="${longdate}|${level}|${message}" />
<target xsi:type="File" name="ErrorLog" fileName="${basedir}/error.txt"
layout="${longdate}
Trace: ${stacktrace}
${message}" />
<target xsi:type="File" name="AccessLog" fileName="${basedir}/access.txt"
layout="${shortdate} | ${message}" />
</targets>
But this causes problems if the user isn't an admin on their machine, because they will not have write access to "Program Files". How can I get something like %AppData% to NLog instead of BaseDir?
You're looking for the NLog special folders.
Example:
...fileName="${specialfolder:folder=ApplicationData}/Program/file.txt"...
Oren's answer should be the right answer. However, for the life of me I couldn't get it to work with my .NET 4.0 website using nLog 2.0.0.0. I ended up using simply
fileName="${basedir}app_data\logs\${shortdate}.log"
${specialfolder:ApplicationData} also works
The previous answers helped solve the problem I was having, but a couple of years later and the solution is now somewhat different under v4.3. The directory and filename are combined with the path.
#theGecko's link is still current for the syntax, but the page is deficient of an example:
https://github.com/nlog/NLog/wiki/Special-Folder-Layout-Renderer
The following example would write the file myLog.log to the current users application data roaming directory C:\USers\current.user\AppData\Roaming\My\Path\Somewhere:
fileName="${specialfolder:dir=My/Path/Somewhere/:file=myFile.log:folder=ApplicationData}"
For logging to the project directory:
While the previous answers work for the original question, searching for how to log to the project APP_DATA directory leads to this question. And while bkaid's answer works for ASP.NET and for using the APP_DATA folder specifically, for .NET Core and .NET 5 the solution is a bit different, because that motif has been abandoned in favor of defining a wwwroot folder for only those things which should be served, and the remainder being private. The answer for .NET Core/5, then, is to write to the solution root directory:
First, ensure the NLog.Web.AspNetCore assembly is added to nlog.config:
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
Then use one of the layout renderers provided by that extension, in this case ${aspnet-appbasepath} which references the solution root directory:
<targets>
<target name="file"
type="File"
xsi:type="File"
fileName="${aspnet-appbasepath}/log/${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}"/>
</targets>
This will write the file to <solution folder>/log/2021-07-01.log, which will never be served by the public-facing website. Other layout renderers provided by this assembly are listed on the NLog website.

web.config transform from web.template.xml not working

I'm trying to get web.config transformations working as described here. We've used this method on other projects and it works without issue, but not on this new project.
Here's what I've tried testing without success
Changing name of wpp.targets file in case I got the project name wrong. I know the current one I'm using works since it's the only one that causes web.config to be rebuilt from web.template.xml this transform works. Only the sub templates don't work.
Tried with xdt:Locator="Match(name)"
Tried .config extension vs .xml, our other projects where this works use .xml
Configuration manager is set to use the "Test" configuration for the project I'm working on.
web.template.Test.xml has xdt:Transform="Replace" for the section I want to replace
web.template.xml has the placeholder
Tried removing the "CopyWebTemplateConfig" section from wpp.targets as suggested on the stack question linked below. Our other projects have this and the "PropertyGroup" section commented out and I've tried both combinations.
I've read through the above link multiple times and this related stack question, but can't see what the problem is.
Note The publish transform does work in a way. It creates a web.template.xml file that contains the values from web.template.Test.xml, but does not create a web.config.xml as the wpp.targets instructs. So this is more of an issue with getting the build transform working it seems.
Anyone have an idea of what's missing?
wpp.targets
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Make sure web.config will be there even for package/publish -->
<Target Name="CopyWebTemplateConfig" BeforeTargets="Build">
<Copy SourceFiles="web.template.xml"
DestinationFiles="web.config"/>
</Target>
<PropertyGroup>
<PrepareForRunDependsOn>
$(PrepareForRunDependsOn);
UpdateWebConfigBeforeRun;
</PrepareForRunDependsOn>
</PropertyGroup>
<!-- This target will run right before you run your app in Visual Studio -->
<Target Name="UpdateWebConfigBeforeRun">
<Message Text="Configuration: $(Configuration): Web.template.$(Configuration).xml"/>
<TransformXml Source="web.template.xml"
Transform="web.template.$(Configuration).xml"
Destination="web.config" />
</Target>
<!-- Exclude the config template files from the created package -->
<Target Name="ExcludeCustomConfigTransformFiles" BeforeTargets="ExcludeFilesFromPackage">
<ItemGroup>
<ExcludeFromPackageFiles Include="web.template.xml;web.template.*.xml"/>
</ItemGroup>
<Message Text="ExcludeFromPackageFiles: #(ExcludeFromPackageFiles)" Importance="high"/>
</Target>
</Project>
web.template.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=152368
-->
<configuration>
<configSections>
<sectionGroup name="TestSettings"></sectionGroup>
....
</configSections>
....
<TestSettings>
</TestSettings>
....
</configuration>
web.template.Test.xml
<?xml version="1.0"?>
<!-- For more information on using transformations
see the web.config examples at http://go.microsoft.com/fwlink/?LinkId=214134. -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<TestSettings xdt:Transform="Replace">
...
</TestSettings>
</configuration>
MSBuild output
Target "UpdateWebConfigBeforeRun: (TargetId:143)" in file "C:\...\Project.wpp.targets" from project "C:\...\Project.csproj" (target "PrepareForRun" depends on it):
Task "Message" (TaskId:93)
Configuration: Test: Web.template.Test.xml (TaskId:93)
Done executing task "Message". (TaskId:93)
Task "TransformXml" (TaskId:94)
Transforming Source File: Web.template.xml (TaskId:94)
Applying Transform File: Web.template.Test.xml (TaskId:94)
Executing Replace (transform line 5, 18) (TaskId:94)
on /configuration/TestSettings (TaskId:94)
Applying to 'TestSettings' element (source line 121, 4) (TaskId:94)
Replaced 'TestSettings' element (TaskId:94)
Done executing Replace (TaskId:94)
Output File: web.config (TaskId:94)
Transformation succeeded (TaskId:94)
Done executing task "TransformXml". (TaskId:94)
Done building target "UpdateWebConfigBeforeRun" in project "Project.csproj".: (TargetId:143)
I had installed StyleCop and that was doing the overwrite for me.
So I uninstalled it and the issue was resolved.
Funny is that I re-installed the StyleCop and the transform was still working!
Also at some points I noticed that I should remove the CopyWebTemplateConfig target section as well.
I've got a solution to my problem, but not sure what the cause is, so not sure if this will solve it in other cases.
I reviewed the output of the MSBuild diagnostic and noticed that towards the end there was another section that copied web.template to web.config. Note that this is after the UpdateWebConfigBeforeRun target already ran and made its updates from the sub template transform file to web.config. It looked like this last step was overriding the web.config with the transform I wanted.
I wasn't sure where this last set of copy instruction was coming from, so I did a search for all files on my PC looking for other wpp.target files. I found another one in Slow Cheetah's extensions folder and saw some section up top that was setting a property "transformOnBuild" to false.
Thinking there was a conflict with SlowCheetah, I uninstalled it and the transformations started working as expected. This was still a bit odd since the other solutions worked with SlowCheetah enabled. On a whim I re-installed SlowCheetah and the transformation continued to work as expected.
So my solution ended up being a re-installation of SlowCheetah. I'm still confused about what the cause of this issue was, so if anyone else posts an answer to this I'll give them the bounty.
I've had a similar issue last week.
Turns out that whenever you add a project to a solution in VS 2010 the right project configuration doesn't get applied all the time.
So you think you have a configuration active but another is actually active on that project, thus the transformation you expect doesn't get applied.
Check the steps in last comment of this issue: Custom solution configuration not showing up in Visual Studio 2010
"I know the current one I'm using works since it's the only one that causes web.config to be rebuilt from web.template.xml this transform works. Only the sub templates don't work."
Does this mean, transformation works but TestSettings section alone does not get transformed?
Can you share build output with msbuild with verbosity set to diagnostic / detailed?
I wrote a blog post about this subject. I use it everyday in our web application. I wrote the blog post because the feature in slowcheetah isn't ready yet.
http://www.locktar.nl/general/use-config-transforms-when-debugging-your-web-application/

NLog does not create a log file

I am trying to add logging to an application running on mobile device with Windows Mobile 6.1. � .NET Compact framework 3.5. using NLog.
I have the appropriate version of the NLog distribution installed.
However no log files are being created.
Here is my NLog.config 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=".\Neolant.ASRM.Terminal.log" layout="${longdate}|${level}|${message}|${exception}" autoFlush="true"/>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logfile" />
</rules>
</nlog>
And here is the test code I was using:
public static void Main()
{
try
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
var logger = NLog.LogManager.GetLogger("UpperLevel");
logger.Info("test test test.");
try
{
throw new Exception("Unexpected!");
}
catch (Exception e)
{
var logger = NLog.LogManager.GetLogger("UpperLevel");
logger.WarnException("An exception occured.", e);
}
throw new Exception("Suddenly!");
}
finally
{
NLog.LogManager.Flush();
}
}
private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
var logger = NLog.LogManager.GetLogger("UpperLevel");
logger.FatalException("Application closed due to exception.", unhandledExceptionEventArgs.ExceptionObject as Exception);
NLog.LogManager.Flush();
}
I had this problem turned out that my log file was not being copied to my build directory. The NLog github page had the answer. (I've reformatted the paragraph a little for better readability.)
https://github.com/NLog/NLog/wiki/Logging-troubleshooting
NLog cannot find the configuration file. This can happen when the NLog.config file is configured with Build Action = None or Copy to Output Directory = Do not copy in Visual Studio.
Set Build Action = Content and "Copy to Output Directory = Copy if newer to fix this)
The log file was being created - but not in the application directory.
Using ${basedir} layout renderer as part of the file name proved to be a solution.
from nlog troubleshooting guide
Please check Nlog.config file properties: Copy to output directory should be Copy always
Please view image link https://i.stack.imgur.com/AlUG5.png
In case the response marked as answer is not all that clear you can check the example
<targets>
<target xsi:type="Console" name="console"
layout="${longdate}|${level}|${message}" />
<target xsi:type="File" name="ErrorLog" fileName="${basedir}/error.txt"
layout="${longdate}
Trace: ${stacktrace}
${message}" />
<target xsi:type="File" name="AccessLog" fileName="${basedir}/access.txt"
layout="${shortdate} | ${message}" />
</targets>
Taken from here using AppData location in NLog
My issue was permission related, the log file needs to allow the process to write to it, without write permissions you'll get no file.
Here's how to fix it for websites in IIS:
Right click on your folder in windows explorer and select properties
Choose the security tab
Click edit
Click add
In the textbox type 'IIS AppPool\YourAppPoolName' replace YourAppPoolName with the actual name of the application pool your site runs under
Click Check names
Click OK
Security footnote:
From a security aspect the best practice is to use ApplicationPoolIdentity as it is a dynamically created, unprivileged account.
more reading here: https://learn.microsoft.com/en-us/iis/manage/configuring-security/application-pool-identities
From the nlog troubleshooting guide:
https://github.com/NLog/NLog/wiki/Logging-troubleshooting
If you know that your config file is definitely being found, temporarily replace the section of your NLog.config file with the following and try it.
This rule will match any logger you've created, and if it works, it will put a log.txt file in the 'base directory' - which is the 'bin' directory for your test instance e.g. if you're running in debug mode, you'll see log.txt in your bin > debug folder. (This isn't explained very clearly in the troubleshooting guide).
If this works then you know that the problem is with your rules:
<nlog throwExceptions="true">
<targets>
<target name="file" type="File" fileName="${basedir}/log.txt" />
</targets>
<rules>
<logger name="*" minLevel="Trace" writeTo="file" />
</rules>
</nlog>
I found that only name="file" worked for the target - other values didn't
Adding the throwExceptions="true" as above will also ensure that you get useful error messages when you're debugging.
In my case, I've missed the rules after defining the rules works like a charm
<rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />
<!-- add your logging rules here -->
<!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
</rules>
Spent a lot of time on this issue. This was my problem. I was using a Setup project to install a Windows Service with an MSI. I had to manually add NLog.config to the output of the installer to make sure it got copied to the install directory of the service
for simple troubleshooting purposes, launch VisualStudio to run as administrator. This will help to sort out permissions to create log files while debugging.
Also use createDirs=true in each of the target section to automatically create missing folders in the file path provided in target section.
I also faced the same issue, finally i have solved it. I had a web application, where i want to implement NLog. Please find the following steps to implement NLog.
Step 1:- Go to NuGet packages manager and install following packages.
Step 2:- Open Web.config and add those following line
<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"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="D:\projects\NlogWeb\nlog-internal.log">
<targets>
<target name="console" xsi:type="ColoredConsole" layout="${message}" />
<!--Write logs to File-->
<target name="file" xsi:type="File" fileName="D:\projects\NlogWeb\ErrorLogFile.log" layout="--------------------- ${level}(${longdate})${machinename}-------------------- ${newline}
Exception Type:${exception:format=Type}${newline}
Exception Message:${exception:format=Message}${newline}
Stack Trace:${exception:format=Stack Trace}${newline}
Additional Info:${message}${newline}" >
</target>
</targets>
<rules>
<logger name="*" minlevel="trace" writeTo="file" />
</rules>
</nlog>
Step 3:- Now the last configuration to call in your .cs file.
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace NlogWeb
{
public partial class Home : System.Web.UI.Page
{
private static Logger logger = LogManager.GetCurrentClassLogger();
protected void Page_Load(object sender, EventArgs e)
{
try
{
throw new Exception("Divide By Zero Exception", new DivideByZeroException());
}
catch (Exception ex)
{
logger.Error(ex.Message);
}
}
}
}
We have done. Now execute your code and enjoy logging.
To fix this, I had to run my application in administrator mode. I suspect windows had an update that suddenly prevented exe's from creating a (log) file, since the exe could always prevously log without admin rights.
In my case I had to load the NLog.config file manually in the code since it wasn't found automatically. Loading the configuration must be done before logs are generated.
LogManager.LoadConfiguration(#"D:\doe\ConsoleApp2\ConsoleApp2\NLog.config");
After that I got log files and console output.
in my case, a WebAPI application, I solved the problem by giving modify permissions to IIS_IUSRS the modify permission for the website folder C:\inetpub\wwwroot\my_website

Categories