No log4j automatic compression after app restart - log4j

I'm using the automatic log rolling and compression facilitated by the TimeBasedRollingPolicy provided in Log4J Extras (see config below).
It is normal for the application which is doing this logging to be constantly stopping/starting and I've noticed that the automatic compression does not occur if the application is stopped during a rollover triggering event (hourly rollover in this case). I find this strange as the rolling itself (without compression) still occurs and seems to work fine.
Is it not possible to have log compression work for an application that does not run continuously?
Does anyone know how to get this working with Log4J?
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true">
<appender name="ROLL" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="/var/batchproc/logs/log4j_roll_compress_%d{yyyy-MM-dd-kk}.log.gz"/>
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d] [%t] %-5p %c %m%n"/>
</layout>
</appender>
<root>
<appender-ref ref="ROLL"/>
</root>
</log4j:configuration>

The rollover process is only triggered by logging two messages that are in different time units (hours in the example) while the app is running. Past time units aren't scanned-for on app startup.
One thing you can do is use a separate "active" file name to be where all log messages go before they're rolled/zipped. If you do that, any existing active log file will be appended-to until another hour has gone by and then rolled into a gzipped, timestamped file. Unfortunately, this file's timestamp isn't checked on startup (at least in apache-log4j-extras 1.1), so the old hour's logs and new hour's logs will be together in the rolled file. But at least it'll be zipped!
<appender name="ROLL" class="org.apache.log4j.rolling.RollingFileAppender">
<param name="File" value="/var/batchproc/logs/log4j_roll_active.log"/>
...rest of example config here...
</appender>

Related

Log4j and centralizing log collection

I have an existing distributed application using log4j to write logs to the local server. I want to preserve the existing functionality and also have some of those logs sent to a central repository. I've seen examples of using log4j with SocketAppender to send a log to a remote server, but haven't seen an example of multiple server sending to the same remote server writing each server's logs in a separate file. Is there an example of this?
As an alternative, I'm curious about using the JDBCAppender using a database as the centralized log repository but have the same question regarding how do differentiate where the messages came from when viewing query results. Is there a log4j properties setting that identifies the sender that can be interpreted on the listener server?
For your first question - it will depend on the remote server to whom your client program is sending logs. If you have developed some program for receiving logs on remote server then, there are 2 approaches to create separate log file for each client logs -
Server program should listen on a particular port and after receiving some logs, it should check client IP and then create log file for each client IP.
Make server program to listen on different port for each client and once client is connected to its specific port, receive the data and dump in a log file. This approach seems easy but not recommended.
If your server is based on linux, I would recommend you to use rsyslog for centralizing log collection. In rsyslog, you can configure each client separately and dump the logs in separate log file.
For second question - you can use Nested diagnostic Context (NDC) feature of log4j for writing hostname in database. See this example. This example is using USER_ID as extra column for writing in database. Similarly, you can use this extra column for writing hostname. In the starting of your client program before writing any log statement, you have to put value in NDC using below code -
NDC.push(InetAddress.getLocalHost().getHostName());
you have to make some changes in the Configuration File. Considering multiple applications want to write their log files to the centralised remote location, If yes then the below mentioned changes would help:
You need to make the change in each individual application's Log4j config file.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="60">
<Properties>
<Property name="server-log-path">REMOTE_SERVER_PATH</Property>
</Properties>
<Appenders>
<File name="Login-App-File-Appender" fileName="${server-log-path}/file_name.log" >
<PatternLayout>
<pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
</File>
<File name="CheckOut-App-File-Appender" fileName="${server-log-path}/file_name.log" >
<PatternLayout>
<pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="com.microService.LoginService" level="info" additivity="false">
<AppenderRef ref="Login-App-File-Appender"/>
</Logger>
<Logger name="com.microService.CheckOutService" level="info" additivity="false">
<AppenderRef ref="CheckOut-App-File-Appender"/>
</Logger>
<Root>
<AppenderRef ref="Login-App-File-Appender"/>
</Root>
</Loggers>
</Configuration>

Log4net Json Result into NoSQL Database

I am trying out a scenario where in I am able to generate the JSON logs and store them in database.
I have to use log4net as logging mechanism. So far I am able to achieve the log4net Json using the json formater as below.
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="C:\\TestProj\\jsonlog.txt" />
<param name="AppendToFile" value="true" />
<param name="DatePattern" value="_yyyyMMddHH".log"" />
<param name="RollingStyle" value="Date" />
<param name="StaticLogFileName" value="false" />
<layout type="log4net.Layout.SerializedLayout, log4net.Ext.Json">
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="FileAppender" />
</root>
I also know how to insert the log4net logs into SQL using adonetappender.
However I am not able to figure out these two questions:
How to insert the json logs into sql server database.
How to insert the json logs into a no-sql database.
I think I got it. I use regular ado.net appender and then use json layout for one of the parameters. –
I think you are not storing your logs in to the actual json file, you are using jsonlog.txt which is a text file. If you want to store the jsonlogs to database you can configure log4net to do it for you. Take a look at this.
https://logging.apache.org/log4net/release/config-examples.html
Inserting into no-sql was the primary reason for SerializedLayout to happen. There's multiple ways this can be achieved, but you'll most likely want some intermediate processor for the logs. I can recommend logstash and nxlog. Logstash can easily store your files in elastic search then.
They can both retrieve logs from:
Files
Network
TCP
UDP
Syslog
Other options would be queues, like RabbitMQ or AMQP. I haven't played with those. It's up to your needs and resources with regards to availability and resilience.
With regards to formatting the JSON bunch, see the answer on another question of yours - https://stackoverflow.com/a/36169213/481812

mule log files into DB

In mule CE version 3.3.0, I have a mule project, and the URL for calling it is http://localhost:8086/mule?msg=Hello-World!!!.
Every time that I call it, in a log file in mule server that it has as a default some lines added as a log.
Now I want to change type of logs in mule? I want to instead the file that mule create it for logs, as a default mule create a table into Database and save important info into it.
Actually I want to have a table log for my projects, and in this table I want to have customers' information such as IP and ...
Is it possible?
How can I do it?
You can use Log4j database appender to insert Mule ESB logs into database. Below code snippet is used to do the same.
<appender name="DB" class="org.apache.log4j.jdbc.JDBCAppender">
<param name="url" value="jdbc:mysql://localhost/DBNAME"/>
<param name="driver" value="com.mysql.jdbc.Driver"/>
<param name="user" value="user_id"/>
<param name="password" value="password"/>
<param name="sql" value="INSERT INTO LOGS VALUES('%level','%message','%X{muleMessage}','%X{payload}')"/>
<layout class="org.apache.log4j.PatternLayout">
</layout>
</appender>
<logger name="log4j.rootLogger" additivity="false">
<level value="DEBUG"/>
<appender-ref ref="DB"/>
</logger>

unable to get log4net to use WebServiceAppender from crm 2011

I have attempted to use a log4net webserviceappender from within a crm 2011 plugin (sandboxed), log4net apparently gets installed along with the plugin correctly (exception if log4net config file is malformed), but apparently the appender doesn't get called. I can call the webservice directly from within the plugin, so that part is working, but can't figure out what might be wrong with log4net.
Does anyone know of a step by step for using log4net with crm and/or have a good idea as to why the webserviceappender doesn't get called?
Thanks
EDIT: Including log4net.config file upon request.
<!-- WebService parameters. -->
<param name="Url" value="http://my-internal-server/errorlog/ErrorHandler.asmx" />
<param name="TimeoutSeconds" value="60" />
<!-- Proxy parameters. -->
<param name="UseProxy" value="false" />
<param name="ProxyUrl" value="http://myproxy:3128" />
<param name="ProxyBypassOnLocal" value="true" />
<param name="ProxyUseDefaultCredentials" value="true" />
<param name="ProxyCredentialsDomain" value="OFFICE" />
<param name="ProxyCredentialsUserName" value="MyUser" />
<param name="ProxyCredentialsPassword" value="MyPassword" />
</appender>
<root>
<level value="Info" />
<appender-ref ref="WebServiceAppender" />
</root>
It looks like you have deployed the configuration file on disk. This is not the ideal place as you have to deal with different requirements for the different modules.
To simplify the deployment of plugins, which need additional configuration, you have the possibility to pass configuration values to the plugin constructor. You should pass the configuration and configure log4net at runtime. See how to write the plugin constructor.
Another option is to use the webressources of Dynamics CRM 2011. See this blog article which describes all available options.

What happens if Log4Net doesn't have permission to access the file system

I'm implementing a logging solution with Log4Net for a Windows NT Service. I can flip a switch in a configuration file to start logging information to the file system. So far I've been able to accomplish this by having a rolling file appender and having log4net "Watch" the configuration file.
What I've notice is that Log4Net will create empty log files as soon as the service starts, even if all logging is turned off and I don't intend to log.
I can't find much information on this topic other than this post:
How to disable creation of empty log file on app start?
My concern is that someone could set up the service with a very low level set of permissions that wouldn't even have access to create the log files on the file system. I don't want to incur the performance penalty of having exceptions thrown every time I hit a logging statement even if I didn't intend to log.
I've wrapped each logging statement with check to see if the logging level is enabled before attempting to log, but I'm still not sure if in the inner workings of log4net whether or not exceptions are going to still be thrown if the file configured in the appender wasn't created.
if (logger.IsDebugEnabled)
{
logger.DebugFormat(format, traceMessage);
}
Does anyone know what log4net will do if it can't create the log files initially?
Here is a little information about my configuration. Logging works fine when it is turned on, I'm just worried about permissions issues.
Attribute on my logging class to watch for config changes:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Logging.config", Watch = true)]
Appender:
<appender name="Test" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value=".\\AppLogs\\_test.%appdomain.log" />
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ALL" />
<levelMax value="FATAL" />
<acceptOnMatch value="false"/>
</filter>
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="Test" />
</filter>
<appendToFile value="true" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="6MB" />
<rollingStyle value="Size" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.DenyAllFilter" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level - %message%newline" />
</layout>
</appender>
"My concern is that someone could set up the service with a very low level set of permissions that wouldn't even have access to create the log files on the file system. " - on service start up detect your minimum set of permisions required is present and throw an exception (or otherwise handle) if they are not.
I don't think this is a logging issue per se; it's more an issue of whether or not your service has its required permissions.

Resources