How to use NLog in multiple classes - c#

I am learning to use NLog. My situation is I want to use it inside DLL probably wrap it inside a log class. Basically my goals are:
1) I want this configuration to occur only ONCE:
var config = new LoggingConfiguration();
var fileTarget = new FileTarget();
config.AddTarget("file", fileTarget);
// Step 3. Set target properties
fileTarget.Layout = #"${date:format=HH\:mm\:ss} - ${message}";
fileTarget.FileName = "c:/myFolder/" + "${date:format=yyyy-MM-dd}.log";
var rule2 = new LoggingRule("*", LogLevel.Debug, fileTarget);
config.LoggingRules.Add(rule2);
// Step 5. Activate the configuration
LogManager.Configuration = config;
// Example usage
_logger = LogManager.GetLogger("Example");
If it will be relevant I also want to be able to specify say as the parameter the log file path to the initialization routine.
2) Any other class should be able to call a method like LogWrapper.Log("message"), which should log messages using my configured NLog object - I know which method of NLog writes the entry to log file, that is not a problem, say it is called _logger.write.
How can I achieve this in a (thread) safe way?
I have been struggling with this for a while already and would appreciate much help! This should not be that hard right, basically I am asking how to use NLog.

you deleted your previous question which answer this one so let me go at it again,
for #1, you need to put this code in a static constructor
ex;
static class test
{
static test()
{ /* ... code */}
}
for #2 to be safe you need a locker ex;
static class test
{
private static object _locker = new object();
static test()
{ /* ... code */}
public static void log(string msg)
{
lock(_locker )
{ /* ... code */}
}
}

Related

Prevent process seeing existing instance

Here's the situation.
I have an application which for all intents and purposes I have to treat like a black box.
I need to be able to open multiple instances of this application each with a set of files. The syntax for opening this is executable.exe file1.ext file2.ext.
If I run executable.exe x amount of times with no arguments, new instances open fine.
If I run executable.exe file1.ext followed by executable.exe file2.ext then the second call opens file 2 in the existing window rather than creating a new instance. This interferes with the rest of my solution and is the problem.
My solution wraps this application and performs various management operations on it, here's one of my wrapper classes:
public class myWrapper
{
public event EventHandler<IntPtr> SplashFinished;
public event EventHandler ProcessExited;
private const string aaTrendLocation = #"redacted";
//private const string aaTrendLocation = "notepad";
private readonly Process _process;
private readonly Logger _logger;
public myWrapper(string[] args, Logger logger =null)
{
_logger = logger;
_logger?.WriteLine("Intiialising new wrapper object...");
if (args == null || args.Length < 1) args = new[] {""};
ProcessStartInfo info = new ProcessStartInfo(aaTrendLocation,args.Aggregate((s,c)=>$"{s} {c}"));
_process = new Process{StartInfo = info};
}
public void Start()
{
_logger?.WriteLine("Starting process...");
_logger?.WriteLine($"Process: {_process.StartInfo.FileName} || Args: {_process.StartInfo.Arguments}");
_process.Start();
Task.Run(()=>MonitorSplash());
Task.Run(() => MonitorLifeTime());
}
private void MonitorLifeTime()
{
_logger?.WriteLine("Monitoring lifetime...");
while (!_process.HasExited)
{
_process.Refresh();
Thread.Sleep(50);
}
_logger?.WriteLine("Process exited!");
_logger?.WriteLine("Invoking!");
ProcessExited?.BeginInvoke(this, null, null, null);
}
private void MonitorSplash()
{
_logger?.WriteLine("Monitoring Splash...");
while (!_process.MainWindowTitle.Contains("Trend"))
{
_process.Refresh();
Thread.Sleep(500);
}
_logger?.WriteLine("Splash finished!");
_logger?.WriteLine("Invoking...");
SplashFinished?.BeginInvoke(this,_process.MainWindowHandle,null,null);
}
public void Stop()
{
_logger?.WriteLine("Killing trend...");
_process.Kill();
}
public IntPtr GetHandle()
{
_logger?.WriteLine("Fetching handle...");
_process.Refresh();
return _process.MainWindowHandle;
}
public string GetMainTitle()
{
_logger?.WriteLine("Fetching Title...");
_process.Refresh();
return _process.MainWindowTitle;
}
}
My wrapper class all works fine until I start providing file arguments and this unexpected instancing behaviour kicks in.
I can't modify the target application and nor do I have access to its source to determine whether this instancing is managed with Mutexes or through some other feature. Consequently, I need to determine if there is a way to prevent the new instance seeing the existing one. Would anyone have any suggestions?
TLDR: How do I prevent an application that is limited to a single instance determining that there is already an instance running
To clarify (following suspicious comments), my company's R&D team wrote executable.exe but I don't have time to wait for their help in this matter (I have days not months) and have permission to do whatever required to deliver the required functionality (there's a lot more to my solution than this question mentions) swiftly.
With some decompiling work I can see that the following is being used to find the existing instance.
Process[] processesByName = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
Is there any way to mess with this short of creating multiple copies of the application with different names? I looked into renaming the Process on the fly but apparently this isn't possible short of writing kernel exploits...
I have solved this problem in the past by creating copies of the source executable. In your case, you could:
Save the 'original.exe' in a specific location.
Each time you need to call it, create a copy of original.exe and name it 'instance_xxxx.exe', where xxxx is a unique number.
Execute your new instance exe as required, and when it completes you can delete it
You could possibly even re-use the instances by creating a pool of them
Building on Dave Lucre's answer I solved it by creating new instances of the executable bound to my wrapper class. Initially, I inherited IDisposable and removed the temporary files in the Disposer but for some reason that was causing issues where the cleanup would block the application, so now my main program performs cleanup at the end.
My constructor now looks like:
public AaTrend(string[] args, ILogger logger = null)
{
_logger = logger;
_logger?.WriteLine("Initialising new aaTrend object...");
if (args == null || args.Length < 1) args = new[] { "" };
_tempFilePath = GenerateTempFileName();
CreateTempCopy(); //Needed to bypass lazy single instance checks
HideTempFile(); //Stops users worrying
ProcessStartInfo info = new ProcessStartInfo(_tempFilePath, args.Aggregate((s, c) => $"{s} {c}"));
_process = new Process { StartInfo = info };
}
With the two new methods:
private void CreateTempCopy()
{
_logger?.WriteLine("Creating temporary file...");
_logger?.WriteLine(_tempFilePath);
File.Copy(AaTrendLocation, _tempFilePath);
}
private string GenerateTempFileName(int increment = 0)
{
string directory = Path.GetDirectoryName(AaTrendLocation); //Obtain pass components.
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(AaTrendLocation);
string extension = Path.GetExtension(AaTrendLocation);
string tempName = $"{directory}\\{fileNameWithoutExtension}-{increment}{extension}"; //Re-assemble path with increment inserted.
return File.Exists(tempName) ? GenerateTempFileName(++increment) : tempName; //If this name is already used, increment an recurse otherwise return new path.
}
Then in my main program:
private static void DeleteTempFiles()
{
string dir = Path.GetDirectoryName(AaTrend.AaTrendLocation);
foreach (string file in Directory.GetFiles(dir, "aaTrend-*.exe", SearchOption.TopDirectoryOnly))
{
File.Delete(file);
}
}
As a side-note, this approach will only work for applications with (lazy) methods of determining instancing that rely on Process.GetProcessByName(); it won't work if a Mutex is used or if the executable name is explicitly set in the manifests.

How to log with Nlog in SpecFlow?

SpecFlow writes its output into Console like this:
Given the "TestOperator" user is logged in
-> done: WebUserSteps.GivenTheUserIsLoggedIn("TestOperator", "") (9.5s)
How can we make it use NLog to configure where it should write?
With this:
public class CustomListener : ITraceListener
{
private Logger Log = LogManager.GetLogger("SPECFLOW");
public void WriteTestOutput(string message)
{
Log.Trace(message);
}
public void WriteToolOutput(string message)
{
Log.Trace(message);
}
}
And
[Binding]
public class ScenarioContextInitializer
{
private readonly IObjectContainer _container;
public ScenarioContextInitializer(ScenarioContext scenarioContext)
{
_container = (scenarioContext ?? throw new ArgumentNullException(nameof(scenarioContext))).ScenarioContainer;
}
[Before]
protected void Load()
{
_container.RegisterTypeAs<CustomListener, ITraceListener>();
}
}
It didn't work. I know there is ability to add plugins but that seems too much overhead.
Also we use ObjectivityLtd Test.Automation extensions.
It works via xunit tests generated by SpecFlow.xUnit
The issue is probably that NLog cannot find it's config.
When running unit tests, the dlls are moved and not the nlog.config
There are multiple solutions:
Load the config from a fixed path, e.g.
LogManager.Configuration = new XmlLoggingConfiguration("c:/mydir/nlog.config");
Or setup from code instead of config, e.g.:
var config = new LoggingConfiguration();
config.AddRuleForAllLevels(new FileTarget()
{
FileName = "c:/temp/logfile.log"
});
LogManager.Configuration = config; //apply config
See wiki
If that is still an issue, check the internal log
I've done similar thing in my framework with this workaround:
Add hook [AfterStep], that calls Console.WriteLine() [or your logger] with the name of the step + if passed or not (if test error != null, that means failed, o.w passed)
Please note that this works perfect in parallel execution. (the correct output goes to each test)
Here is the example:
https://github.com/LirazShay/SpecFlowDemo/blob/master/src/SpecFlowDemo/Hooks.cs
Something like this:
[AfterStep]
public void LogStepResult()
{
string stepText = StepContext.StepInfo.StepDefinitionType + " " + StepContext.StepInfo.Text;
Console.WriteLine(stepText);
var stepTable = StepContext.StepInfo.Table;
if (stepTable != null && stepTable.ToString() != "") Console.WriteLine(stepTable);
var error = ScenarioContext.TestError;
Console.WriteLine(error != null ? "-> error: " + error.Message : "-> done.");
}

NLog from different project

I'm using more NLog instances within single project (see my previous question Nlog config file priority). However, it doesn't work as expected.
If I call method that logs in second project, it's logged properly, but even after returning to previous project, items are being logged at wrong place.
So, for example Project1 has set to log in Project1.log, same way for second one. I can do method that simply calls:
Project1.Log.Write("1");
Project2.Log.Write("2");
Project1.Log.Write("3");
When I check logs, project1 contains "1", project 2 contains "2" and "3".
Exact (bit simplified) logger classes looks like:
public static class Log
{
private static readonly Lazy<Logger> Logger = new Lazy<Logger>(CreateLogger);
private static Logger CreateLogger()
{
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogManager.Configuration = new XmlLoggingConfiguration(assemblyFolder + "\\ProjectX.exe.nlog", true); //X means project id
return LogManager.GetCurrentClassLogger();
}
public static void Write(object log)
{
Logger.Value.Debug(log);
}
}
What am I doing wrong?
Your previous question talks about the application should have priority in loading a single configuration for the entire application:
Application-specific exe.nlog
Fallback to global nlog.config
Now you are talking about having multiple assemblies in the same application, that wants to load their individual NLog-configuration side-by-side.
When using the static LogManager.Configuration then you are modifying the global configuration for the entire application. If two project-assemblies are changing the global configuration, then it will of course have side-effects for others.
Maybe your CreateLogger could look like this:
private static Logger CreateLogger()
{
// Check for global NLog-configuration (Maybe your don't want this at all?)
var configuration = LogManager.Configuration;
if (configuration?.AllTarget.Count > 0)
return LogManager.GetCurrentClassLogger();
// Create assembly-specific NLog-configuration
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
LogFactory logFactory = new LogFactory();
logFactory.Configuration = new XmlLoggingConfiguration(assemblyFolder + "\\ProjectX.exe.nlog", true, logFactory); //X means project id
return logFactory.GetCurrentClassLogger();
}
See also https://github.com/NLog/NLog/wiki/Configure-component-logging

How do I make a collection fast searchable?

EDIT: I rephrased the question, and it was solved on this post: How do I search within a collection of type ConfigurationSection?
Original Question:
I am storing a list of config options in my web config. I may have 50 or 100 items in here eventually.
I am using the method described here:
http://net.tutsplus.com/tutorials/asp-net/how-to-add-custom-configuration-settings-for-your-asp-net-application/
The good news:
It works, and I have a _Config collection that has all the
The problem: How do I query _Config for a specific feed? (I will have 50-100, maybe more over time.... someday this will move to a db, but not now, as it is hosted on azure, and I need to avoid azure persistence for now.)
(And since this will execute a lot, perhaps it should be hashtable or dictionary? but I don't know how to create em...)
I have struggled, and have been unable to cast _Config into a list or something that I can query.
The question is: How do I get _Config (from the link above) into something that I can query for a specific feed?
The ultimate goal is to have a func that is called to work with a specific feed, and so it needs the config info just from that feed record. In pseudocode, the goal is something like:
getFeed(feedname)
if (_Config.name == feedname) // e.g. feedname is one of the "name" elements in the web.config
// do the stuff
GetData(_Config.feedname.url)
else
// requested feed is not in our config
// tell use can't do it
Or, (also pseudo code)
getFeed(feedname)
try
thisPassFeed = _Config.feedname;
string url = thisPassFeed.url;
// do the stuff
GetData(url);
catch
// requested feed is not in our config
// tell use can't do it
return("can't find that feedname in web.config")
You could create a static class that has a private Dictionary member. In the static constructor access the _Config and do
public static class Feeds
{
private static readonly Dictionary<string, FeedElement> feeds;
static Feeds()
{
feeds = new Dictionary<string, FeedElement>();
var config = ConfigurationManager.GetSection("feedRetriever") as FeedRetrieverSection;
foreach (FeedElement feed in config.Feeds)
{
feeds.Add(feed.Name, feed);
}
}
static public FeedElement GetFeed(string name)
{
return feeds[name];
}
}

Separating Logging Code from C# Objects

Currently I have a custom built static logging class in C# that can be called with the following code:
EventLogger.Log(EventLogger.EventType.Application, string.Format("AddData request from {0}", ipAddress));
When this is called it simply writes to a defined log file specified in a configuration file.
However, being that I have to log many, many events, my code is starting to become hard to read because all of the logging messages.
Is there an established way to more or less separate logging code from objects and methods in a C# class so code doesn't become unruly?
Thank you all in advance for your help as this is something I have been struggling with lately.
I like the AOP Features, that PostSharp offers. In my opinion Loggin is an aspect of any kind of software. Logging isn't the main value an application should provide.
So in my case, PostSharp always was fine. Spring.NET has also an AOP module which could be used to achieve this.
The most commonly used technique I have seen employs AOP in one form or another.
PostSharp is one product that does IL weaving as a form of AOP, though not the only way to do AOP in .NET.
A solution to this is to use Aspect-oriented programming in which you can separate these concerns. This is a pretty complex/invasive change though, so I'm not sure if it's feasible in your situation.
I used to have a custom built logger but recently changed to TracerX. This provides a simple way to instrument the code with different levels of severity. Loggers can be created with names closely related to the class etc that you are working with
It has a separate Viewer with a lot of filtering capabilities including logger, severity and so on.
http://tracerx.codeplex.com/
There is an article on it here: http://www.codeproject.com/KB/dotnet/TracerX.aspx
If your primary goal is to log function entry/exit points and occasional information in between, I've had good results with an Disposable logging object where the constructor traces the function entry, and Dispose() traces the exit. This allows calling code to simply wrap each method's code inside a single using statement. Methods are also provided for arbitrary logs in between. Here is a complete C# ETW event tracing class along with a function entry/exit wrapper:
using System;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace MyExample
{
// This class traces function entry/exit
// Constructor is used to automatically log function entry.
// Dispose is used to automatically log function exit.
// use "using(FnTraceWrap x = new FnTraceWrap()){ function code }" pattern for function entry/exit tracing
public class FnTraceWrap : IDisposable
{
string methodName;
string className;
private bool _disposed = false;
public FnTraceWrap()
{
StackFrame frame;
MethodBase method;
frame = new StackFrame(1);
method = frame.GetMethod();
this.methodName = method.Name;
this.className = method.DeclaringType.Name;
MyEventSourceClass.Log.TraceEnter(this.className, this.methodName);
}
public void TraceMessage(string format, params object[] args)
{
string message = String.Format(format, args);
MyEventSourceClass.Log.TraceMessage(message);
}
public void Dispose()
{
if (!this._disposed)
{
this._disposed = true;
MyEventSourceClass.Log.TraceExit(this.className, this.methodName);
}
}
}
[EventSource(Name = "MyEventSource")]
sealed class MyEventSourceClass : EventSource
{
// Global singleton instance
public static MyEventSourceClass Log = new MyEventSourceClass();
private MyEventSourceClass()
{
}
[Event(1, Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
public void TraceMessage(string message)
{
WriteEvent(1, message);
}
[Event(2, Message = "{0}({1}) - {2}: {3}", Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
public void TraceCodeLine([CallerFilePath] string filePath = "",
[CallerLineNumber] int line = 0,
[CallerMemberName] string memberName = "", string message = "")
{
WriteEvent(2, filePath, line, memberName, message);
}
// Function-level entry and exit tracing
[Event(3, Message = "Entering {0}.{1}", Opcode = EventOpcode.Start, Level = EventLevel.Informational)]
public void TraceEnter(string className, string methodName)
{
WriteEvent(3, className, methodName);
}
[Event(4, Message = "Exiting {0}.{1}", Opcode = EventOpcode.Stop, Level = EventLevel.Informational)]
public void TraceExit(string className, string methodName)
{
WriteEvent(4, className, methodName);
}
}
}
Code that uses it will look something like this:
public void DoWork(string foo)
{
using (FnTraceWrap fnTrace = new FnTraceWrap())
{
fnTrace.TraceMessage("Doing work on {0}.", foo);
/*
code ...
*/
}
}
To make the code readable, only log what you really need to (info/warning/error). Log debug messages during development, but remove most when you are finished. For trace logging, use
AOP to log simple things like method entry/exit (if you feel you need that kind of granularity).
Example:
public int SomeMethod(int arg)
{
Log.Trace("SomeClass.SomeMethod({0}), entering",arg); // A
if (arg < 0)
{
arg = -arg;
Log.Warn("Negative arg {0} was corrected", arg); // B
}
Log.Trace("SomeClass.SomeMethod({0}), returning.",arg); // C
return 2*arg;
}
In this example, the only necessary log statement is B. The log statements A and C are boilerplate, logging that you can leave to PostSharp to insert for you instead.
Also: in your example you can see that there is some form of "Action X invoked by Y", which suggests that a lot of your code could in fact be moved up to a higher level (e.g. Command/Filter).
Your proliferation of logging statements could be telling you something: that some form of design pattern could be used, which could also centralize a lot of the logging.
void DoSomething(Command command, User user)
{
Log.Info("Command {0} invoked by {1}", command, user);
command.Process(user);
}
I think it is a good option to implement something similar to filters in ASP.NET MVC. This is implement with the help of attributes and reflection. You mark every method you want to log in a certain way and enjoy. I suppose there might be a better way to do it, may be with the help of Observer pattern or something but as long as I thought about it I couldn't think of something better.
Basically such problems are called cross-cutting concerns and can be tackled with the help of AOP.
I also think that some interesting inheritance schema can be applied with log entities at the base but I would go for filters

Categories