Injecting properties into LoggingEvent

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Injecting properties into LoggingEvent

Nicholas Duane

Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?


The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:


public static class Logging

{

    public static void LogEvent(this ILog logger, Category category, IEvent evnt)

    {

        if ((category != null) && (evnt != null))

            {

            evnt.SetCategory(category.Name);

            LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,

                    logger.Logger.Name, Level.Emergency, evnt, null);

            le.Properties["category"] = category.Name;

            logger.Logger.Log(le);

            }

    }

}


So for instance when a user does the following:


logger.Error("this is my error message");

or

logger.Warn("this is my warning message");

or

logger.Info("this is my info message");


I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:


logger.Debug("this is my debug message");

or

logger.Trace("this is my trace message");


I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?


I also posted this at:


http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent


Thanks,

Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Dominik Psenner

What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.

A. Implement an extension class for the ILog interface
B. Implement a custom ILog interface implementation and a LoggerFactory.
C. Define custom loglevels
D. Use thread context properties altogether with custom format layouts
E. Log "complex" classes that hold your category information and find a way to format them

There might be more things that you could do..


On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:

Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?


The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:


public static class Logging

{

    public static void LogEvent(this ILog logger, Category category, IEvent evnt)

    {

        if ((category != null) && (evnt != null))

            {

            evnt.SetCategory(category.Name);

            LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,

                    logger.Logger.Name, Level.Emergency, evnt, null);

            le.Properties["category"] = category.Name;

            logger.Logger.Log(le);

            }

    }

}


So for instance when a user does the following:


logger.Error("this is my error message");

or

logger.Warn("this is my warning message");

or

logger.Info("this is my info message");


I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:


logger.Debug("this is my debug message");

or

logger.Trace("this is my trace message");


I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?


I also posted this at:


http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent


Thanks,

Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Nicholas Duane

Thank you for the suggestions.


We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:


logger.Warn("this is my warning message");


logger.Error("this is my error message");


logger.Info("this is my info message");


In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:


logger.Error(...);

logger.Warn(...);


What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.


By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Saturday, October 22, 2016 1:29 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.

A. Implement an extension class for the ILog interface
B. Implement a custom ILog interface implementation and a LoggerFactory.
C. Define custom loglevels
D. Use thread context properties altogether with custom format layouts
E. Log "complex" classes that hold your category information and find a way to format them

There might be more things that you could do..


On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:

Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?


The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:


public static class Logging

{

    public static void LogEvent(this ILog logger, Category category, IEvent evnt)

    {

        if ((category != null) && (evnt != null))

            {

            evnt.SetCategory(category.Name);

            LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,

                    logger.Logger.Name, Level.Emergency, evnt, null);

            le.Properties["category"] = category.Name;

            logger.Logger.Log(le);

            }

    }

}


So for instance when a user does the following:


logger.Error("this is my error message");

or

logger.Warn("this is my warning message");

or

logger.Info("this is my info message");


I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:


logger.Debug("this is my debug message");

or

logger.Trace("this is my trace message");


I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?


I also posted this at:


http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent


Thanks,

Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Dominik Psenner

Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.


On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:

Thank you for the suggestions.


We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:


logger.Warn("this is my warning message");


logger.Error("this is my error message");


logger.Info("this is my info message");


In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:


logger.Error(...);

logger.Warn(...);


What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.


By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Saturday, October 22, 2016 1:29 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.

A. Implement an extension class for the ILog interface
B. Implement a custom ILog interface implementation and a LoggerFactory.
C. Define custom loglevels
D. Use thread context properties altogether with custom format layouts
E. Log "complex" classes that hold your category information and find a way to format them

There might be more things that you could do..


On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:

Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?


The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:


public static class Logging

{

    public static void LogEvent(this ILog logger, Category category, IEvent evnt)

    {

        if ((category != null) && (evnt != null))

            {

            evnt.SetCategory(category.Name);

            LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,

                    logger.Logger.Name, Level.Emergency, evnt, null);

            le.Properties["category"] = category.Name;

            logger.Logger.Log(le);

            }

    }

}


So for instance when a user does the following:


logger.Error("this is my error message");

or

logger.Warn("this is my warning message");

or

logger.Info("this is my info message");


I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:


logger.Debug("this is my debug message");

or

logger.Trace("this is my trace message");


I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?


I also posted this at:


http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent


Thanks,

Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Nicholas Duane

Is there a way for me to add properties to a LoggingEvent without the user doing anything out of the ordinary.  Maybe it's even best to assume an existing application which is using log4net.  I would like to take this existing log4net application and without them changing any code, configuration changes are ok, I would like to add properties to each LoggingEvent which is created from their log statements like:


logger.Error();

logger.Info();

logger.Debug();

etc.


such that I could use the PropertyFilter filter to filter out events?  I want to set a property based on the level of the event.  I could of course use the LevelRangeFilter but in other cases I'm using the PropertyFilter and was figuring it might be nice to do it the same for all events.


This other case where I'm using the PropertyFilter is for new events we've introduced.  These are what we call "compliance" and "business" events.  We originally introduced a "compliance" event and at that time I introduced a custom level for that.  However, I'm trying to move away from defining custom levels and instead use a property on the event to distinguish its "category".  For these new events which don't fit nicely into the level gradient I've introduced a method for developers to use to log them called LogEvent().  They will pass in their logger, the category of the event, and the event.  In this scenario it's easy for me to set properties on the LoggingEvent.  However, for what we call the diagnostic events, those that are logged using the methods exposed by log4net, we don't want them to have to do anything different than they were doing.  If they want to log an error they would still use:


logger.Error("this is my error");


or a warning:


logger.Warn("this is my warning");


etc.


Ideally I would like to set the "category" on those events also so that by the time they make it to the appender it has this "category" property.  Is there a way to do that?


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Sunday, October 23, 2016 9:18 AM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.


On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:

Thank you for the suggestions.


We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:


logger.Warn("this is my warning message");


logger.Error("this is my error message");


logger.Info("this is my info message");


In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:


logger.Error(...);

logger.Warn(...);


What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.


By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Saturday, October 22, 2016 1:29 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.

A. Implement an extension class for the ILog interface
B. Implement a custom ILog interface implementation and a LoggerFactory.
C. Define custom loglevels
D. Use thread context properties altogether with custom format layouts
E. Log "complex" classes that hold your category information and find a way to format them

There might be more things that you could do..


On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:

Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?


The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:


public static class Logging

{

    public static void LogEvent(this ILog logger, Category category, IEvent evnt)

    {

        if ((category != null) && (evnt != null))

            {

            evnt.SetCategory(category.Name);

            LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,

                    logger.Logger.Name, Level.Emergency, evnt, null);

            le.Properties["category"] = category.Name;

            logger.Logger.Log(le);

            }

    }

}


So for instance when a user does the following:


logger.Error("this is my error message");

or

logger.Warn("this is my warning message");

or

logger.Info("this is my info message");


I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:


logger.Debug("this is my debug message");

or

logger.Trace("this is my trace message");


I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?


I also posted this at:


http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent


Thanks,

Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Dominik Psenner

Responding inline..

On 23 Oct 2016 4:04 p.m., "Nicholas Duane" <[hidden email]> wrote:
>
> Is there a way for me to add properties to a LoggingEvent without the user doing anything out of the ordinary.  Maybe it's even best to assume an existing application which is using log4net. I would like to take this existing log4net application and without them changing any code, configuration changes are ok, I would like to add properties to each LoggingEvent which is created from their log statements like:
>
>
> logger.Error();
>
> logger.Info();
>
> logger.Debug();
>
> etc.
>
>

That requirement sounds like you would like to:

// thread properties... log4net.LogicalThreadContext.Properties["CustomColumn"] = "Custom value"; log.Info("Message");

// ...or global properties log4net.GlobalContext.Properties["CustomColumn"] = "Custom value";

These automatically set these properties on the logging events and you can then filter those with a propertyfilter as you write here:

> such that I could use the PropertyFilter filter to filter out events?  I want to set a property based on the level of the event.  I could of course use the LevelRangeFilter but in other cases I'm using the PropertyFilter and was figuring it might be nice to do it the same for all events.
>
>
> This other case where I'm using the PropertyFilter is for new events we've introduced.  These are what we call "compliance" and "business" events.  We originally introduced a "compliance" event and at that time I introduced a custom level for that.  However, I'm trying to move away from defining custom levels and instead use a property on the event to distinguish its "category".  For these new events which don't fit nicely into the level gradient I've introduced a method for developers to use to log them called LogEvent().  They will pass in their logger, the category of the event, and the event.  In this scenario it's easy for me to set properties on the LoggingEvent.

To me this sounds like you are trying to force the logging framework to do something different than the rest of the application logs do. If thats the case, then let me warn you that it might not be a good idea. Logs could be only a byproduct of the feature you would like to implement. If you are implementing application features through the logging framework, logging is too smart and does too much. Try to design your applocation so that it could do its job even if logging was not there.

However it sounds like this works for you, therefore I do not try to work out anything.

>  However, for what we call the diagnostic events, those that are logged using the methods exposed by log4net, we don't want them to have to do anything different than they were doing.  If they want to log an error they would still use:
>
>
> logger.Error("this is my error");
>
>
> or a warning:
>
>
> logger.Warn("this is my warning");
>
>
> etc.
>
>
> Ideally I would like to set the "category" on those events also so that by the time they make it to the appender it has this "category" property.  Is there a way to do that?

This sounds like this:

http://stackoverflow.com/questions/9015432/how-can-i-inject-a-property-for-only-one-call-in-log4net

Best regards,
Dominik

>
>
> Thanks,
>
> Nick
>
>
> ________________________________
> From: Dominik Psenner <[hidden email]>
> Sent: Sunday, October 23, 2016 9:18 AM
>
> To: Log4NET User
> Subject: Re: Injecting properties into LoggingEvent
>  
>
> Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.
>
>
> On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:
>>
>> Thank you for the suggestions.
>>
>>
>> We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:
>>
>>
>> logger.Warn("this is my warning message");
>>
>>
>> logger.Error("this is my error message");
>>
>>
>> logger.Info("this is my info message");
>>
>>
>> In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:
>>
>>
>> logger.Error(...);
>>
>> logger.Warn(...);
>>
>>
>> What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.
>>
>>
>> By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.
>>
>>
>> Thanks,
>>
>> Nick
>>
>>
>> ________________________________
>> From: Dominik Psenner <[hidden email]>
>> Sent: Saturday, October 22, 2016 1:29 PM
>> To: Log4NET User
>> Subject: Re: Injecting properties into LoggingEvent
>>  
>>
>> What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.
>>
>> A. Implement an extension class for the ILog interface
>> B. Implement a custom ILog interface implementation and a LoggerFactory.
>> C. Define custom loglevels
>> D. Use thread context properties altogether with custom format layouts
>> E. Log "complex" classes that hold your category information and find a way to format them
>>
>> There might be more things that you could do..
>>
>>
>> On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:
>>>
>>> Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?
>>>
>>>
>>> The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:
>>>
>>>
>>> public static class Logging
>>>
>>> {
>>>
>>>     public static void LogEvent(this ILog logger, Category category, IEvent evnt)
>>>
>>>     {
>>>
>>>         if ((category != null) && (evnt != null))
>>>
>>>             {
>>>
>>>             evnt.SetCategory(category.Name);
>>>
>>>             LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,
>>>
>>>                     logger.Logger.Name, Level.Emergency, evnt, null);
>>>
>>>             le.Properties["category"] = category.Name;
>>>
>>>             logger.Logger.Log(le);
>>>
>>>             }
>>>
>>>     }
>>>
>>> }
>>>
>>>
>>> So for instance when a user does the following:
>>>
>>>
>>> logger.Error("this is my error message");
>>>
>>> or
>>>
>>> logger.Warn("this is my warning message");
>>>
>>> or
>>>
>>> logger.Info("this is my info message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:
>>>
>>>
>>> logger.Debug("this is my debug message");
>>>
>>> or
>>>
>>> logger.Trace("this is my trace message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?
>>>
>>>
>>> I also posted this at:
>>>
>>>
>>> http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent
>>>
>>>
>>> Thanks,
>>>
>>> Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Nicholas Duane

Thanks.  I think I'm not quite explaining it well enough.  While I would like to set properties on the LoggingEvent class, it could not be accomplished similar to the way you suggest.  The reason is that the property I want to set, "category", would be based on the level the user is logging the event at and thus could not be done until the logging method was called.


I don't think I'm asking the logging framework to do something way out of the ordinary.  All I'm trying to do is set a property based on the level, and I would like to do that without the user having to do anything, other than maybe including some config code which would allow me to inject my code into the equation.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Sunday, October 23, 2016 3:13 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Responding inline..

On 23 Oct 2016 4:04 p.m., "Nicholas Duane" <[hidden email]> wrote:
>
> Is there a way for me to add properties to a LoggingEvent without the user doing anything out of the ordinary.  Maybe it's even best to assume an existing application which is using log4net. I would like to take this existing log4net application and without them changing any code, configuration changes are ok, I would like to add properties to each LoggingEvent which is created from their log statements like:
>
>
> logger.Error();
>
> logger.Info();
>
> logger.Debug();
>
> etc.
>
>

That requirement sounds like you would like to:

// thread properties... log4net.LogicalThreadContext.Properties["CustomColumn"] = "Custom value"; log.Info("Message");

// ...or global properties log4net.GlobalContext.Properties["CustomColumn"] = "Custom value";

These automatically set these properties on the logging events and you can then filter those with a propertyfilter as you write here:

> such that I could use the PropertyFilter filter to filter out events?  I want to set a property based on the level of the event.  I could of course use the LevelRangeFilter but in other cases I'm using the PropertyFilter and was figuring it might be nice to do it the same for all events.
>
>
> This other case where I'm using the PropertyFilter is for new events we've introduced.  These are what we call "compliance" and "business" events.  We originally introduced a "compliance" event and at that time I introduced a custom level for that.  However, I'm trying to move away from defining custom levels and instead use a property on the event to distinguish its "category".  For these new events which don't fit nicely into the level gradient I've introduced a method for developers to use to log them called LogEvent().  They will pass in their logger, the category of the event, and the event.  In this scenario it's easy for me to set properties on the LoggingEvent.

To me this sounds like you are trying to force the logging framework to do something different than the rest of the application logs do. If thats the case, then let me warn you that it might not be a good idea. Logs could be only a byproduct of the feature you would like to implement. If you are implementing application features through the logging framework, logging is too smart and does too much. Try to design your applocation so that it could do its job even if logging was not there.

However it sounds like this works for you, therefore I do not try to work out anything.

>  However, for what we call the diagnostic events, those that are logged using the methods exposed by log4net, we don't want them to have to do anything different than they were doing.  If they want to log an error they would still use:
>
>
> logger.Error("this is my error");
>
>
> or a warning:
>
>
> logger.Warn("this is my warning");
>
>
> etc.
>
>
> Ideally I would like to set the "category" on those events also so that by the time they make it to the appender it has this "category" property.  Is there a way to do that?

This sounds like this:

http://stackoverflow.com/questions/9015432/how-can-i-inject-a-property-for-only-one-call-in-log4net

Best regards,
Dominik

>
>
> Thanks,
>
> Nick
>
>
> ________________________________
> From: Dominik Psenner <[hidden email]>
> Sent: Sunday, October 23, 2016 9:18 AM
>
> To: Log4NET User
> Subject: Re: Injecting properties into LoggingEvent
>  
>
> Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.
>
>
> On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:
>>
>> Thank you for the suggestions.
>>
>>
>> We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:
>>
>>
>> logger.Warn("this is my warning message");
>>
>>
>> logger.Error("this is my error message");
>>
>>
>> logger.Info("this is my info message");
>>
>>
>> In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:
>>
>>
>> logger.Error(...);
>>
>> logger.Warn(...);
>>
>>
>> What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.
>>
>>
>> By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.
>>
>>
>> Thanks,
>>
>> Nick
>>
>>
>> ________________________________
>> From: Dominik Psenner <[hidden email]>
>> Sent: Saturday, October 22, 2016 1:29 PM
>> To: Log4NET User
>> Subject: Re: Injecting properties into LoggingEvent
>>  
>>
>> What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.
>>
>> A. Implement an extension class for the ILog interface
>> B. Implement a custom ILog interface implementation and a LoggerFactory.
>> C. Define custom loglevels
>> D. Use thread context properties altogether with custom format layouts
>> E. Log "complex" classes that hold your category information and find a way to format them
>>
>> There might be more things that you could do..
>>
>>
>> On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:
>>>
>>> Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?
>>>
>>>
>>> The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:
>>>
>>>
>>> public static class Logging
>>>
>>> {
>>>
>>>     public static void LogEvent(this ILog logger, Category category, IEvent evnt)
>>>
>>>     {
>>>
>>>         if ((category != null) && (evnt != null))
>>>
>>>             {
>>>
>>>             evnt.SetCategory(category.Name);
>>>
>>>             LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,
>>>
>>>                     logger.Logger.Name, Level.Emergency, evnt, null);
>>>
>>>             le.Properties["category"] = category.Name;
>>>
>>>             logger.Logger.Log(le);
>>>
>>>             }
>>>
>>>     }
>>>
>>> }
>>>
>>>
>>> So for instance when a user does the following:
>>>
>>>
>>> logger.Error("this is my error message");
>>>
>>> or
>>>
>>> logger.Warn("this is my warning message");
>>>
>>> or
>>>
>>> logger.Info("this is my info message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:
>>>
>>>
>>> logger.Debug("this is my debug message");
>>>
>>> or
>>>
>>> logger.Trace("this is my trace message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?
>>>
>>>
>>> I also posted this at:
>>>
>>>
>>> http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent
>>>
>>>
>>> Thanks,
>>>
>>> Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Dominik Psenner

In that case you can pipe your log events through a custom appender that you implement. That custom appender can implement your logic of events as smart as you need it and then call inner appenders to process events. See the bufferingappenderskeleton.


On 24 Oct 2016 12:52 a.m., "Nicholas Duane" <[hidden email]> wrote:

Thanks.  I think I'm not quite explaining it well enough.  While I would like to set properties on the LoggingEvent class, it could not be accomplished similar to the way you suggest.  The reason is that the property I want to set, "category", would be based on the level the user is logging the event at and thus could not be done until the logging method was called.


I don't think I'm asking the logging framework to do something way out of the ordinary.  All I'm trying to do is set a property based on the level, and I would like to do that without the user having to do anything, other than maybe including some config code which would allow me to inject my code into the equation.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Sunday, October 23, 2016 3:13 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Responding inline..

On 23 Oct 2016 4:04 p.m., "Nicholas Duane" <[hidden email]> wrote:
>
> Is there a way for me to add properties to a LoggingEvent without the user doing anything out of the ordinary.  Maybe it's even best to assume an existing application which is using log4net. I would like to take this existing log4net application and without them changing any code, configuration changes are ok, I would like to add properties to each LoggingEvent which is created from their log statements like:
>
>
> logger.Error();
>
> logger.Info();
>
> logger.Debug();
>
> etc.
>
>

That requirement sounds like you would like to:

// thread properties... log4net.LogicalThreadContext.Properties["CustomColumn"] = "Custom value"; log.Info("Message");

// ...or global properties log4net.GlobalContext.Properties["CustomColumn"] = "Custom value";

These automatically set these properties on the logging events and you can then filter those with a propertyfilter as you write here:

> such that I could use the PropertyFilter filter to filter out events?  I want to set a property based on the level of the event.  I could of course use the LevelRangeFilter but in other cases I'm using the PropertyFilter and was figuring it might be nice to do it the same for all events.
>
>
> This other case where I'm using the PropertyFilter is for new events we've introduced.  These are what we call "compliance" and "business" events.  We originally introduced a "compliance" event and at that time I introduced a custom level for that.  However, I'm trying to move away from defining custom levels and instead use a property on the event to distinguish its "category".  For these new events which don't fit nicely into the level gradient I've introduced a method for developers to use to log them called LogEvent().  They will pass in their logger, the category of the event, and the event.  In this scenario it's easy for me to set properties on the LoggingEvent.

To me this sounds like you are trying to force the logging framework to do something different than the rest of the application logs do. If thats the case, then let me warn you that it might not be a good idea. Logs could be only a byproduct of the feature you would like to implement. If you are implementing application features through the logging framework, logging is too smart and does too much. Try to design your applocation so that it could do its job even if logging was not there.

However it sounds like this works for you, therefore I do not try to work out anything.

>  However, for what we call the diagnostic events, those that are logged using the methods exposed by log4net, we don't want them to have to do anything different than they were doing.  If they want to log an error they would still use:
>
>
> logger.Error("this is my error");
>
>
> or a warning:
>
>
> logger.Warn("this is my warning");
>
>
> etc.
>
>
> Ideally I would like to set the "category" on those events also so that by the time they make it to the appender it has this "category" property.  Is there a way to do that?

This sounds like this:

http://stackoverflow.com/questions/9015432/how-can-i-inject-a-property-for-only-one-call-in-log4net

Best regards,
Dominik

>
>
> Thanks,
>
> Nick
>
>
> ________________________________
> From: Dominik Psenner <[hidden email]>
> Sent: Sunday, October 23, 2016 9:18 AM
>
> To: Log4NET User
> Subject: Re: Injecting properties into LoggingEvent
>  
>
> Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.
>
>
> On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:
>>
>> Thank you for the suggestions.
>>
>>
>> We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:
>>
>>
>> logger.Warn("this is my warning message");
>>
>>
>> logger.Error("this is my error message");
>>
>>
>> logger.Info("this is my info message");
>>
>>
>> In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:
>>
>>
>> logger.Error(...);
>>
>> logger.Warn(...);
>>
>>
>> What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.
>>
>>
>> By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.
>>
>>
>> Thanks,
>>
>> Nick
>>
>>
>> ________________________________
>> From: Dominik Psenner <[hidden email]>
>> Sent: Saturday, October 22, 2016 1:29 PM
>> To: Log4NET User
>> Subject: Re: Injecting properties into LoggingEvent
>>  
>>
>> What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.
>>
>> A. Implement an extension class for the ILog interface
>> B. Implement a custom ILog interface implementation and a LoggerFactory.
>> C. Define custom loglevels
>> D. Use thread context properties altogether with custom format layouts
>> E. Log "complex" classes that hold your category information and find a way to format them
>>
>> There might be more things that you could do..
>>
>>
>> On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:
>>>
>>> Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?
>>>
>>>
>>> The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:
>>>
>>>
>>> public static class Logging
>>>
>>> {
>>>
>>>     public static void LogEvent(this ILog logger, Category category, IEvent evnt)
>>>
>>>     {
>>>
>>>         if ((category != null) && (evnt != null))
>>>
>>>             {
>>>
>>>             evnt.SetCategory(category.Name);
>>>
>>>             LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,
>>>
>>>                     logger.Logger.Name, Level.Emergency, evnt, null);
>>>
>>>             le.Properties["category"] = category.Name;
>>>
>>>             logger.Logger.Log(le);
>>>
>>>             }
>>>
>>>     }
>>>
>>> }
>>>
>>>
>>> So for instance when a user does the following:
>>>
>>>
>>> logger.Error("this is my error message");
>>>
>>> or
>>>
>>> logger.Warn("this is my warning message");
>>>
>>> or
>>>
>>> logger.Info("this is my info message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:
>>>
>>>
>>> logger.Debug("this is my debug message");
>>>
>>> or
>>>
>>> logger.Trace("this is my trace message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?
>>>
>>>
>>> I also posted this at:
>>>
>>>
>>> http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent
>>>
>>>
>>> Thanks,
>>>
>>> Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Dominik Psenner

Ps: this might also something that you should look at.

http://stackoverflow.com/questions/17120943/how-add-custom-properties-in-appenderskeleton-log4net

And note too that the layoutpattern gets a applicationsetting pattern string to include application settings in the formatted logevent string. You can try that feature by building from source or by using the relerase candidate binaries.

It is unclear where these "categories" come from if the developers do not maintain them. Therefore I am not able to understand your requirements.


On 24 Oct 2016 7:21 a.m., "Dominik Psenner" <[hidden email]> wrote:

In that case you can pipe your log events through a custom appender that you implement. That custom appender can implement your logic of events as smart as you need it and then call inner appenders to process events. See the bufferingappenderskeleton.


On 24 Oct 2016 12:52 a.m., "Nicholas Duane" <[hidden email]> wrote:

Thanks.  I think I'm not quite explaining it well enough.  While I would like to set properties on the LoggingEvent class, it could not be accomplished similar to the way you suggest.  The reason is that the property I want to set, "category", would be based on the level the user is logging the event at and thus could not be done until the logging method was called.


I don't think I'm asking the logging framework to do something way out of the ordinary.  All I'm trying to do is set a property based on the level, and I would like to do that without the user having to do anything, other than maybe including some config code which would allow me to inject my code into the equation.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Sunday, October 23, 2016 3:13 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Responding inline..

On 23 Oct 2016 4:04 p.m., "Nicholas Duane" <[hidden email]> wrote:
>
> Is there a way for me to add properties to a LoggingEvent without the user doing anything out of the ordinary.  Maybe it's even best to assume an existing application which is using log4net. I would like to take this existing log4net application and without them changing any code, configuration changes are ok, I would like to add properties to each LoggingEvent which is created from their log statements like:
>
>
> logger.Error();
>
> logger.Info();
>
> logger.Debug();
>
> etc.
>
>

That requirement sounds like you would like to:

// thread properties... log4net.LogicalThreadContext.Properties["CustomColumn"] = "Custom value"; log.Info("Message");

// ...or global properties log4net.GlobalContext.Properties["CustomColumn"] = "Custom value";

These automatically set these properties on the logging events and you can then filter those with a propertyfilter as you write here:

> such that I could use the PropertyFilter filter to filter out events?  I want to set a property based on the level of the event.  I could of course use the LevelRangeFilter but in other cases I'm using the PropertyFilter and was figuring it might be nice to do it the same for all events.
>
>
> This other case where I'm using the PropertyFilter is for new events we've introduced.  These are what we call "compliance" and "business" events.  We originally introduced a "compliance" event and at that time I introduced a custom level for that.  However, I'm trying to move away from defining custom levels and instead use a property on the event to distinguish its "category".  For these new events which don't fit nicely into the level gradient I've introduced a method for developers to use to log them called LogEvent().  They will pass in their logger, the category of the event, and the event.  In this scenario it's easy for me to set properties on the LoggingEvent.

To me this sounds like you are trying to force the logging framework to do something different than the rest of the application logs do. If thats the case, then let me warn you that it might not be a good idea. Logs could be only a byproduct of the feature you would like to implement. If you are implementing application features through the logging framework, logging is too smart and does too much. Try to design your applocation so that it could do its job even if logging was not there.

However it sounds like this works for you, therefore I do not try to work out anything.

>  However, for what we call the diagnostic events, those that are logged using the methods exposed by log4net, we don't want them to have to do anything different than they were doing.  If they want to log an error they would still use:
>
>
> logger.Error("this is my error");
>
>
> or a warning:
>
>
> logger.Warn("this is my warning");
>
>
> etc.
>
>
> Ideally I would like to set the "category" on those events also so that by the time they make it to the appender it has this "category" property.  Is there a way to do that?

This sounds like this:

http://stackoverflow.com/questions/9015432/how-can-i-inject-a-property-for-only-one-call-in-log4net

Best regards,
Dominik

>
>
> Thanks,
>
> Nick
>
>
> ________________________________
> From: Dominik Psenner <[hidden email]>
> Sent: Sunday, October 23, 2016 9:18 AM
>
> To: Log4NET User
> Subject: Re: Injecting properties into LoggingEvent
>  
>
> Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.
>
>
> On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:
>>
>> Thank you for the suggestions.
>>
>>
>> We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:
>>
>>
>> logger.Warn("this is my warning message");
>>
>>
>> logger.Error("this is my error message");
>>
>>
>> logger.Info("this is my info message");
>>
>>
>> In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:
>>
>>
>> logger.Error(...);
>>
>> logger.Warn(...);
>>
>>
>> What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.
>>
>>
>> By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.
>>
>>
>> Thanks,
>>
>> Nick
>>
>>
>> ________________________________
>> From: Dominik Psenner <[hidden email]>
>> Sent: Saturday, October 22, 2016 1:29 PM
>> To: Log4NET User
>> Subject: Re: Injecting properties into LoggingEvent
>>  
>>
>> What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.
>>
>> A. Implement an extension class for the ILog interface
>> B. Implement a custom ILog interface implementation and a LoggerFactory.
>> C. Define custom loglevels
>> D. Use thread context properties altogether with custom format layouts
>> E. Log "complex" classes that hold your category information and find a way to format them
>>
>> There might be more things that you could do..
>>
>>
>> On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:
>>>
>>> Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?
>>>
>>>
>>> The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:
>>>
>>>
>>> public static class Logging
>>>
>>> {
>>>
>>>     public static void LogEvent(this ILog logger, Category category, IEvent evnt)
>>>
>>>     {
>>>
>>>         if ((category != null) && (evnt != null))
>>>
>>>             {
>>>
>>>             evnt.SetCategory(category.Name);
>>>
>>>             LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,
>>>
>>>                     logger.Logger.Name, Level.Emergency, evnt, null);
>>>
>>>             le.Properties["category"] = category.Name;
>>>
>>>             logger.Logger.Log(le);
>>>
>>>             }
>>>
>>>     }
>>>
>>> }
>>>
>>>
>>> So for instance when a user does the following:
>>>
>>>
>>> logger.Error("this is my error message");
>>>
>>> or
>>>
>>> logger.Warn("this is my warning message");
>>>
>>> or
>>>
>>> logger.Info("this is my info message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:
>>>
>>>
>>> logger.Debug("this is my debug message");
>>>
>>> or
>>>
>>> logger.Trace("this is my trace message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?
>>>
>>>
>>> I also posted this at:
>>>
>>>
>>> http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent
>>>
>>>
>>> Thanks,
>>>
>>> Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Dominik Psenner

Yet another possible solution to your problem could be to do something like:

https://www.loggly.com/blog/why-json-is-the-best-application-log-format-and-how-to-switch/

On 2016-10-24 07:39, Dominik Psenner wrote:

Ps: this might also something that you should look at.

http://stackoverflow.com/questions/17120943/how-add-custom-properties-in-appenderskeleton-log4net

And note too that the layoutpattern gets a applicationsetting pattern string to include application settings in the formatted logevent string. You can try that feature by building from source or by using the relerase candidate binaries.

It is unclear where these "categories" come from if the developers do not maintain them. Therefore I am not able to understand your requirements.


On 24 Oct 2016 7:21 a.m., "Dominik Psenner" <[hidden email]> wrote:

In that case you can pipe your log events through a custom appender that you implement. That custom appender can implement your logic of events as smart as you need it and then call inner appenders to process events. See the bufferingappenderskeleton.


On 24 Oct 2016 12:52 a.m., "Nicholas Duane" <[hidden email]> wrote:

Thanks.  I think I'm not quite explaining it well enough.  While I would like to set properties on the LoggingEvent class, it could not be accomplished similar to the way you suggest.  The reason is that the property I want to set, "category", would be based on the level the user is logging the event at and thus could not be done until the logging method was called.


I don't think I'm asking the logging framework to do something way out of the ordinary.  All I'm trying to do is set a property based on the level, and I would like to do that without the user having to do anything, other than maybe including some config code which would allow me to inject my code into the equation.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Sunday, October 23, 2016 3:13 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Responding inline..

On 23 Oct 2016 4:04 p.m., "Nicholas Duane" <[hidden email]> wrote:
>
> Is there a way for me to add properties to a LoggingEvent without the user doing anything out of the ordinary.  Maybe it's even best to assume an existing application which is using log4net. I would like to take this existing log4net application and without them changing any code, configuration changes are ok, I would like to add properties to each LoggingEvent which is created from their log statements like:
>
>
> logger.Error();
>
> logger.Info();
>
> logger.Debug();
>
> etc.
>
>

That requirement sounds like you would like to:

// thread properties... log4net.LogicalThreadContext.Properties["CustomColumn"] = "Custom value"; log.Info("Message");

// ...or global properties log4net.GlobalContext.Properties["CustomColumn"] = "Custom value";

These automatically set these properties on the logging events and you can then filter those with a propertyfilter as you write here:

> such that I could use the PropertyFilter filter to filter out events?  I want to set a property based on the level of the event.  I could of course use the LevelRangeFilter but in other cases I'm using the PropertyFilter and was figuring it might be nice to do it the same for all events.
>
>
> This other case where I'm using the PropertyFilter is for new events we've introduced.  These are what we call "compliance" and "business" events.  We originally introduced a "compliance" event and at that time I introduced a custom level for that.  However, I'm trying to move away from defining custom levels and instead use a property on the event to distinguish its "category".  For these new events which don't fit nicely into the level gradient I've introduced a method for developers to use to log them called LogEvent().  They will pass in their logger, the category of the event, and the event.  In this scenario it's easy for me to set properties on the LoggingEvent.

To me this sounds like you are trying to force the logging framework to do something different than the rest of the application logs do. If thats the case, then let me warn you that it might not be a good idea. Logs could be only a byproduct of the feature you would like to implement. If you are implementing application features through the logging framework, logging is too smart and does too much. Try to design your applocation so that it could do its job even if logging was not there.

However it sounds like this works for you, therefore I do not try to work out anything.

>  However, for what we call the diagnostic events, those that are logged using the methods exposed by log4net, we don't want them to have to do anything different than they were doing.  If they want to log an error they would still use:
>
>
> logger.Error("this is my error");
>
>
> or a warning:
>
>
> logger.Warn("this is my warning");
>
>
> etc.
>
>
> Ideally I would like to set the "category" on those events also so that by the time they make it to the appender it has this "category" property.  Is there a way to do that?

This sounds like this:

http://stackoverflow.com/questions/9015432/how-can-i-inject-a-property-for-only-one-call-in-log4net

Best regards,
Dominik

>
>
> Thanks,
>
> Nick
>
>
> ________________________________
> From: Dominik Psenner <[hidden email]>
> Sent: Sunday, October 23, 2016 9:18 AM
>
> To: Log4NET User
> Subject: Re: Injecting properties into LoggingEvent
>  
>
> Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.
>
>
> On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:
>>
>> Thank you for the suggestions.
>>
>>
>> We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:
>>
>>
>> logger.Warn("this is my warning message");
>>
>>
>> logger.Error("this is my error message");
>>
>>
>> logger.Info("this is my info message");
>>
>>
>> In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:
>>
>>
>> logger.Error(...);
>>
>> logger.Warn(...);
>>
>>
>> What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.
>>
>>
>> By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.
>>
>>
>> Thanks,
>>
>> Nick
>>
>>
>> ________________________________
>> From: Dominik Psenner <[hidden email]>
>> Sent: Saturday, October 22, 2016 1:29 PM
>> To: Log4NET User
>> Subject: Re: Injecting properties into LoggingEvent
>>  
>>
>> What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.
>>
>> A. Implement an extension class for the ILog interface
>> B. Implement a custom ILog interface implementation and a LoggerFactory.
>> C. Define custom loglevels
>> D. Use thread context properties altogether with custom format layouts
>> E. Log "complex" classes that hold your category information and find a way to format them
>>
>> There might be more things that you could do..
>>
>>
>> On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:
>>>
>>> Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?
>>>
>>>
>>> The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:
>>>
>>>
>>> public static class Logging
>>>
>>> {
>>>
>>>     public static void LogEvent(this ILog logger, Category category, IEvent evnt)
>>>
>>>     {
>>>
>>>         if ((category != null) && (evnt != null))
>>>
>>>             {
>>>
>>>             evnt.SetCategory(category.Name);
>>>
>>>             LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,
>>>
>>>                     logger.Logger.Name, Level.Emergency, evnt, null);
>>>
>>>             le.Properties["category"] = category.Name;
>>>
>>>             logger.Logger.Log(le);
>>>
>>>             }
>>>
>>>     }
>>>
>>> }
>>>
>>>
>>> So for instance when a user does the following:
>>>
>>>
>>> logger.Error("this is my error message");
>>>
>>> or
>>>
>>> logger.Warn("this is my warning message");
>>>
>>> or
>>>
>>> logger.Info("this is my info message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:
>>>
>>>
>>> logger.Debug("this is my debug message");
>>>
>>> or
>>>
>>> logger.Trace("this is my trace message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?
>>>
>>>
>>> I also posted this at:
>>>
>>>
>>> http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent
>>>
>>>
>>> Thanks,
>>>
>>> Nick


Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Nicholas Duane
In reply to this post by Dominik Psenner

Thanks. We already have written a custom appender.  Ideally I want the category set by the time the event makes it to our appender.  As I mentioned, what I'm trying to do is the following:


When someone logs an event I want to populate a property named "category" on the LoggingEvent which is based on the level of the event.


level: FATAL - INFO -> set category to criticalDiagnostic

level: DEBUG, TRACE -> set category to noncriticalDiagnostic


I could imagine there could be many other reasons why someone might want to modify the LoggingEvent automatically without any user code to do so.


As I mentioned, I don't want an application to make code changes to make this happen.  I'm looking for a config only solution for this.  You could imagine that the LogManager could expose a set of events and allow plugging in event sinks via configuration.  This would allow me to write an event sink and plug it into the system via the configuration.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Monday, October 24, 2016 1:39 AM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Ps: this might also something that you should look at.

http://stackoverflow.com/questions/17120943/how-add-custom-properties-in-appenderskeleton-log4net

stackoverflow.com
I Create Custom Appender(with AppenderSkeleton) that Connect to the Web Service... in this Appender i need to send some custom properties(like Url , Browser ,User ...

And note too that the layoutpattern gets a applicationsetting pattern string to include application settings in the formatted logevent string. You can try that feature by building from source or by using the relerase candidate binaries.

It is unclear where these "categories" come from if the developers do not maintain them. Therefore I am not able to understand your requirements.


On 24 Oct 2016 7:21 a.m., "Dominik Psenner" <[hidden email]> wrote:

In that case you can pipe your log events through a custom appender that you implement. That custom appender can implement your logic of events as smart as you need it and then call inner appenders to process events. See the bufferingappenderskeleton.


On 24 Oct 2016 12:52 a.m., "Nicholas Duane" <[hidden email]> wrote:

Thanks.  I think I'm not quite explaining it well enough.  While I would like to set properties on the LoggingEvent class, it could not be accomplished similar to the way you suggest.  The reason is that the property I want to set, "category", would be based on the level the user is logging the event at and thus could not be done until the logging method was called.


I don't think I'm asking the logging framework to do something way out of the ordinary.  All I'm trying to do is set a property based on the level, and I would like to do that without the user having to do anything, other than maybe including some config code which would allow me to inject my code into the equation.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Sunday, October 23, 2016 3:13 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Responding inline..

On 23 Oct 2016 4:04 p.m., "Nicholas Duane" <[hidden email]> wrote:
>
> Is there a way for me to add properties to a LoggingEvent without the user doing anything out of the ordinary.  Maybe it's even best to assume an existing application which is using log4net. I would like to take this existing log4net application and without them changing any code, configuration changes are ok, I would like to add properties to each LoggingEvent which is created from their log statements like:
>
>
> logger.Error();
>
> logger.Info();
>
> logger.Debug();
>
> etc.
>
>

That requirement sounds like you would like to:

// thread properties... log4net.LogicalThreadContext.Properties["CustomColumn"] = "Custom value"; log.Info("Message");

// ...or global properties log4net.GlobalContext.Properties["CustomColumn"] = "Custom value";

These automatically set these properties on the logging events and you can then filter those with a propertyfilter as you write here:

> such that I could use the PropertyFilter filter to filter out events?  I want to set a property based on the level of the event.  I could of course use the LevelRangeFilter but in other cases I'm using the PropertyFilter and was figuring it might be nice to do it the same for all events.
>
>
> This other case where I'm using the PropertyFilter is for new events we've introduced.  These are what we call "compliance" and "business" events.  We originally introduced a "compliance" event and at that time I introduced a custom level for that.  However, I'm trying to move away from defining custom levels and instead use a property on the event to distinguish its "category".  For these new events which don't fit nicely into the level gradient I've introduced a method for developers to use to log them called LogEvent().  They will pass in their logger, the category of the event, and the event.  In this scenario it's easy for me to set properties on the LoggingEvent.

To me this sounds like you are trying to force the logging framework to do something different than the rest of the application logs do. If thats the case, then let me warn you that it might not be a good idea. Logs could be only a byproduct of the feature you would like to implement. If you are implementing application features through the logging framework, logging is too smart and does too much. Try to design your applocation so that it could do its job even if logging was not there.

However it sounds like this works for you, therefore I do not try to work out anything.

>  However, for what we call the diagnostic events, those that are logged using the methods exposed by log4net, we don't want them to have to do anything different than they were doing.  If they want to log an error they would still use:
>
>
> logger.Error("this is my error");
>
>
> or a warning:
>
>
> logger.Warn("this is my warning");
>
>
> etc.
>
>
> Ideally I would like to set the "category" on those events also so that by the time they make it to the appender it has this "category" property.  Is there a way to do that?

This sounds like this:

http://stackoverflow.com/questions/9015432/how-can-i-inject-a-property-for-only-one-call-in-log4net

Best regards,
Dominik

>
>
> Thanks,
>
> Nick
>
>
> ________________________________
> From: Dominik Psenner <[hidden email]>
> Sent: Sunday, October 23, 2016 9:18 AM
>
> To: Log4NET User
> Subject: Re: Injecting properties into LoggingEvent
>  
>
> Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.
>
>
> On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:
>>
>> Thank you for the suggestions.
>>
>>
>> We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:
>>
>>
>> logger.Warn("this is my warning message");
>>
>>
>> logger.Error("this is my error message");
>>
>>
>> logger.Info("this is my info message");
>>
>>
>> In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:
>>
>>
>> logger.Error(...);
>>
>> logger.Warn(...);
>>
>>
>> What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.
>>
>>
>> By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.
>>
>>
>> Thanks,
>>
>> Nick
>>
>>
>> ________________________________
>> From: Dominik Psenner <[hidden email]>
>> Sent: Saturday, October 22, 2016 1:29 PM
>> To: Log4NET User
>> Subject: Re: Injecting properties into LoggingEvent
>>  
>>
>> What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.
>>
>> A. Implement an extension class for the ILog interface
>> B. Implement a custom ILog interface implementation and a LoggerFactory.
>> C. Define custom loglevels
>> D. Use thread context properties altogether with custom format layouts
>> E. Log "complex" classes that hold your category information and find a way to format them
>>
>> There might be more things that you could do..
>>
>>
>> On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:
>>>
>>> Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?
>>>
>>>
>>> The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:
>>>
>>>
>>> public static class Logging
>>>
>>> {
>>>
>>>     public static void LogEvent(this ILog logger, Category category, IEvent evnt)
>>>
>>>     {
>>>
>>>         if ((category != null) && (evnt != null))
>>>
>>>             {
>>>
>>>             evnt.SetCategory(category.Name);
>>>
>>>             LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,
>>>
>>>                     logger.Logger.Name, Level.Emergency, evnt, null);
>>>
>>>             le.Properties["category"] = category.Name;
>>>
>>>             logger.Logger.Log(le);
>>>
>>>             }
>>>
>>>     }
>>>
>>> }
>>>
>>>
>>> So for instance when a user does the following:
>>>
>>>
>>> logger.Error("this is my error message");
>>>
>>> or
>>>
>>> logger.Warn("this is my warning message");
>>>
>>> or
>>>
>>> logger.Info("this is my info message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:
>>>
>>>
>>> logger.Debug("this is my debug message");
>>>
>>> or
>>>
>>> logger.Trace("this is my trace message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?
>>>
>>>
>>> I also posted this at:
>>>
>>>
>>> http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent
>>>
>>>
>>> Thanks,
>>>
>>> Nick

Reply | Threaded
Open this post in threaded view
|

Re: Injecting properties into LoggingEvent

Dominik Psenner

Hm, we could provide a scripting language that allows you to customize logging event properties but that scripting language wont ever suffice.

You are probably best off by implementing a facade that matches your needs and hides the heavy lifting done the used logging framework.


On 24 Oct 2016 3:28 p.m., "Nicholas Duane" <[hidden email]> wrote:

Thanks. We already have written a custom appender.  Ideally I want the category set by the time the event makes it to our appender.  As I mentioned, what I'm trying to do is the following:


When someone logs an event I want to populate a property named "category" on the LoggingEvent which is based on the level of the event.


level: FATAL - INFO -> set category to criticalDiagnostic

level: DEBUG, TRACE -> set category to noncriticalDiagnostic


I could imagine there could be many other reasons why someone might want to modify the LoggingEvent automatically without any user code to do so.


As I mentioned, I don't want an application to make code changes to make this happen.  I'm looking for a config only solution for this.  You could imagine that the LogManager could expose a set of events and allow plugging in event sinks via configuration.  This would allow me to write an event sink and plug it into the system via the configuration.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Monday, October 24, 2016 1:39 AM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Ps: this might also something that you should look at.

http://stackoverflow.com/questions/17120943/how-add-custom-properties-in-appenderskeleton-log4net

I Create Custom Appender(with AppenderSkeleton) that Connect to the Web Service... in this Appender i need to send some custom properties(like Url , Browser ,User ...

And note too that the layoutpattern gets a applicationsetting pattern string to include application settings in the formatted logevent string. You can try that feature by building from source or by using the relerase candidate binaries.

It is unclear where these "categories" come from if the developers do not maintain them. Therefore I am not able to understand your requirements.


On 24 Oct 2016 7:21 a.m., "Dominik Psenner" <[hidden email]> wrote:

In that case you can pipe your log events through a custom appender that you implement. That custom appender can implement your logic of events as smart as you need it and then call inner appenders to process events. See the bufferingappenderskeleton.


On 24 Oct 2016 12:52 a.m., "Nicholas Duane" <[hidden email]> wrote:

Thanks.  I think I'm not quite explaining it well enough.  While I would like to set properties on the LoggingEvent class, it could not be accomplished similar to the way you suggest.  The reason is that the property I want to set, "category", would be based on the level the user is logging the event at and thus could not be done until the logging method was called.


I don't think I'm asking the logging framework to do something way out of the ordinary.  All I'm trying to do is set a property based on the level, and I would like to do that without the user having to do anything, other than maybe including some config code which would allow me to inject my code into the equation.


Thanks,

Nick



From: Dominik Psenner <[hidden email]>
Sent: Sunday, October 23, 2016 3:13 PM
To: Log4NET User
Subject: Re: Injecting properties into LoggingEvent
 

Responding inline..

On 23 Oct 2016 4:04 p.m., "Nicholas Duane" <[hidden email]> wrote:
>
> Is there a way for me to add properties to a LoggingEvent without the user doing anything out of the ordinary.  Maybe it's even best to assume an existing application which is using log4net. I would like to take this existing log4net application and without them changing any code, configuration changes are ok, I would like to add properties to each LoggingEvent which is created from their log statements like:
>
>
> logger.Error();
>
> logger.Info();
>
> logger.Debug();
>
> etc.
>
>

That requirement sounds like you would like to:

// thread properties... log4net.LogicalThreadContext.Properties["CustomColumn"] = "Custom value"; log.Info("Message");

// ...or global properties log4net.GlobalContext.Properties["CustomColumn"] = "Custom value";

These automatically set these properties on the logging events and you can then filter those with a propertyfilter as you write here:

> such that I could use the PropertyFilter filter to filter out events?  I want to set a property based on the level of the event.  I could of course use the LevelRangeFilter but in other cases I'm using the PropertyFilter and was figuring it might be nice to do it the same for all events.
>
>
> This other case where I'm using the PropertyFilter is for new events we've introduced.  These are what we call "compliance" and "business" events.  We originally introduced a "compliance" event and at that time I introduced a custom level for that.  However, I'm trying to move away from defining custom levels and instead use a property on the event to distinguish its "category".  For these new events which don't fit nicely into the level gradient I've introduced a method for developers to use to log them called LogEvent().  They will pass in their logger, the category of the event, and the event.  In this scenario it's easy for me to set properties on the LoggingEvent.

To me this sounds like you are trying to force the logging framework to do something different than the rest of the application logs do. If thats the case, then let me warn you that it might not be a good idea. Logs could be only a byproduct of the feature you would like to implement. If you are implementing application features through the logging framework, logging is too smart and does too much. Try to design your applocation so that it could do its job even if logging was not there.

However it sounds like this works for you, therefore I do not try to work out anything.

>  However, for what we call the diagnostic events, those that are logged using the methods exposed by log4net, we don't want them to have to do anything different than they were doing.  If they want to log an error they would still use:
>
>
> logger.Error("this is my error");
>
>
> or a warning:
>
>
> logger.Warn("this is my warning");
>
>
> etc.
>
>
> Ideally I would like to set the "category" on those events also so that by the time they make it to the appender it has this "category" property.  Is there a way to do that?

This sounds like this:

http://stackoverflow.com/questions/9015432/how-can-i-inject-a-property-for-only-one-call-in-log4net

Best regards,
Dominik

>
>
> Thanks,
>
> Nick
>
>
> ________________________________
> From: Dominik Psenner <[hidden email]>
> Sent: Sunday, October 23, 2016 9:18 AM
>
> To: Log4NET User
> Subject: Re: Injecting properties into LoggingEvent
>  
>
> Sorry, I cannot grasp your requirements. Please try to explain your usecase better in a way that gives the document some kind of structure.
>
>
> On 23 Oct 2016 12:02 a.m., "Nicholas Duane" <[hidden email]> wrote:
>>
>> Thank you for the suggestions.
>>
>>
>> We are already logging complex objects in many cases.  We have the notion of a compliance event.  That's basically a map (IDictionary<string, object>).  We're now adding business events.  However, even with these "complex" events I don't want the map to contain the category, at least not at event creation time.  I see an event as just a collection of properties.  The act of logging it at a certain level or category is what assigns the severity or category.  For example:
>>
>>
>> logger.Warn("this is my warning message");
>>
>>
>> logger.Error("this is my error message");
>>
>>
>> logger.Info("this is my info message");
>>
>>
>> In each of those cases if we assume the event is the message itself, there is no criticality associated with that event.  It's the act of logging that defines the event's criticality.  I want the same to be true for the category.  I believe I have this working fine for our "complex" events which don't fit into the Level gradient.  I expose a LogEvent() method which logs at the Emergency level as I showed in the code I included in the previous thread.  However, we also need to capture diagnostic events, ones that are logged via the logging framework's methods:
>>
>>
>> logger.Error(...);
>>
>> logger.Warn(...);
>>
>>
>> What I am hoping to do is hook in some of my code and generate one of our complex events each time the logging framework logs an event and will map the level to one of our categories.  I can imagine that this might be possible if I somehow wrap a logger, but as I mentioned I don't want the user to have to call anything special at startup to hook up that wrapping.  I was hoping there would be a way for me to hook myself in via configuration.  I'm ok with giving them a configuration file they need to use but I don't want them to have to change any existing code them may have.
>>
>>
>> By the way, we did generate a custom log level for our compliance event.  However I'm trying to move away from that as it was point out that our events don't fit well within the level gradient.  So the new code for logging a compliance event does not use that level.  Both the compliance and business event would be logged at the Emergency level.  I would use the category property to differentiate them.  Similar, I guess, to log4j2's Markers.
>>
>>
>> Thanks,
>>
>> Nick
>>
>>
>> ________________________________
>> From: Dominik Psenner <[hidden email]>
>> Sent: Saturday, October 22, 2016 1:29 PM
>> To: Log4NET User
>> Subject: Re: Injecting properties into LoggingEvent
>>  
>>
>> What I am proposing here are a mere ideas that will need further investigation. I have not tried any of these ideas. You will have to prioritize these ideas based on your requirements.
>>
>> A. Implement an extension class for the ILog interface
>> B. Implement a custom ILog interface implementation and a LoggerFactory.
>> C. Define custom loglevels
>> D. Use thread context properties altogether with custom format layouts
>> E. Log "complex" classes that hold your category information and find a way to format them
>>
>> There might be more things that you could do..
>>
>>
>> On 22 Oct 2016 5:31 p.m., "Nicholas Duane" <[hidden email]> wrote:
>>>
>>> Is there a way for me to inject properties into a LoggingEvent?  I'm trying to accomplish this without the user (of log4net) doing anything special.  The only thing I could think of was wrapping loggers, and while I'm not against doing that it would have to be done via configuration as I don't want the user to have to do it programmatically.  Is there any way for me to inject a logger wrapper via configuration?
>>>
>>>
>>> The reason I'm looking to do this is that I would like to set a property on the LoggingEvent to use for filtering.  This property would be determined based on the level property.  I could simply use the level property for filtering, but I have other events which I generate which are all logged at the Emergency level but have a different value for this property so for them I'm using this property for filtering.  I don't have the same issue with these other events because they are logged via an extension method I provided on the ILog interface:
>>>
>>>
>>> public static class Logging
>>>
>>> {
>>>
>>>     public static void LogEvent(this ILog logger, Category category, IEvent evnt)
>>>
>>>     {
>>>
>>>         if ((category != null) && (evnt != null))
>>>
>>>             {
>>>
>>>             evnt.SetCategory(category.Name);
>>>
>>>             LoggingEvent le = new LoggingEvent(null, logger.Logger.Respository,
>>>
>>>                     logger.Logger.Name, Level.Emergency, evnt, null);
>>>
>>>             le.Properties["category"] = category.Name;
>>>
>>>             logger.Logger.Log(le);
>>>
>>>             }
>>>
>>>     }
>>>
>>> }
>>>
>>>
>>> So for instance when a user does the following:
>>>
>>>
>>> logger.Error("this is my error message");
>>>
>>> or
>>>
>>> logger.Warn("this is my warning message");
>>>
>>> or
>>>
>>> logger.Info("this is my info message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "criticalDiagnostic".  When they do:
>>>
>>>
>>> logger.Debug("this is my debug message");
>>>
>>> or
>>>
>>> logger.Trace("this is my trace message");
>>>
>>>
>>> I would like to set the property "category" on the LoggingEvent to "noncriticalDiagnostic".  Any way for me to do that automagically?
>>>
>>>
>>> I also posted this at:
>>>
>>>
>>> http://stackoverflow.com/questions/40187597/injecting-properties-into-log4nets-loggingevent
>>>
>>>
>>> Thanks,
>>>
>>> Nick