Capturing log output from library using Castle Core Logging - c#

Currently depending on a library which utilizes the Castle.Core Logging abstraction. I've dug through both that library's docs, and Castle's, and can't seem to find clear explanation of how to capture log output to pipe to our logging framework of choice (NLog, in this instance). I've also dug through a few posts which touch on the topic, but dismissed as not applicable to this situation.
It should be noted that NLog works fine for the rest of the application. No errors seen in the internal logs. Just no output from this third party library.
I see the Castle.Core NLog integration, but that looks to be something to be utilized by the library depending on Castle, not one depending on the library.
So is it possible to capture log output from this library? Or do I need to reach out to the project for support?

If you own the process hosting the library, it is your responsibility to tell Castle.Core.Log which log provider to use.
Configure NLog in your application, then register NLog as the Castle Log Provider as explained in the documentation by calling
container.AddFacility<LoggingFacility>(f => f.LogUsing(LoggerImplementation.NLog) when creating your container
For your library (white) you should provide the logger factory by either setting it on the CoreAppXmlConfiguration instance, or supply your own subclass instance when initializing the library's Application object.
See https://github.com/TestStack/White/blob/master/src/TestStack.White/Configuration/CoreAppXmlConfiguration.cs#L53

Related

Propagating W3C trace context over MassTransit publisher/consumer

'm trying to support propagating the W3C trace context traceId and spanId properties from http calls -> publisher -> consumer -> http call within MassTransit (just so they show up in the logs/seq for now, but we're using Dynatrace), but am I couldn't find anything out-of-the-box here:
https://masstransit-project.com/advanced/monitoring/diagnostic-source.html
If there is nothing available I'll probably try to create something myself based on these articles:
I could find this one as an example for OpenTracing:
https://github.com/yesmarket/MassTransit.OpenTracing
And this as a reference for NServiceBus:
https://jimmybogard.com/building-end-to-end-diagnostics-and-tracing-a-primer-trace-context/
Unless anyone can suggest something that already exists?
EDIT2:
The latest versions of MassTransit propagate the trace context by default.
Enable W3C Tracing in your startup:
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
on configuring your bus call:
bus.UseInstrumentation();
EDIT:
Based on the library by Ryan Bartsch & article by Jimmy Bogard, I created this package which does what I need it to do:
https://github.com/zidad/MassTransit.ActivityTracing
I'm the author of the MassTransit.OpenTracing library you referenced, but I wrote it prior to the W3C recommendation, which looks to be quite recent (Feb 6, 2020).
My goal was that I wanted distributed tracing through a microservice architecture that had both synchronous/HTTP as well as asynchronous message broker communications. For the HTTP stuff I was using OpenTracing.Contrib.NetCore, which 'uses .NET's DiagnosticSource to instrument its code'. For the asynchronous message broker communications, I was using RabbitMQ with MassTransit, but I didn't really understand the MassTransit DiagnosticSource approach suggested on the website (and nor could I find any examples), so I decided to get into the nuts and bolts a bit and roll my own.
Long story short, it all worked as expected using Jaeger as the tracer. Interestingly, we (as in the company I work for) decided to also use DynaTrace, which operates at a much lower level and kind of removes the need for handling a lot of this stuff in code. That said, the approach is not invalid (IMO), as not everyone can afford DynaTrace (or similar APM tools).
I'll try to upgrade this library with the W3C recommendation in the coming week or 2. Let me know if you want to help with contribution/review (or if you want to go off in a different direction and roll your own is also fine)...
Dynatracing claims to integrate seamlessly with OpenTracing https://www.dynatrace.com/integrations/opentracing/ and if you use the library you mentioned and if you have your HTTP part instrumented with OpenTracing, it will work out of the box.
The only potential drawback that in the service that hosts gets an HTTP call and within the context of handling it sends or publishes a message via MassTransit, everything must be instrumented with OpenTracing, because it will start the child span using the OpenTracing API.
We do this with Datadog, so we use the Datadog OpenTracing integration library and trace the WebApi and HttpClient using OpenTracing Contrib libraries. So, the automatic instrumentation didn't work for us. But it's not hard to use those libs to instrument your app instead of using the automatic instrumentation.
The usual flow is like:
Outside -> WebApi: start a span
WebApi -> MassTransit: start a child span, inject the context to headers
MassTransit -> consumer: extract the context, start a child span
and so on
Both bits with injection and extraction are handled in the MassTransit.OpenTracing library, so, there's nothing extra to do.
With a library that your provider has to support OpenTracing it's usually like this:
Configure the tracer of the provider
Set the OpenTracing global tracer to the wrapper, using the integration library from your provider
When you create a span with OpenTracing, it will create a vendor-specific span and wrap it in OpenTracing span

Design principles to consider when wrapping a 3rd party logger like log4net

I'm creating a logger for a company that has several types of .NET projects (Windows Services, ASP.NET, etc), and I was considering using log4net as my logger, but I don't want to be married to log4net, so I was thinking of wrapping it in my own assembly. I realize some developers don't recommend wrapping log4net because that would be an anti-pattern, but assuming I was going that route anyway, I had some questions:
I am planning to use the design principles mentioned in this article to design my wrapper (using factory method, interfaces, and reflection, I can simply decide which logger I want to use (whether log4net, elmah or something else) by specifying in the config file:
https://www.simple-talk.com/dotnet/.net-framework/designing-c-software-with-interfaces/
Question is:
Should I create this logger project in a separate Visual Studio solution and just use the dll in my client applications? If so, where would the configuration details for log4net go? Would that be supplied by the client application's config file? If so, is that good design? For instance, if I decided to switch away from log4net to a different logging framework, I would not only have to change the config setting to specify the new concrete logger's assembly/class name, but would also have to remove the log4net config entries (and perhaps add the new logger's config entries). Is this considered as an acceptable design approach?
Oh my goodness your timing is awesome. And that article is very relevant to me so thanks! I am doing this very same thing right now. I realized that log4net is a decent logger, but a terrible library for making a logger.
I agree with the article, in that you should not directly expose to log4net. Unless this is a small app it would be too difficult to switch later. And log4net is showing age so that may happen. I like the interface approach overall.
But, wrapping log4net it is a pain in the butt. So in doing my prototype wrapper I feel like I rewrote 50% of log4net, and discarded 25%. Some issues I found:
log4net will grab the "caller information" for you. Normally that is great. But if you wrap log4net, the caller information will point to your logger. So you will have to explicitly grab it yourself. But log4net doesn't provide a way for you to override the caller information. So now you will have to create your own fields for the caller's file, line number, class, and package. Thus, not only do you not gain the benefit here, but it is actually more work than just doing it yourself.
Log4net uses the old pre C#-4.0 method of grabbing the caller information which is slow.
Your will be unable to completely wrap log4net without wrapping the configuration. The caller has to configure the loggers either in code or in their app.config. If they do it in their app.config then they are putting log4net specific stuff in their app, so you failed to hide it with your wrapper. But if you have your wrapper code automatically perform the configuration, you just lost the flexibility of log4net. The third option is to make your own configuration, but then what good did log4net do for you? You just rewrote another piece of it.
You are stuck with the log levels that come with log4net. In our app, we want "categories" instead of "levels" which I then have to map to the log4net "levels" under the hood. Now, all the predefined log4net filters are of no use to me.
Anyone using your wrapper still has to reference log4net in their project anyway.
If your wrapper needs a way to handle errors, or pass them back to the caller, you will have trouble. log4net has its own internal error handling and you will need to hook into that and provide your own. Otherwise, errors (like a misconfigured appender) will just go out to the console. If it was designed as a library for making loggers, it would just throw the exception back up or provide a simple event.
One thing we wanted to get out of log4net is the ability to write to different outputs without us us having to write that code ourselves. Ex: I've never written to the event log, and I think log4net can do that. But it might be easier for me to rip out the Event logging code, rather than to try and wrap that. Same thing with filters.
There are some other problems I had with log4net that aren't directly related to trying to wrap it necessarily.
The code is old. The interfaces don't use generics where they should. Lots of object.
They use the old System.Collections collections. Similar to #1.
It has ifdefs for .NET 1 versus 2, and ifdefs for the obsolete compact framework. ugh.
It is designed to log strings, not structured objects. I made my own code to do so, and so did these people: http://stephenjamescode.blogspot.com/2014/01/logging-custom-objects-and-fields-with.html and http://element533.blogspot.com/2010/05/mapping-message-object-properties-to.html but this feels like basic functionality.
It doesn't support CSV and it is cumbersome to add. http://element533.blogspot.com/2010/05/writing-to-csv-using-log4net.html
It doesn't have any kind of logging "service"
It doesn't provide a way to read or parse the log.
I found it was more effort to configure the appenders than to write your own. Ex: I mapped a bunch of fields to the AdoNetAppender, but it would have taken me less time to just rewrite AdoNetAppender. Debugging a database field mapping in XML is harder than trying to debug the equivalent C# + ADO.NET code. The XML is more verbose and less type safe. This might be specific to me because I had a very structured set of data and a lot of fields.
Sorry for the really long post, I have lots and lots of thoughts on this topic. I don't really dislike log4net, I just think it is out of date and if you are wrapping it, you might be better off writing your own.

Exposing ILogger in a loosely coupled fashion

I am the author of a C# open-source wrapper for a 3rd party service. I need to expose an ILogger facility (such as https://logging.apache.org/log4net/release/sdk/log4net.Core.ILogger.html) to log specific events and errors.
I could just go on and add a major logger such as Log4Net, but I don't want the wrapper to be tied to a specific logger.
I could just add an IoC container to easily solve this with a constructor dependecy injection but then again I don't want my wrapper to be tied to any specific IoC.
On the other hand it would be great if I could somehow expose the logging events to the consuming app (which is the one responsible for logging anyway) with the wrapper being agnostic towards its consumer.
Any thoughts on how to achieve this?
Projects will often provide their own abstraction. A default logger is bundled so things work out of the box, but you can easily configure the logging provider, as seen in ServiceStack logging and NServiceBus logging. For example:
LogManager.LogFactory = new Log4NetFactory(true);
There is also Common.Logging, which was designed to address the logging framework dependency issue. However, I have not seen it used extensively in major open source projects even though it's been around a while.

Optional logging dependency for C# library?

I've been working on a library in C# and would like to offer capability for it automatically log all exceptions. Ideally, I'd like it to use log4net, thus allowing the client to configure the log however they like (i.e. they can redirect it to the EventLog or a database or what have you).
However, I would like to avoid having the logging dependency if they chose not to use the logging feature. Is this doable?
In other words, is there a way I can optionally have a log4net dependency, depending on what the client sets in config file?
The obvious answer is to use the System.Diagnostics.Trace subsystem with a custom TraceSource. That way you can set up, in the configuration file, any TraceListener you'd like, including log4net, EventLog, text files, Console, or XML files.
If you added a log4net TraceListener then the dependency would be loaded at runtime, and not compiled in. The Trace subsystem has become quite powerful since its inception, and I recommend you look into it.
You can use the tracing sub-system that is already built into .NET - it is configuration controlled.
I wouldn't add a dependency myself - simply emit messages through the tracing API - the client can decide how to log them if they so wish.
Personally I prefer the Log4Net API to that provided by System.Diagnostics.Trace.
So I have my own abstraction layer that uses a provider-model design pattern, and exposes an API similar to log4net. I can then plug in a log4net provider, but am free to replace it with a different provider (e.g. System.Diagnostics.Trace; EntLib) in the future.
The implementation is very similar to this one.
By doing this, applications have no direct dependency on the underlying logging provider, and you can easily switch to a different provider if you (or your customers) have other preferences.

Notification or Alerts Framework for .NET C# Component

I am looking for a Notification or Alerts framework that can be used in my application as a separate module, I can just use the features of the framework.Are there any good ones?.
I need frameworks that dont use to much dll from other vendors to do some jobs..just connected to .net framework dlls
notifcations like email as basic...
We are using log4net and have found great flexibility with it. We also have our own wrapper class which is used in all of our projects allowing us to use static methods for writing to the defined logs. Log4net comes with one dll, and of course our wrapper dll. It is easy to extend this for added functionality, our wrapper class now allows us to write to the windows event logs if/when needed.
There are plenty of examples of how to implement log4net, and it provides alot of ways to write/send log information:
http://logging.apache.org/log4net/release/config-examples.html
Example implementation of our wrapper:
Log.Error("Message", this);
Log.Error("Message", Exception, this);
Log.Error("Message", Exception, Type);
Log.Info("Message", this);
Log.Warn("Message", this);
Something like log4Net? or a messaging queue system, sks MSMQ
the microsoft enterprise logging module of the enterprise framework can be configured for your purpose. it supports a variety of channels including email and trace file. it can be reconfigured through a change in the configuration file of your app.

Categories

Resources