Log4Net on cloud solution? - log4net

I would like to utilize Log4Net on a Dynamics 365 solution (plugins, etc.)
Is this possible somehow - I cannot just deploy a config file I guess, but are there a feasible way to do it anyhow?
The dream of mine is to unify logging, to place logging in one place, no matter if it is plug-ins, integrations or other functionality...

Besides using a configuration file, Log4net can accept its configuration from other sources using eg. a Stream or XmlElement.
To do so, you'll have to use the Log4net api via XmlConfigurator.Configure.
It is important not to apply the XmlConfiguratorAttribute; it's either one or the other.
The example below shows how to apply a configuration via an XmlElement.
The content of this XmlElement can be retrieved from anywhere; hardcoded, an embedded resource file, a record from a dabase, etc.
In the xml configuration, you declare any loggers that can be used within your Dynamics 365 environment.
string xml = #"
<log4net>
<appender name='consoleAppender' type='log4net.Appender.ConsoleAppender' >
<layout type='log4net.Layout.PatternLayout'>
<conversionPattern value='%date | %logger | %level | %message | %exception%n' />
</layout>
</appender>
<root>
<level value='ALL' />
<appender-ref ref='consoleAppender' />
</root>
</log4net>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlElement config = doc.DocumentElement;
ILoggerRepository repository = log4net.LogManager.GetRepository(Assembly.GetCallingAssembly());
XmlConfigurator.Configure(repository, config);
ILog logger = LogManager.GetLogger("somelog");
logger.Debug("foobar");

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>

Azure AppInsight with Log4Net

I have been trying to write Logs(Trace, Information & Exception) in Azure AppInsights using Log4Net instead of default api Telemetry client. When I run the application from VS2013 neither I get any error message nor am seeing logs in Azure portal.
Pleaes help me figure out this issue.
Note: Am using Log4net appender for AppIinsights.
Web.Config
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="aiAppender" />
</root>
<appender name="aiAppender" type="Microsoft.ApplicationInsights.Log4NetAppender.ApplicationInsightsAppender, Microsoft.ApplicationInsights.Log4NetAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message%newline" />
</layout>
</appender>
MVC Controller
public class HomeController : Controller
{
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public ActionResult Index()
{
//Trace.TraceInformation("Home accessed at : {0}", DateTime.UtcNow);
Log.Info(string.Format("Home accessed at : {0}", DateTime.UtcNow));
return View();
}
}
Regards,
Rajaram.
If you are not seeing any log4net output, i'm presuming you are missing some log4net startup code, like this:
log4net.Config.XmlConfigurator.Configure();
which you might want in your startup class / code somewhere. Without that, log4net doesn't know wo read the configuration that's in web.config.
In addition to the answer from #JohnGardner, you can instead add a line to your AssemblyInfo.cs file as so: -
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
There is more discussion on the two approaches in the following question: -
Configure Log4Net in web application
And in a comment in somewhere in that discussion is a link to the log4net FAQs that touches on the differences in the question "When should I log my first message?": -
https://logging.apache.org/log4net/release/faq.html#first-log
I found both of these to be of further use to me.

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.

Resources