I am trying to implement Log4Net file appender in asp.net. I have been successful implementing it. However I am not sure about correct architecture to implement it.
I can add a logger in each page and log information. However, I was thinking to centralize the logger class. May be implement a singleton pattern. But i was wondering what will happen if a request for same page comes from two different browsers. I can implement Thread Static and then every page instead of initializing their own logger would use this centralize logger class to log.
I suppose the log4net file appender or rolling file appender using a queue mechanism to write to the log file. Because only one handle of the file can be acquired to write to a file.
Can anyone help me in this regard. Am i going the right way or i will have issues down the road when there will be tens and hundreds of requests coming from different browsers.
I recommend not to use a singleton, but instead to use a logger for each controller and class that you want to log from. Loggers are cheap to create and cached by log4net - and even more so if you declare them as static within the class - and by having one per class you can change logging per class or namespace by changing the log4net configuration at runtime - say to enable some debug logging to aid diagnosing a problem in production, or to turn down some logging which is unexpectedly noisy. You can do this without recycling your app if you have your log config in a separate file.
Also if you're going to use file logging, make sure you use MinimalLock
Related
I have an ASP.NET project using .NET Core 2 and I notice that when I use the default logger provided by ASP.NET (injected into any controller as ILogger), I see log messages formatted as follows:
notice how the log level "info" is coloured. Clearly, the IDE is recognising that this is a logger message and handling it in some special way.
However, if I use NLog instead, by doing:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseNLog() // add this line!
.Build();
in Program.cs, without any further code changes
this will then route all log message to nlog processor as well which will handle logging based on nlog logging rules in nlog.config file. So, for example if I have a rule to print to console, then I see the following:
(note that the default Microsoft logger is still active! and will still print the same message again like the first picture)
Now, my real question is, is there a way to make all nlog console log messages appear the same way like the ones coming from the default logger?
You might be wondering why I need nlog console log at all since the default logger is still active anyway. That's because the default logger is only available to controllers using dependency injection and I don't see an easy way to use it in all my classes, whereas NLog is easy to add to any class by doing:
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
So, I have two options here:
Make nlog console messages recognised by the IDE similar to how it recognised the default logger's message.
Make the default Microsoft logger available to any class without needing complex dependency injection, and make sure it is still routing all messages to NLog logger (since I still need nlog's file logging rules with compression, archiving and other nlog features)
What does you layout look like in your NLog.Config file?
You can try something like this to get the layout you want.
Layout="${level:uppercase=false}: ${logger}${newline}${message}"
NLog has a ColoredConsole Target that might give you the colors you are looking for if the Layout does not do it in the ASP.Net Logger.
I've recently just discovered the power of Tracing(no clue why it took this long). The theory and practice wasn't unknown to me just the resources available in .Net for doing so. Traditionally I would just log the parts of my programs that I needed to investigate until I got an answer to any problems or confusion. As of recent this task just doesn't give me enough information and is far too tedious as my application is too big now. There are not a lot of clear resources on much of this so I have a few questions:
If I add my own trace listener source to the trace.listeners collection will that trace listener receive the trace information that can be seen in the trace.axd page when tracing is enabled in the web.config of my application?
If so how would I go about creating said listener that can receive that input? I've created my own class that implements the trace listener class and I can't seem to get any other input to be logged other than my own? Have I misunderstood something?
If there is another way to log my application line by line without having to place my own logging, that would be very very helpful. Thank you.
If I add my own trace listener source to the trace.listeners
collection will that trace listener receive the trace information that
can be seen in the trace.axd page when tracing is enabled in the
web.config of my application?
You will be able to see anything written to Trace. The trace that is written to trace.axd is a bit different from a plain vanilla TraceSource, TraceListener, etc. The biggest difference is that it uses the Trace object, which is the .NET 1.1 way of doing trace. in .NET 2.0 & later, named TraceSources are introduced.
If you register a TraceSwitch, TraceSource and TraceListener in your web config, you can enable listening to any TraceSource that you know the name of, the WCF libraries are an example.
Other places document TraceSource and TraceListener and switches better than I can, e.g. http://blog.stephencleary.com/2010/12/simple-and-easy-tracing-in-net.html or https://msdn.microsoft.com/en-us/library/ms228984(v=vs.110).aspx
If so how would I go about creating said listener that can receive
that input? I've created my own class that implements the trace
listener class and I can't seem to get any other input to be logged
other than my own?
You can start by subclassing the ConsoleLogListener or a TextWriterTraceListener. This library has many tools for dealing with the rough edges of System.Diagnostics Trace. https://essentialdiagnostics.codeplex.com/
(Because the built in library has rough edges, expect to see a few people tell you to use some other logging library, there are many, but only System.Diagnostics is built in and always available)
If there is another way to log my application line by line without
having to place my own logging, that would be very very helpful.
This requires "code weaving" or Aspect oriented programming, where you use a tool to recompile your application and add things like logging or trace everywhere or where ever a certain attribute is found. PostSharp is one such application. Memory profiles sort of give you that line by line trace as a byproduct of showing you where your application is spending most of its time.
is there any way to map 2 Models once in my application ( Mapper.CreateMap()) for example in global.asax and then wherever necessary just call Mapper.Map() in codes ?
Yes you can, and in fact that's the recommended way to configure AutoMapper. Creating the initial mappings is the (relatively) expensive part of AutoMapper, so you want to do it only once.
As you suggest, Global.asax is a good place to do it. Although it's a good idea to put it in a separate class, for example Bootstrapper, that the Application_Start method calls into, such that this class and method can also be called from your unit tests.
From the AutoMapper docs:
Where do I configure AutoMapper?
If you're using the static Mapper method, configuration only needs to happen once per AppDomain. That means the best place to put the configuration code is in application startup, such as the Global.asax file for ASP.NET applications. Typically, the configuration bootstrapper class is in its own class, and this bootstrapper class is called from the startup method.
See also this question, which has some good ideas including a suggestion from Jimmy Bogard, who wrote AutoMapper.
I'm working with Orchard CMS and it is better CMS for me. I want to understand how it does the logging and whether I can add my own logging or not. I saw that Orchard uses NullLogger class and it does no work. I've opened the App_Data.Logs folder and have seen that there are the log files. But how? I searched in code where is the trick that replaces NullLogger with log4net (I guess this is log4net, because the log format and the formatting for log4net.config are very similar) but I haven't found this.
Can somebody answer me:
How Orchard does the logging?
Whether I can add my own logger and if yes what best practices exist to do this?
Thanks, Andrey.
An Autofac module (Orchard.Logging.LoggerModule to be precise) handles that. Basically - it scans each dependency and fills all properties of type ILogger with a reference to appropriate logger instance. Each dependency gets its own logger with name equal to full type name (including namespace) of a containing class.
The NullLogger is just a placeholder so accessing the property would not throw NullReferenceExceptions before the property is being set by Autofac.
Extending the default logging is a rather complicated task as it would involve doing three things:
create a custom implementation of ILoggerFactory (just like the default Orchard.Logging.CastleLoggerFactory) and
create an Autofac module that registers that implementation in the container (like the mentioned LoggerModule does)
suppress the current default logging module by decorating your new one with [OrchardSuppressDependency("Orchard.Logging.LoggingModule")]
UPDATE
Just realized I haven't addressed the most important part of the question here:)
Yes, Orchard uses log4net so you may alter the default settings via Config/log4net.config file.
There is a great article on how Orchard Logging works. (I am not sure if it is ok to copy and paste the entire article). This is the link: Injection Logger in Orchard
So the trick is this:
Whenever a class requires a Logger instance, all it needs to do is to
declare a ILogger property, that’s it. And later, in your class, you
can use this property to Logging at anytime
And how is this done?
When Orchard web application startup, the OrchardStarter will be used
to do most of the registration work.
In a few words, it looks all the code in all projects, gets all the classes that use an ILogger property, and implements it for you (if not implemented), using Castle's logger factory.
I currently hold my resources in a database instead of resx files. I would like to be able to test whether all keys used in the application are held in the database to avoid runtime errors.
I have a custom ResourceProviderFactory to accomplish retrieving the resources.
Resources could be in aspx view pages - GetLocalResourceObject("ResourceKey") or GetGlobalResourceObject("ResourceClass", "ResourceKey").
They could be in a controller - HttpContext.GetGlobalResourceObject("ResourceClass", "ResourceKey").
I also call the resources from the core assemblies of my application without using the ASP.NET resource factory (using a singleton instead) - CoreResources.Current.GetResource("ResourceClass", "ResourceKey")
What would be the best way for me to ensure that all resources are in the database without having to waiting for a runtime exception?
The only approach I can think of is writing an app that scans your source code files and extracts all the resource keys you are using. You can then check the existence of each key in your database.
Unfortunately it is not so trivial... I don't think there is an easier way.
I would however change your ResourceProviderFactory to not throw an exception in case of a missing key. Just return some text like "Resource missing: 'xxx'" and log it so that it can be added.