I've got a silverlight project and I'm trying to configure NLog for calling static method but it doesn't (using Nlog.config).
I'm following this example.
Here's Nlog.config code:
...
<targets>
<target name="m" xsi:type="MethodCall"
className="NLogTestSilver.MainPage, NLogTestSilver"
methodName="LogMethod">
<parameter layout="${level}" />
<parameter layout="${message}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="m" />
</rules>
...
Assembly name = NLogTestSilver.dll
Here's MainPage.xaml.cs code:
namespace NLogTestSilver
{
public partial class MainPage : UserControl
{
public static Logger Logger = LogManager.GetCurrentClassLogger();
public MainPage()
{
InitializeComponent();
Logger.Fatal("Fatality");
}
public static void LogMethod(string level, string message)
{
System.Windows.Browser.HtmlPage.Window.Alert(level + " " + message);
}
}
}
P.S. Programmatic configuration works well.
So it was found out that an exception is thrown in NLog.Targets.MethodCallTarget.InitializeTarget() method while processing className parameter.
If we change
className="NLogTestSilver.MainPage, NLogTestSilver"
to
className="NLogTestSilver.MainPage, NLogTestSilver,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx"
it works great.
Where xxxxxxxxxxxxxxxx is public key token of our assembley.
Related
I'm using nlog it's working well for log file but I want to add log info in db too.
But it's not working for me.
I couldn't find my problem.
I'm using postgresql as database.
I'm using .NET5
NLog 4.7.10
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">
<targets>
<target name="allfile" xsi:type="File"
fileName="D:\BEBKA.JobTracking.logs\${shortdate}.log"/>
<target xsi:type="Database" name="db" dbProvider="Npgsql.NpgsqlConnection, Npgsql" connectionstring="Server=127.0.0.1;Port=5432;Database=BEBKAJobTracking;User Id=postgres;Password=123;">
<commandText>
INSERT INTO public."Logs"("Type", "Method", "StatusCode", "StackTrace", "MethodName", "Message", "RequestData", "ResponseData", "Ip", "CreatedDate", "CreatedId")
VALUES (#Type, #Method, #StatusCode, #StackTrace, #MethodName, #Message, #RequestData, #ResponseData, #Ip, #CreatedDate, #CreatedId);
</commandText>
<parameter name="#Type" layout="${type}"/>
<parameter name="#Method" layout="${method}"/>
<parameter name="#StatusCode" layout="${statusCode}"/>
<parameter name="#StackTrace" layout="${stackTrace}"/>
<parameter name="#MethodName" layout="${methodName}"/>
<parameter name="#Message" layout="${message}"/>
<parameter name="#RequestData" layout="${requestData}"/>
<parameter name="#ResponseData" layout="${responseData}"/>
<parameter name="#Ip" layout="${ip}"/>
<parameter name="#CreatedDate" layout="${createdDate}"/>
<parameter name="#CreatedId" layout="${createdId}"/>
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="allfile" />
<logger name="db" minlevel="Trace" writeTo="db" />
</rules>
</nlog>
My logger service
using BEBKA.Infrastructure.Abstractions.Core;
using BEBKA.Infrastructure.Abstractions.Loggger.Interfaces;
using NLog;
namespace BEBKA.Infrastructure.Services
{
public class LoggerService : ILoggerService
{
private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
public void LogDebug(ILog log)
{
logger.Debug(log.Message);
}
public void LogDebug(string message)
{
logger.Debug(message);
}
public void LogError(ILog log)
{
logger.Error(log.Message);
}
public void LogError(string message)
{
logger.Error(message);
}
public void LogInfo(ILog log)
{
//TODO: Need Bugfix
LogEventInfo theEvent = new(LogLevel.Info, "db", log.Message);
SetLogEventInfo(theEvent, log);
logger.Log(theEvent);
//logger.Info("{message}",log.Message);
}
public void LogInfo(string message)
{
logger.Info(message);
}
public void LogWarn(ILog log)
{
logger.Warn(log.Message);
}
public void LogWarn(string message)
{
logger.Warn(message);
}
private static void SetLogEventInfo(LogEventInfo theEvent, ILog
data)
{
theEvent.Properties["Type"] = data.Type;
theEvent.Properties["Method"] = data.Method;
theEvent.Properties["StatusCode"] = data.StatusCode;
theEvent.Properties["StackTrace"] = data.StackTrace;
theEvent.Properties["MethodName"] = data.MethodName;
theEvent.Properties["Message"] = data.Message;
theEvent.Properties["RequestData"] = data.RequestData;
theEvent.Properties["ResponseData"] = data.ResponseData;
theEvent.Properties["Ip"] = data.Ip;
theEvent.Properties["CreatedDate"] = data.CreatedDate;
theEvent.Properties["CreatedId"] = data.CreatedId;
}
}
}
..................................................................................................................................................................................................................................................................
You have several issues going on:
Event-Properties must be rendered with help from ${event-properties}
<parameter name="#Type" layout="${event-properties:type}"/>
<parameter name="#Method" layout="${event-properties:method}"/>
<parameter name="#StatusCode" layout="${event-properties:statusCode}"/>
<parameter name="#StackTrace" layout="${event-properties:stackTrace}"/>
<parameter name="#MethodName" layout="${event-properties:methodName}"/>
<parameter name="#Message" layout="${event-properties:message}"/>
<parameter name="#RequestData" layout="${event-properties:requestData}"/>
<parameter name="#ResponseData" layout="${event-properties:responseData}"/>
<parameter name="#Ip" layout="${event-properties:ip}"/>
<parameter name="#CreatedDate" layout="${event-properties:createdDate}"/>
<parameter name="#CreatedId" layout="${event-properties:createdId}"/>
Logger-Name should never be assigned, but must be null for filtering to work
public class LoggerService : ILoggerService
{
private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
private static readonly ILogger Dblogger = LogManager.GetLogger("db");
public void LogInfo(ILog log)
{
LogEventInfo theEvent = new(LogLevel.Info, null, log.Message);
SetLogEventInfo(theEvent, log);
Dblogger.Log(theEvent); // DbLogger matches <logger name="db" minlevel="Trace" writeTo="db" />
}
It is a little confusing that all LogEventInfo-constructors takes Logger-name as input-parameter, but it should never be assigned. Tried to improve on this, but my pull-request was rejected: https://github.com/NLog/NLog/issues/4086
Notice that one could also log ILog as single object like Dblogger.Info("{payload}", data) and extract individual properties like this: ${eventproperties:payload:objectpath=CreatedId}
When I use log4j and TestNG #DataProvider I was able to generate logs for the below code, but when I use #DataProvider the logs are getting overwritten. I tried to use #BeforeTest but it's not working. Any idea on how can I generate for logs for all the my rows?
public class DemoTest extends baseFX {
public static Logger Log = LogManager.getLogger(baseFX.class.getName());
#Test(dataProvider="DataProvider", groups = { "baseFX" })
public void loginPageNav(String Test, String newMemEmail, String newMemPass ) throws Exception {
driver=driverSetup();
Log.info("Driver is initialized");
//Creating object for the Index to the class
IndexPage indexpage = new IndexPage(driver);
Log.info("Navigated to Index Page");
//invoke method
indexpage.clickLogin().click();
Log.info("Clicked on Login");
//Creating an object for the login page and invoke its elements
LoginPage loginpage = new LoginPage(driver);
loginpage.getPassword().sendKeys(password);
loginpage.loginBtn().click();
Log.info("Member successfully logged in");
//driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
driver.close();
}
#DataProvider
public Object[][] DataProvider() throws Exception{
Object[][] arrayObject = ReadExcelData.getExcelData("./src/test/java/Autopkg/TestData/Demo.xlsx", "Sheet1");
return arrayObject;
}
//#AfterTest
//public void tearDown(){
//}
}
I use log4j configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="basePath">./logs</Property>
</Properties>
<Appenders>
<RollingFile name="File" fileName="${basePath}/prints.log" filePattern="${basePath}/prints-%d{yyyy-MM-dd}.log">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<SizeBasedTriggeringPolicy size="1000" />
</RollingFile>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
I am using below code for creating logging in my project using PRISM ILoggrFacade.
But i am not sure is the best way and second thing how can i use CustomLogger class logging because i am unable to create logging.
public class CustomLogger : ILoggerFacade
{
protected static readonly ILog log = LogManager.GetLogger(typeof(CustomLogger));
public CustomLogger()
{
log4net.Config.XmlConfigurator.Configure();
}
public void Log(string message, Category category, Priority priority)
{
switch (category)
{
case Category.Debug:
log.Debug(message);
break;
case Category.Warn:
log.Warn(message);
break;
case Category.Exception:
log.Error(message);
break;
case Category.Info:
log.Info(message);
break;
}
}
}
Bootstrapper
private readonly CustomLogger _logger = new CustomLogger();
protected override ILoggerFacade CreateLogger()
{
return _logger;
}
ViewModel
logger.Log("Logging success", Category.Info, Priority.None);
log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="C:\temp\log.txt" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %message%newline" />
</layout>
</appender>
</log4net>
</configuration>
Problem with above code is that need to configure log4net in assembly like below:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4Net.config", Watch = true)]
Also in addition if you wan to drag log4net in ViewModels the use below code
private readonly ILoggerFacade _loggerFacade;
public ContentAViewViewModel(ILoggerFacade loggerFacade)
{
_loggerFacade = loggerFacade;
}
Example
private void LoadPeople()
{
_loggerFacade.Log("Load People", Category.Debug, Priority.High);
}
All ViewModel classes inherit from a base class:
public abstract class ScreenBase : ViewModelBase, IScreen, IDisposable
{
protected readonly NLog.Logger _logger;
protected ScreenBase()
: this(Messenger.Default) { }
protected ScreenBase(IMessenger messenger)
: base(messenger)
{
_logger = NLog.LogManager.GetLogger(this.GetType().Name);
_logger.Debug("{0} ({1}) constructed. ", this.GetType().Name, this.GetHashCode());
}
~ScreenBase()
{
FinalizeProc();
}
[Conditional("DEBUG")]
private void FinalizeProc()
{
_logger.Debug("{0} ({1}) Finalized. ", this.GetType().Name, this.GetHashCode());
}
}
As you can see, any time instance of ViewModel is created / destroyed, it should log it. I am logging it into Console window and file:
<targets>
<!-- add your targets here -->
<target name="logDebugInfo" xsi:type="File" deleteOldFileOnStartup="true" fileName="${specialfolder:folder=CommonApplicationData}/MyApp/debug.txt" layout="${longdate} | ${uppercase:${level}} | ${stacktrace} | ${message}${onexception:EXCEPTION OCCURRED\:${exception:format=tostring}}" />
<target name="console" xsi:type="Console" />
</targets>
<rules>
<!-- add your logging rules here -->
<logger name="*" minlevel="Trace" maxlevel="Info" writeTo="logDebugInfo" />
<logger name="*" minlevel="Trace" writeTo="console" />
</rules>
Each message is properly logged until the application is closed. When 'X' Close button is pressed on the main view, I do not do anything specific in code, I let the application close itself. However, no 'Finalized' messages are displayed at that point.
Anyone knows why?
The reason why this is happening is that Logger is being destroyed on application shutdown.
I'm trying to enable solution-wide logging by adding a stand-alone project that wraps log4net. I found a code on StackOverflow but the code is using some config file. I do not understand that bit. Here is the only static class:
using log4net;
using log4net.Config;
using System;
using System.IO;
namespace ExciteEngine2.LoggingManager {
//// TODO: Implement the additional GetLogger method signatures and log4net.LogManager methods that are not seen below.
public static class ExciteLog {
private static readonly string LOG_CONFIG_FILE = #"log4net.config";
public static ILog GetLogger(Type type) {
// If no loggers have been created, load our own.
if (LogManager.GetCurrentLoggers().Length == 0) {
LoadConfig();
}
return LogManager.GetLogger(type);
}
private static void LoadConfig() {
//// TODO: Do exception handling for File access issues and supply sane defaults if it's unavailable.
try {
XmlConfigurator.ConfigureAndWatch(new FileInfo(LOG_CONFIG_FILE));
}
catch (Exception ex) {
}
}
}
}
Now, there is no log4net.config anywhere. And in my main application project, I'm using the ILog as follows:
using log4net;
using ExciteEngine2.LoggingManager;
namespace ExciteEngine2.MainApplication {
internal static class Program {
public static readonly ILog ApplicationLogger = ExciteLog.GetLogger(typeof(Program));
private static void SetupLogging() {
log4net.Config.XmlConfigurator.Configure();
}
[STAThread] static void Main(string[] args) {
//Uninstall
foreach (string arg in args) {
if (arg.Split('=')[0] == "/u") {
Process.Start(new ProcessStartInfo(Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\msiexec.exe", "/x " + arg.Split('=')[1]));
return;
}
}
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
try {
ThemeResolutionService.ApplicationThemeName = ConfigurationManager.AppSettings["ThemeToUse"];
}
catch (Exception ex) {
ApplicationLogger.Error("Exception while setting Telerik Theme.", ex);
ThemeResolutionService.ApplicationThemeName = "ControlDefault";
}
DevExpress.UserSkins.OfficeSkins.Register();
DevExpress.UserSkins.BonusSkins.Register();
DevExpress.Skins.SkinManager.EnableFormSkins();
DevExpress.Skins.SkinManager.EnableMdiFormSkins();
//try {
if (args.Contains("/dx")) {
Application.Run(new AppMDIRibbonDX());
ApplicationLogger.Info("Application (DX) started.");
}
else {
Application.Run(new AppMDIRibbon());
ApplicationLogger.Info("Application started.");
}
//} catch (Exception ex) {
// ApplicationLogger.Fatal("Exception while initiating. Nothing can be done here.", ex);
// XtraMessageBox.Show(String.Format("Exception while initiating. Nothing can be done here.{0}Message: {1}", Environment.NewLine, ex.Message), "Excite Engine 2", MessageBoxButtons.OK, MessageBoxIcon.Error);
//}
}
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
ApplicationLogger.Fatal("Application Level Exception.", e.Exception);
Thread t = (Thread)sender;
Exception threadexception = e.Exception;
string errormessage = String.Format("Thread ID: {0} [ {1} ]", t.ManagedThreadId, threadexception.Message);
XtraMessageBox.Show(String.Format("Application Level Exception!{1}{0}{1}Details:{1}{2}", errormessage, Environment.NewLine, threadexception.StackTrace), "Excite Engine 2", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
As you can see from my flow, I'm executing this line of code thinking log4net will use my main application project's app.config: log4net.Config.XmlConfigurator.Configure();
And here is a line I added in AssemblyInfo.cs:
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
Finally, the app.config for my Main application:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<appSettings>
</appSettings>
<connectionStrings>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
<log4net>
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" >
<param name="File" value="Excite Engine 2 Log.log" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%-5p%d{ddd, dd-MMM-yyyy hh:mm:ss} - %m%n" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
<applicationName value="Excite Engine 2" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
</log4net>
</configuration>
When I run with <appender-ref ref="LogFileAppender" />, I get an empty file named Excite Engine 2 Log.log right next to my main EXE. And when I set <appender-ref ref="EventLogAppender" />, nothing happens in Event Viewer. Also, there is an attribute: <level value="DEBUG" /> thats really bothering me. What I want is a full EventViewer logging for my application regardless of the build configuration it is running in.
Appreciate if someone could guide me on this. Thanks!
I found a code on StackOverflow but
the code is using some config file. I
do not understand that bit.
The reason he's using a specific config file can be explained by the following taken from log4net's site:
The System.Configuration API is only
available if the configuration data is
in the application's config file; the
file named MyApp.exe.config or
Web.config. Because the
System.Configuration API does not
support reloading of the config file
the configuration settings cannot be
watched using the
log4net.Config.XmlConfigurator.ConfigureAndWatch
methods. The main advantage of using
the System.Configuration APIs to read
the configuration data is that it
requires less permissions than
accessing the configuration file
directly. The only way to configure an
application using the
System.Configuration APIs is to call
the
log4net.Config.XmlConfigurator.Configure()
method or the
log4net.Config.XmlConfigurator.Configure(ILoggerRepository)
method.
Edit:
To log to your log file you need to call your SetupLogging method above.
log4net.Config.XmlConfigurator.Configure();
This statement is never being called. It looks like you are calling LoadConfig() in your ExciteEngine2.LoggingManager but this uses a config file called log4net.config which you said doesn't exist. If you are putting your configuration in your app.config file then you need to call your SetupLogging method.