Using log4net RemoteSyslogAppender with .Net Core - .net-core

I am trying to use both a RollingFileAppender and RemoteSyslogAppender in a .Net Core app with log4net 2.0.8. Here's what my log4net.config file looks like:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<priority value="Debug" />
<appender-ref ref="FileAppender" />
<appender-ref ref="SyslogAppender" />
</root>
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\ProgressiveLogs\ProgLoggerNetCoreDemo.log" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="14" />
<maximumFileSize value="15000KB" />
<datePattern value="yyyyMMdd" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="SyslogAppender" type="log4net.Appender.RemoteSyslogAppender">
<remoteAddress name="Address" value="syslogServer" />
<remotePort name="Port" value="514" />
<layout type="ProgressiveLogging.Core.ProgLayout.ProgPatternLayout, ProgressiveLogging.Core">
<conversionPattern value="%json%newline" />
</layout>
</appender>
</log4net>
As you can see, I'm using a custom pattern for the syslog appender. When I run my .Net Core version of the app (which uses a .Net Standard 1.3 build of ProgressiveLogging.Core), I do get output to the RollingFileAppender file, but not the RemoteSyslogAppender. When I run my my test app using .Net 4.6.2 (using a .Net 4.0 build of ProgressiveLogging.Core) it outputs fine to both appenders.
I have found documentation online stating that the log4net RemoteSysLogAppender is supported for .Net Standard 1.3 (https://logging.apache.org/log4net/release/framework-support.html).
Has anyone else been able to get something similar to work (using RemoteSysLogAppender with .Net Core or .Net Standard)?
Added 2017-09-01: I have done further investigation and find that this boils down to a major difference in how UDP packets are built and sent between .Net 4.* and .Net Standard. .Net 40, which works, sends the UDP message all in one datagram (packet), whereas .Net Standard splits the message up into a bunch of packets, which packets appear to be delimited by the commas in our JSON message. Apparently, our syslog daemon can't understand such nonsense. I'm going to do some direct testing to see if I can make a difference in what gets sent via UDP to syslog.

After much more thorough investigation I have found that there is not a problem with log4net RemoteSyslogAppender. My problem was that I was formatting the JSON message that ultimately was sent by the System.Net.Sockets.UdpClient. The formatting added CRLFs to the string, which then the UdpClient delimited the message and fragmented on those CRLF boundaries. That was making no sense to Syslog. It was a very simple fix - remove the formatting options from the call to NewtonSoft.Json.JsonConvert.SerializeObject. I had copied a snippet from somewhere that included formatting of the Json string. Works perfect now!

Related

Unable to save aspnet-sessionid using NLog

I'm working with Nlog logging framework. currently I'm facing issue, that unable to save aspnet-sessionid.
<target xsi:type="File"name="LogFileAppender"fileName="C:\Users\acer\Downloads\test1.txt"
layout="${longdate} ${aspnet-sessionid} - ${message} "/>
It is saving (as per layout) in target fileName like
2020-05-07 11:16:56.4047 - Global.asax.cs:Application_Start(): Application initializing, starting cache load
But in log4net I'm able to save aspnet-sessionid
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<file value="C:\Users\acer\Downloads\test1.txt"/>
<appendToFile value="true"/>
<rollingStyle value="Date"/>
<datePattern value="yyyy-MM-dd.log"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %aspnet-session{SessionID} - %message"/>
</layout>
It is saving (as per conversion pattern) in target fileName like
2020-05-06 12:09:49,560 26aef5e9-16-132332207751900447spnet-session{SessionID} - Global.asax.cs:Application_Start(): Application initializing, starting cache load
The problem is, with log4net logging framework I'm able to save aspnet-sessionid but not with NLog framework.Any help is welcome.
Thanks.
This NLog ${aspnet-sessionid} renders the following:
HttpContext.Session.SessionID
This Log4net %aspnet-session{SessionID} renders the following:
HttpContext.Session.Content["SessionID"]
It is matching this NLog LayoutRenderer: ${aspnet-session:SessionID}
See also https://github.com/nlog/nlog/wiki/AspNetSession-Layout-Renderer
It's mistake with log4net Conversion pattern only.
<conversionPattern value="%date %aspnet-session{SessionID} - %message"/>
In this conversionpattern, for %aspnet-session{SessionID} in log4net it will consider only %a and it will be appdomain conversion pattern.
So , its in NLog will be like
<target xsi:type="File"name="LogFileAppender"fileName="C:\Users\acer\Downloads\test1.txt"
layout="${longdate} ${appdomain} - ${message} "/>
So, its confusion with name of conversion pattern for aspnet-sessionid in log4net.
[https://github.com/NLog/NLog/wiki/AppDomain-Layout-Renderer] refered for appdomain layout renderer.

log4net with .NET Framework 4.6.2

I got my new Windows 10 having to install Visual Studio 2019 only with .NET Framework 4.6.2. I also all frameworks available available in the VS Installer including the framework 4.5.2, but cannot select it, so i have chosen 4.6.2 using my latest log4net package. But now it stopped creating my log file when using the application.
Looking at the "Supported Frameworks" page at Apache Log4Net it does not list 4.6 or 4.6.2. Does that mean its not supporting at all. Tried to clone the github repo compiling on my own but still, it is not creating my log file.
Any known issues with .NET 4.6.x?
Update with code:
Globals.asax.cs contains this:
protected void Application_Start(object sender, EventArgs e)
{
log4net.Config.XmlConfigurator.Configure();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
}
web.config contains this:
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
and this:
<log4net>
<root>
<level value="ALL"/>
<appender-ref ref="file"/>
</root>
<appender name="file" type="log4net.Appender.RollingFileAppender">
<encoding value="utf-8"/>
<file value="log\LOG_"/>
<appendToFile value="true"/>
<rollingStyle value="Date"/>
<maxSizeRollBackups value="5"/>
<maximumFileSize value="15MB"/>
<staticLogFileName value="false"/>
<datePattern value="yyyy-MM-dd'.log'"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline"/>
</layout>
</appender>
</log4net>
and my cs files call this to log:
log4net.LogManager.GetLogger(HttpContext.Current.Session.SessionID).Debug(message);
Very strange. The Global.asax file was missing in the root directory. Since the Global.asax.cs is compiled into the DLL, i thought it runs anyway, but we need to keep Global.asax whose content simply is THIS:
<%# Application Codebehind="Global.asax.cs" Inherits="MyNamespace.App.Global" Language="C#" %>
Without this, all the Application_Start having the .Configure() call for log4net is NOT called. Didn't know that.

Configuring commons logging in Glassfish

I am using commons logging for my application running on Glassfish V3.1(I am new to glassfish). I have different applications running on Glassfish under ../domain1 folder(Developers machine). I am using an XML to configure Logging.Following is the my xml config
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
<appender name="file"
class="org.apache.log4j.RollingFileAppender">
<param name="maxFileSize" value="100KB" />
<param name="maxBackupIndex" value="5" />
<param name="File" value="/home/phanikumar/Desktop/debug.log" />
<param name="threshold" value="debug"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{DATE} %5p %c{1}:%L - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="warn" />
<param name="LevelMax" value="fatal" />
</filter>
</appender>
<logger name="com">
<level value="DEBUG" />
<appender-ref ref="file"/>
</logger>
<root>
<appender-ref ref="file" />
</root>
</log4j:configuration>
In this config file I have explicitly mentioned the file to be in a specific location but it never did.Is there any problem with the logger file?Am I missing some thing?
or
Is there any way that I can configure my logs to be in a specific location? I have seen the server.log file and it is unsuitable for my requirement as the logs of all applications are logged in a same file.
Please kindly help me.
SOLUTION
Add a Properties file named commons-logging.properties in the class path.
And add the following property
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
This initializes Logging to Log4j Logger
Then it works perfectly.
EDIT:
Usually, by default commons logging searches for loggers like log4j. If the above solution doesnt work, one needs to check if the commons-logging jar file is corrupted i.e, check if the class files like org.apache.commons.logging.impl.Log4jLogger is present.

.NET Web Deployment Tool with log4Net: Not overwriting logs

I'm using the Web Deployment Tool to build and release an MVC site from VS 2010 to a server running IIS. I also have log4net logging to a subdirectory off of the root of the web application I'm deploying to. I already figured out how to keep write permissions intact when deploying with this tool on that directory, but now I'm running into the problem that I'd rather not lose the logs when deploying, and also, the deploy is failing because the log file that log4net is using is "used by another process" (presumably w3wp) and won't let the deploy continue.
So, I'd like to preserve the log files and not delete or overwrite them, for auditing purposes. Is there a way to do that within the confines of the Web Deployment Tool?
EDIT: Here's the applicable bits of the log4net configuration, in Web.Config.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net" />
</configSections>
<log4net>
<appender name="RollingLog" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Logs\Log.txt" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="20" />
<maximumFileSize value="10MB" />
<datePattern value="yyyyMMdd" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="{%level}%date{MM/dd HH:mm:ss} - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingLog" />
</root>
</log4net>
</configuration>
Found it by hunting around: there is a "skip" parameter you can tack on to the command when you call the pre-packaged deploy script. You HAVE to use a regular old CMD prompt for this; Powershell's crazy escaping of quotes makes it near-impossible to get right, so I gave up. Anyway, here's the end result I came up with:
.\MyProject.deploy.cmd /Y /M:MyServerName "-skip:skipAction=Delete,objectName=filePath,absolutePath=Logs"
"MyProject.deploy.cmd" being the name of the prepackaged deploy command, "MyServerName" being the name of the server I was deploying to, and "Logs" being the name of the folder I wanted to skip. This command seems to leave alone that Logs directory and deploy anything else that matters.
Source where I started to hone in on things: http://blogs.iis.net/msdeploy/archive/2009/04/23/what-has-changed-about-skip-replace-rules-in-rc.aspx
Set locking model of your appender to minimal lock and everything will be fine:
<appender name="RollingLog" type="log4net.Appender.RollingFileAppender">
...
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
...
</appender>
log4net.Appender.FileAppender (see remarks)

log4Net EventlogAppender does not work for Asp.Net 2.0 WebSite?

I have configured log4Net EventLogAppender for Asp.Net 2.0. However it does not log anything. I have following in my Web.Config.
<log4net>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="LogName" value="Test Log" />
<param name="ApplicationName" value="Test-Web" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<root>
<priority value="ERROR"/>
<appender-ref ref="EventLogAppender"/>
</root>
<logger name="NHibernate">
<level value="ERROR" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
I already have Test-Log Event Log created and AspNet user has permission on the Event Log registry entry. I also have log4Net configured in Global.asax Application_Start.
log4net.Config.XmlConfigurator.Configure();
Update : I switched on the log4net internal debugging and found the following error in the trace.
log4net:ERROR XmlHierarchyConfigurator: Could not create Appender [EventLogAppender] of type [log4net.Appender.EventLogAppender]. Reported error follows.
System.Security.SecurityException: The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security.
at System.Diagnostics.EventLog.FindSourceRegistration(String source, String machineName, Boolean readOnly)
at System.Diagnostics.EventLog.SourceExists(String source, String machineName)
at System.Diagnostics.EventLog.SourceExists(String source)
at log4net.Appender.EventLogAppender.ActivateOptions()
at log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(XmlElement appenderElement)
Update 2 : It finally works if I create the Event Source (Test-Web) using a console based application in c# and then using the Web Application.
There's some very simple steps to get Log4Net working with the event log with ASP.NET.
Your options are:
Change the app pool
Run the application pool as LocalSystem
Or...set an application name, add a registry key
Configure your config file first so there is an application name.
This is important if you are having a permissions issue, because if you peer at the source you'll see the EventLogAppender defaults the application name (the source column in the event log) to:
System.Threading.Thread.GetDomain().FriendlyName
This requires your application to create a registry key each time the name changes, and is a bit messy. So the best solution is to set your application name. Here's an example EventLogAppender section that sends every error level, the ApplicationName line is the important part:
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="ApplicationName" value="MY-AWESOME-APP" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="INFO" />
</evaluator>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO"/>
<param name="LevelMax" value="FATAL"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<!-- The event log already logs the date so just log the message -->
<conversionPattern value="%message" />
</layout>
</appender>
Before making this change, do the following:
Create a registry key
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\MY-AWESOME-APP
Create a string value inside this
Name it EventMessageFile, set its value to
C:\Windows\Microsoft.NET\Framework\v2.0.50727\EventLogMessages.dll
That path appears to work in both 64 bit and 32 bit environments.
With this technique you don't need to set permissions in the registry, and once the key above is created it should just work.
I can't tell you exactly what might be wrong, but if you go here you will see "How do I enable log4net internal debugging?" way down at the bottom. Log4net will not throw exceptions if something is wrong, so you must enable internal debugging in order to get information from log4net.
http://logging.apache.org/log4net/release/faq.html
Edit: Also see the quesiton directly after that one that explains potential hangups with using the EventLogAppender.
I would suspect code access security is preventing you from accessing the event log. This article have information on the topic. Basically, if your ASP.Net application is running under medium trust the app will not have access to event logs.
Note: this is not a restriction built into log4net per se, it is a "feature" of the .Net Framework and ASP.Net.

Resources