how to set isdebugenabled in NLog - asp.net

I try to find a way to set isdebugenabled false or true in configuration file,
so I can turn it on or off whenever I need. Thanks !

Using a really simple logging setup
<targets>
<target xsi:type="File"
name="debug"
fileName="c:\temp\debug.txt"
layout="${longdate} ${uppercase:${level}} ${message}"
/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="debug" />
</rules>
And an equally simple code sample
class Program
{
static void Main(string[] args)
{
var logger = new NLog.LogFactory().GetCurrentClassLogger();
if (logger.IsDebugEnabled)
{
logger.Debug("this is a debug message");
}
logger.Debug("this is another debug message");
}
}
When minLevel is set to Debug or Trace, both logger.Debug statements will write to the log. If you raise minLevel to a higher level (Info, Warn, Off) neither statement will be written to the log. logger.Debug checks IsDebugEnabled (which is inferred from the log level).
You can certainly get a performance increase (in cases where you are going to be logging calculated values and not just strings) by checking IsDebugEnabled, and changing minLevel for the logger is the way to toggle this.

Related

NLog ApplicationInsightsTarget unable to read application insights key from appsettings.json

I am trying to read the application insights instrumentation key from appsettings.json file in my ASP.NET Core 3.1 Web Application but all my tries went in vain so far as the target is still showing as unconfigured.
If I add the key directly in ApplicationInsightsTarget, then it is working fine.
Here is the content of appsettings.json file:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"AppInsightsKey": "Instrumentation-Key-From-Azure-Application-Insights-Resource"
}
Here is the content of 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"
autoReload="true"
throwConfigExceptions="true"
internalLogLevel="info"
internalLogFile="c:\temp\internal-nlog-AspNetCore3.txt">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="Microsoft.ApplicationInsights.NLogTarget" />
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
<target xsi:type="Console" name="lifetimeConsole" layout="${configsetting:item=AppInsightsKey} ${level:truncate=4:lowercase=true}: ${logger}[0]${newline} ${message}${exception:format=tostring}" />
<target name="aiTarget" xsi:type="ApplicationInsightsTarget"
layout="${date:format=yyyy-MM-dd HH\:mm\:ss}: [LOCAL] - ${level} - ${message}${exception:format=ToString}">
<instrumentationKey>${configsetting:item=AppInsightsKey}</instrumentationKey>
<contextproperty name="threadid" layout="${threadid}" />
</target>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Trace" writeTo="lifetimeConsole" />
<logger name="*" minlevel="Trace" writeTo="aiTarget" />
</rules>
</nlog>
As you can see from above, I was trying to grab the application insights key from appsettings.json file by ${configsetting:item=AppInsightsKey}, but in all occasions it's coming as empty.
I've tried with ${configsetting:name=AppInsightsKey} , which didn't help either.
This is the program.cs file content
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Web;
using System;
namespace ASPNETCoreWebAppNLogAppInsightsDemo
{
public class Program
{
public static void Main(string[] args)
{
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("init main");
CreateHostBuilder(args).Build().Run();
}
catch (Exception exception)
{
//NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog(); // NLog: Setup NLog for Dependency injection
}
}
Then I've tried to embed the key in the console target layout, just to ensure nlog is able to read it correctly, which to my surprise is working perfectly fine. So, looks like the issue is with ApplicationInsightsTarget only.
I know, I can pull it from Environment variables and hence in Azure App service it is not required to read from appsettings.json, but I would like to understand about this behavior since already spent too much time fixing myself :-)
Any help will be appreciated.
Try replacing the old code:
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
With this new code:
var logger = LogManager.Setup()
.LoadConfigurationFromAppSettings()
.GetCurrentClassLogger();
The new code will load the appsettings.json, and sure that ${configsetting} are available during initialization of NLog Targets.

Manage logging configuration with NLog in .NET Core 3

I'm using NLog in a .NET Core 3.1 worker service application.
Following the tutorial of NLog I inserted an nlog.config file to manage the configuration.
Now I'm confused because I have three points where I configure the logging:
In the code where I need to create a logger in a dependency injection context
// Other code...
services.AddScoped<IApplyJcdsCommandsJob, ApplyJcdsCommandsJob>(provider =>
{
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.ClearProviders()
.AddFilter("Microsoft", Microsoft.Extensions.Logging.LogLevel.Trace)
.AddFilter("System", Microsoft.Extensions.Logging.LogLevel.Trace)
.AddFilter("ApplyJcdsCommandsJob", Microsoft.Extensions.Logging.LogLevel.Trace)
//.AddConsole()
//.AddEventLog();
.AddNLog(configuration);
});
Microsoft.Extensions.Logging.ILogger logger = loggerFactory.CreateLogger<CommandsJob>();
return new CommandsJob(logger);
})
// Other code...
In appSettings.json
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace",
"System": "Trace",
"Microsoft": "Trace"
}
}
}
In NLog.config
The default config file produced by the nuget package installation:
<!-- a section of the config -->
<targets>
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="f" />
</rules>
<!-- ... -->
What I see is that if I remove the Nlog.config file, the log file will not be created.
Other changes seam to have no effect.
How are this configurations related?
What is the best way to switch on/off the logging and set the level?
People that decide to use NLog usually also want to disable all MEL-filtering to avoid the confusion with two filtering systems. So the NLog wiki-tutorial is targeted those users.
I guess people who are MEL-users first will probably just use new HostBuilder().CreateDefaultBuilder().Build() (Will setup everything with all guns enabled).
But if staying with the simple example, then you need to remove:
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
And add:
loggingBuilder.AddConfiguration(config.GetSection("Logging"));
So it looks like this:
serviceCollection.AddLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
loggingBuilder.AddConfiguration(config.GetSection("Logging"));
loggingBuilder.AddNLog(config);
})
ILoggingBuilder.AddConfiguration can be found at Nuget: Microsoft.Extensions.Logging.Configuration
AddNLog registers NLog like any other Microsoft Extension Logger (MEL) LoggingProvider (Similar to AddConsole).
This means NLog only gets log-output that has been "approved" by the MEL-ILogger. So any filtering configured in MEL will prevent logevents from reaching NLog.
NLog still has the ability to redirect based on Logger-names and LogLevel-severity to the wanted NLog-targets.
You can decide if you want to use MEL-Filtering or NLog-Filtering, or a combination of both. But if you just want to use "pure" NLog then just create an instance of NLog.Extensions.Logging.NLogLoggerFactory. It is a specialized ILoggerFactory that ignores MEL-Filtering-Configuration.
Btw. it is a little weird that you create an isolated LoggerFactory for each CommandsJob-instance. Would think that you would register the type in the dependency injection-framework, and let it inject constructor-parameters. See also this example:
https://github.com/NLog/NLog.Extensions.Logging/blob/master/examples/NetCore2/ConsoleExample/Program.cs
Where LoggerFactory is created with AddLogging(...) and where the Runner is registered in ServiceCollection for dependency-injection. When creating instance of Runner then dependency-injection will automatically provide ILogger as constructor-parameter.

NLog throws 'Target cannot be found' for any custom target running on Azure Web App

I've created two NLog custom targets on .NET Standard 2.0, and imported them into an existing ASP.NET 4.7.2 website.
nlog.config looks like this:
<?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"
autoReload="true"
internalLogLevel="Info"
internalLogFile="${basedir}/internal-nlog.txt"
throwExceptions="true"
throwConfigExceptions="true">
<extensions>
<add assembly="MyAssembly"/>
</extensions>
<targets async="false">
<target name="logconsole" xsi:type="Console" />
<target xsi:type="AzureTableTarget"
name="azureTable"
// some configs
/>
<target xsi:type="PostmarkLogTarget"
name="postmark"
// some configs
/>
</targets>
<rules>
<logger name="*" minlevel="Warn" writeTo="postmark" />
<logger name="*" minlevel="Info" writeTo="azureTable" />
<logger name="*" minlevel="Debug" writeTo="logconsole" />
</rules>
</nlog>
When the app starts locally, everything works fine. When it starts on the Azure App Service, I get this in the nlog internal log (and a big, fat error page):
2019-06-21 15:08:53.5719 Info Message Template Auto Format enabled
2019-06-21 15:08:53.6015 Info Loading assembly: MyAssembly
2019-06-21 15:08:53.6926 Info Adding target ConsoleTarget(Name=logconsole)
2019-06-21 15:08:53.7595 Error Parsing configuration from D:\home\site\wwwroot\NLog.config failed. Exception: NLog.NLogConfigurationException: Exception when parsing D:\home\site\wwwroot\NLog.config. ---> System.ArgumentException: Target cannot be found: 'AzureTableTarget'
at NLog.Config.Factory`2.CreateInstance(String itemName)
at NLog.Config.LoggingConfigurationParser.ParseTargetsElement(ILoggingConfigurationElement targetsElement)
at NLog.Config.LoggingConfigurationParser.ParseNLogSection(ILoggingConfigurationElement configSection)
at NLog.Config.XmlLoggingConfiguration.ParseNLogSection(ILoggingConfigurationElement configSection)
at NLog.Config.LoggingConfigurationParser.LoadConfig(ILoggingConfigurationElement nlogConfig, String basePath)
at NLog.Config.XmlLoggingConfiguration.ParseNLogElement(ILoggingConfigurationElement nlogElement, String filePath, Boolean autoReloadDefault)
at NLog.Config.XmlLoggingConfiguration.ParseTopLevel(NLogXmlElement content, String filePath, Boolean autoReloadDefault)
at NLog.Config.XmlLoggingConfiguration.Initialize(XmlReader reader, String fileName, Boolean ignoreErrors)
--- End of inner exception stack trace ---
2019-06-21 15:08:53.8489 Error Failed loading from config file location: D:\home\site\wwwroot\NLog.config Exception: NLog.NLogConfigurationException: Exception when parsing D:\home\site\wwwroot\NLog.config. ---> System.ArgumentException: Target cannot be found: 'AzureTableTarget'
at NLog.Config.Factory`2.CreateInstance(String itemName)
at NLog.Config.LoggingConfigurationParser.ParseTargetsElement(ILoggingConfigurationElement targetsElement)
at NLog.Config.LoggingConfigurationParser.ParseNLogSection(ILoggingConfigurationElement configSection)
at NLog.Config.XmlLoggingConfiguration.ParseNLogSection(ILoggingConfigurationElement configSection)
at NLog.Config.LoggingConfigurationParser.LoadConfig(ILoggingConfigurationElement nlogConfig, String basePath)
at NLog.Config.XmlLoggingConfiguration.ParseNLogElement(ILoggingConfigurationElement nlogElement, String filePath, Boolean autoReloadDefault)
at NLog.Config.XmlLoggingConfiguration.ParseTopLevel(NLogXmlElement content, String filePath, Boolean autoReloadDefault)
at NLog.Config.XmlLoggingConfiguration.Initialize(XmlReader reader, String fileName, Boolean ignoreErrors)
--- End of inner exception stack trace ---
at NLog.Config.XmlLoggingConfiguration.Initialize(XmlReader reader, String fileName, Boolean ignoreErrors)
at NLog.Config.XmlLoggingConfiguration..ctor(XmlReader reader, String fileName, Boolean ignoreErrors, LogFactory logFactory)
at NLog.Config.LoggingConfigurationFileLoader.LoadXmlLoggingConfiguration(XmlReader xmlReader, String configFile, LogFactory logFactory)
at NLog.Config.LoggingConfigurationFileLoader.LoadXmlLoggingConfigurationFile(LogFactory logFactory, String configFile)
at NLog.Config.LoggingConfigurationFileLoader.TryLoadLoggingConfiguration(LogFactory logFactory, String configFile, LoggingConfiguration& config)
2019-06-21 15:08:54.1153 Info Configuring from an XML element in D:\home\site\wwwroot\NLog.config...
2019-06-21 15:08:54.1457 Info Message Template Auto Format enabled
2019-06-21 15:08:54.1457 Info Loading assembly: MyAssembly
2019-06-21 15:08:54.1457 Info Adding target ConsoleTarget(Name=logconsole)
2019-06-21 15:08:54.3332 Info Adding target AzureTableTarget(Name=azureTable)
2019-06-21 15:08:54.3525 Info Adding target PostmarkLogTarget(Name=postmark)
2019-06-21 15:08:54.4120 Info Found 38 configuration items
2019-06-21 15:08:54.4738 Info Configuration initialized.
The second load comes about because I have code in global.asax.cs to register and configure the targets specifically. This code fires immediately after setting up AutoFac, and before anything tries to log to anywhere.
Running locally, the code proceeds through these steps in order, even in Release mode. It looks like it tries to log a message before configuration has completed when running on Azure.
Even if that were the case, both custom targets have default public constructors, so NLog should be able to instantiate them automagically. (Which is why I reload configs after setting up the targets.)
Two questions:
What is different about the Azure App Service that causes (or allows) NLog to jump the gun like that?
Short of removing nlog.config and setting up logging in code, how can I prevent this behavior from happening?
Target cannot be found: 'AzureTableTarget'
This mean that the target class 'AzureTableTarget' cannot be found in one of the assemblies and thus an instance cannot be create.
You need to tell NLog in which assembly the AzureTableTarget type could be found.
Something like this:
<extensions>
<add assembly="AssemblyNameWhereAzureTableTargetIsDefined"/>
</extensions>
What is different about the Azure App Service that causes (or allows) NLog to jump the gun like that?
Are the same assemblies available? So is the assembly with the AzureTableTarget published?
Short of removing nlog.config and setting up logging in code
For this case it doesn't matter if NLog is configured from file or from code.
how can I prevent this behavior from happening?
Always add all external NLog extensions to <extensions>
Last but not least, throwExceptions="true" isn't recommend for production! (If your logging breaks, do you really like that your application breaks?)
Found it. Wow.
I had this code hanging out in a .cs file:
public static readonly Logger Logger = LogManager.GetCurrentClassLogger();
On the App Service deployment, the static constructor of the class containing that line ran before App_Start had finished. On my local box, it didn't.
So I changed it to this:
public static Logger Logger => _logger ?? (_logger = LogManager.GetCurrentClassLogger());
private static Logger _logger;
...and everything works now. The Logger is only created when used, not just because ASP.NET wanted to instantiate static classes ahead of time.

Inline MS Build Task in separate AppDomain

End Goal:
I would like to have a custom build task that takes my compiled assembly, and extracts all instances of a particular attribute for automated documentation and uninstallation. (In this case the GUID attribute for a set of COM-visible types).
Problem:
After reading some examples, the prospect of using an Inline Build Task was rather tempting. However, my task needs to reflect across the built assemblies and extract certain meta-data from it (specifically attributes).
The catch is reflecting over the assembly will lock the output file until the AppDomain is unloaded, which in this case appears to be only when Visual Studio is closed. The result: the build can only once per session.
I see that there exists special build task classes, namely AppDomainIsolatedTask but I can find no examples or evidence that this class can be utilized for an inline task.
Question:
Is it possible to run an Inline Build task in a separate AppDomain? If so, then how?
Code Sample: (as short as possible)
<UsingTask TaskName="InDomainTask" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<Task><Code Type="Class" Language="cs"><![CDATA[
public class InDomainTask : Microsoft.Build.Utilities.Task
{
public override bool Execute()
{
Log.LogMessage("InDomainTask AppDomain.Id = " + System.AppDomain.CurrentDomain.Id);
return true;
}
}
]]></Code></Task>
</UsingTask>
<UsingTask TaskName="OutDomainTask" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<Task><Code Type="Class" Language="cs"><![CDATA[
[Microsoft.Build.Framework.LoadInSeparateAppDomain]
public class OutDomainTask : Microsoft.Build.Utilities.AppDomainIsolatedTask
{
public override bool Execute()
{
Log.LogMessage("OutDomainTask AppDomain.Id = " + System.AppDomain.CurrentDomain.Id);
return true;
}
}
]]></Code></Task>
</UsingTask>
<Target Name="AfterBuild" AfterTargets="Compile">
<InDomainTask />
<OutDomainTask />
</Target>
The build output of these is:
1> InDomainTask AppDomain.Id = 1
1> OutDomainTask AppDomain.Id = 1
No, it's not possible.
Inline tasks use the CodeTaskFactory to create the task, and if you take a look at the code on GitHub, you will see that after compiling an assembly that contains the code, an instance of the task is creating using Activator.CreateInstance. This means it is always created in the same AppDomain as MSBuild.
Compare that to pre-compiled tasks, which use the TaskLoader class to create an instance of the task, and that TaskLoader looks for the LoadInSeparateAppDomainAttribute on the task type and creates an instance in a separate AppDomain if it's found.
The easiest solution is to turn your inline code into a pre-compiled task. It's really easy to do:
Create a class library project
Reference Microsoft.Build.Utilities.
Create a class for your task.
Compile the project.
Replace your UsingTask element with one that specifies the assembly that contains the tasks.
Here's an example:
Your class library that contains the tasks:
public class InDomainTask : Microsoft.Build.Utilities.Task
{
public override bool Execute()
{
Log.LogMessage(System.AppDomain.CurrentDomain.FriendlyName);
return true;
}
}
public class OutDomainTask : Microsoft.Build.Utilities.AppDomainIsolatedTask
{
public override bool Execute()
{
Log.LogMessage(System.AppDomain.CurrentDomain.FriendlyName);
return true;
}
}
Your MSBuild file:
<UsingTask TaskName="InDomainTask" AssemblyFile="path\to\the\class\library.dll"/>
<UsingTask TaskName="OutDomainTask" AssemblyFile="path\to\the\class\library.dll"/>
<Target Name="AfterBuild" AfterTargets="Compile">
<InDomainTask/>
<OutDomainTask/>
</Target>
This outputs:
MSBuild.exe
taskAppDomain (in-proc)
Alternatively, you can run your job in separate MsBuild.exe process using Exec command and pass in same current targets file and needed properties.
<Project ToolsVersion="15.0" DefaultTargets="RunCodeFromTargetPath" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<RunCodeFromTargetPathAfterTargets>PrepareForRun</RunCodeFromTargetPathAfterTargets>
</PropertyGroup>
<Target Name="RunCodeFromTargetPath" AfterTargets="$(RunCodeFromTargetPathAfterTargets)">
<PropertyGroup Condition="'$(PlatformTarget)' == 'x64'">
<MsBuildFolderLocation >\amd64</MsBuildFolderLocation><!--support for x64 only assemblies -->
</PropertyGroup>
<Exec Command=""$(MSBuildBinPath)$(MsBuildFolderLocation)\MSBuild.exe" /target:RunCodeFromTargetPathInternal /p:TargetPath="$(TargetPath.Replace('\','\\'))" "$(MSBuildThisFileFullPath)"" />
</Target>
<Target Name="RunCodeFromTargetPathInternal">
<RunCodeFromTargetPathTask />
</Target>
<UsingTask
TaskName="RunCodeFromTargetPathTask"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<Task>
<Reference Include="$(TargetPath)" />
<Code Type="Fragment" Language="cs">
<![CDATA[
// your code here
]]>
</Code>
</Task>
</UsingTask>
</Project>

log4net with ASP.NET 3.5 problems

I'm having some trouble getting log4net to work from ASP.NET 3.5. This is the first time I've tried to use log4net, I feel like I'm missing a piece of the puzzle.
My project references the log4net assembly, and as far as I can tell, it is being deployed successfully on my server.
My web.config contains the following:
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler
, log4net"
requirePermission="false"/>
</configSections>
<log4net>
<appender name="InfoAppender" type="log4net.Appender.FileAppender">
<file value="..\..\logs\\InfoLog.html" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern
value="%d [%t] %-5p %c [%x] - %m%n" />
</layout>
</appender>
<logger name="_Default">
<level value="INFO" />
<appender-ref ref="InfoAppender" />
</logger>
</log4net>
I'm using the following code to test the logger:
using log4net;
using log4net.Config;
public partial class _Default : System.Web.UI.Page
{
private static readonly ILog log = LogManager.GetLogger("_Default");
protected void Page_Load(object sender, EventArgs e)
{
log.Info("Hello logging world!");
}
}
In my Global.asax, I'm doing the following:
void Application_Start(object sender, EventArgs e)
{
log4net.Config.XmlConfigurator.Configure();
}
At this point, I can't think of what else I might be doing wrong. The directory I'm trying to store the log in is writable, and even if I try different directories I get the same result: no file, no logs.
Any suggestions? :-)
Edit: I've tried several different formats for the path & name of the log file, some of which include "..\..\InfoLog.html", "InfoLog.html", "logs\InfoLog.html", etc, just in case someone is wondering if that's the problem.
Edit: I've added the root logger node back into the log4net section, I ommitted that on accident when copying from the samples. The root logger node looks like this:
<root>
<level value="INFO" />
<appender-ref ref="InfoAppender" />
</root>
Even with it, however, I'm still having no luck.
The root logger is mandatory I think. I suspect configuration is failing because the root doesn't exist.
Another potential problem is that Configure isn't being pointed to the Web.config.
Try Configure(Server.MapPath("~/web.config")) instead.
It sounds very much like a file permissions issue to me. If you specify a file name without any path, log4net will write to the root directory of the web application. Try that. Barring any success there, I'd recommend you enable internal log4net debugging by putting the following in your web.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
</configuration>
Then, deploy the app compiled in debug mode and run the visual studio remote debugger to see any errors that are thrown.
Iv just spent 3 hours trying to fix this problem is the end it was the web.config formatting.
I had this, and it didn't work:
<section name="SubSonicService" type="SubSonic.SubSonicSection, SubSonic" requirePermission="false"/>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler
, log4net"
requirePermission="false"/>
changing it to this fixed it:
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" requirePermission="false"/>
Annoying!!
Just for info: the file path must be formatted as follows:
<file value="..\\..\\logs\\InfoLog.html" />
A simple configuration tutorial from CodeProject
I don't have the Global.asx to run in .net 3.5
this is my code... I configure the log4net in a separate file log4net.config
// Configure log4net using the .config file
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
//My Web Services class name
private static readonly log4net.ILog log = log4net.LogManager.GetLogger("Service1");
i had the same (frustrating) problem. i moved the root to the top of the log4net config section and it all worked. Also, i too had root and a logger element, this resulted in two lines each time i made a call to the logger. i removed the logger element and simply keep the root and its working great.
How about creating the logger with the page's type, like this:
private static readonly ILog log = LogManager.GetLogger(typeof(_Default));
This is what i have in Global.ASX. Got it all working in asp.net 3.5
<%# Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
log4net.Config.XmlConfigurator.Configure();
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
log4net.LogManager.Shutdown();
}
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
}
void Session_Start(object sender, EventArgs e)
{
// Code that runs when a new session is started
}
void Session_End(object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
}
</script>

Resources