Log4net fails silently by design. Good. I don't want it taking down my app.
Is there a way to set up a notification when Log4net crashes and stops logging?
Is there some kind of event handler that I can hook into which will tell me that Log4net has gone silent?
I want to know when this happens so I can recycle the app pool as soon as possible.
Thanks!
If I'm understanding you correctly, you would like log4net to signal you when an appender fails. If we look at the logging code for the Logger implementation we see that the only point that takes into account the appenders failing is the internal logging mechanism:
// log4net.Repository.Hierarchy.Logger
public virtual void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception)
{
try
{
if (this.IsEnabledFor(level))
{
this.ForcedLog((callerStackBoundaryDeclaringType != null) ? callerStackBoundaryDeclaringType : Logger.ThisDeclaringType, level, message, exception);
}
}
catch (Exception exception2)
{
LogLog.Error("Log: Exception while logging", exception2);
}
catch
{
LogLog.Error("Log: Exception while logging");
}
}
Of course this occurs only if the appender throws an exception. The LogLog component then forwards the message to the Console and Trace components:
// log4net.Util.LogLog
private static void EmitErrorLine(string message)
{
try
{
Console.Error.WriteLine(message);
Trace.WriteLine(message);
}
catch
{
}
}
So, by listening messages coming from the trace you can get an idea of what happens in your appenders. To turn this into an event you can add a trace listener that triggers in some specific cases: you can take a look at what is in this answer regarding custom trace listeners in order to trigger an event from one.
Related
I'm migrating a project that uses Spring AMQP to a project that uses Spring Cloud Stream with RabbitMQ.
In my old project, when some exception occurred while processing a message using #RabbitListener, that exception was thrown. If there was a dead letter queue binded, exception was still thrown (only once if there were retries, the last one I guess). This was very helpful for logging purposes.
In Spring Cloud there is a dead letter queue mechanism for #StreamListener if you define the properties:
spring.cloud.stream.bindings.input1.destination=dest1
spring.cloud.stream.rabbit.bindings.input1.consumer.auto-bind-dlq=true
spring.cloud.stream.rabbit.bindings.input1.consumer.republishToDlq=true
But if you have a method like this (is just an example):
#StreamListener("input1")
public void process(String message){
System.out.println("Trying...");
throw new RuntimeException();
}
Logs are:
Trying...
Trying...
Trying...
(end of log, no exception thrown)
Is there any way to throw the exception (only in the last retry)?
Thanks!
See the documentation about consumer properties.
Set ...consumer.max-attempts=1 to disable retry.
You can handle the exception, log it and then throw AmqpRejectAndDontRequeueException. This will send the message to dead letter queue
You are under #StreamListener where would you expect the exception to go? who is catch it?
you can do it something like that:
#StreamListener("input1")
public void process(String message){
try {
System.out.println("Trying...");
throw new RuntimeException();
// or the actual code that handle the message
} catch (RuntimeException re) {
// handle the exception, logging etc.
throw re
}
}
i am encountering a problem i'm not familiar with.
So i'm trying to log exceptions from a test Azure Function but when i throw an exception and return a 400 bad request, application insight registers the log as a successful request.
As i understand it it is probably register the function's successful run but what i don't understand is how i then should log the exception.
So what i have done so far is this.
(I Will be referring to Application Insights as AI from here on out)
I started by created an AI-Resource.
Then i took the instrument key and applied it to the app settings of my function.
After that i installed the AI NUGET to my function bu creating a Projet.json file and then pasting something like this which installed the necessary assemblies and such.
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.ApplicationInsights": "2.4.0"
}
}
}
}
after this i initialize the TelemetryClient in the function and try to log and exception in a catch:
Initiation:
string key = TelemetryConfiguration.Active.InstrumentationKey = System.Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY", EnvironmentVariableTarget.Process);
TelemetryClient telemetry = new TelemetryClient() {
InstrumentationKey = key
};
Catch:
catch (Exception e)
{
Dictionary<string,string> properties = new Dictionary<string,string>();
properties.Add("Function Payload", data.ToString());
properties.Add("Function Exception", e.ToString());
telemetry.TrackException(e, properties);
return req.CreateResponse(HttpStatusCode.BadRequest, e);
}
Test running the function i get:
2018-03-07T14:24:36.171 [Info] Function started (Id=0292b455-314d-4c4c-872a-2b8137a72305)
2018-03-07T14:24:37.092 [Info] Function completed (Success, Id=0292b455-314d-4c4c-872a-2b8137a72305, Duration=931ms)
In Application insights i can can only see bad requests for StatusCode: 500
but 400 Bad requests gets logged as Successful requests.
And also the TrackException functionality doesn't log any of the custom properties...
So what am i missing?
MORE DETAILS ABOUT EXCEPTION LOGGING:
#Mikhail is right that we treat this as a success because the function is a success. We didn't want to use status codes to guess whether there was a successful operation or not, so we look for whether the function threw an exception.
Your exception isn't appearing in that screen because it hasn't been property correlated with this function execution. If you go to App Insights Analytics and query for that ExceptionTelemetry, you should see it.
In order to correlate it with a specific function, you'd need to set the OperationId, which is the same as the function's InvocationId. There is a sample that shows how to do this with Events, Metrics, and Dependencies, but doing it for Exceptions is the same (you can ignore the User.Id assignment): https://learn.microsoft.com/en-us/azure/azure-functions/functions-monitoring#custom-telemetry-in-c-functions
Update: From what you've shown of your function above, you may be able to get away with doing something like:
catch (Exception e)
{
log.Error("Function Payload " + data.ToString());
throw;
}
That would return a 500 (rather than a 400), and Functions would log the trace to Application Insights, and then log the exception as well as the Request failure. If you're not using your TelemetryClient anywhere else, you could remove that from your code.
The server (Azure Function) processed the request without errors, you returned a result from it, so from the point of view of Function App runtime the request was processed successfully. You can see that from the log too:
... Function completed (Success, ...
So, it makes sense that the Function App registers the call as success in Application Insights too. At least, that's how they chose to implement it.
the "for this operation" not showing exceptions implies that the exception that you sent does not have the same operationId as the azure function. operation
id is how application insights "links" related telemetry together.
your "exeption logging" screenshot is not an exception, but a request, so the custom properties logged on your exception won't be there.
if you want your azure function to fail, and show as a failed request, and log an exception, why are you catching the exception and logging it yourself? doesn't catching the exception then cause the azure function to succeed? why not just let the exception trickle out and let the function runtime do that part for you? (doesn't it?)
I would like to be able to log unhandled exceptions via configuring log4net.
Is that possible to achieve by only making changes to the config file? if yes, how to do that?
Otherwise if it's not possible, what should I implement in the code to make this happen?
You can't do this with only configuration, you need log the actual exception somewhere. So you need to catch the 'uncatched' exception and them log it.
public static void Main(string[] args)
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new
ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors
// to go through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
In the handlers you can log to log4net. After that you can switch them on and off with configuration.
However there are some cases that the exception is not catched. For example when there is a failfast called.
I am calling 2 different web services using two webservice outbound gateways in my Spring integration gateway flow.
I have implemented 2 fault Resolver , in each gateway to resolve SOAP faults
and want to create custom application exception and throw from resolver to my exception handler.
My FaultResolver is getting called whenever we receieve the SOAP fault from service call.
But I am not been able to throw custom excetion from my resolver as its only allowing me to throw IOException.
Due to this I am throwing a Runtime Exception with message from my resolver and catching this Runtime Exception in my Exception Handler.
Is it correct practice to throw a runtime exception and catching in Handler or is ther any other better way to handle this scenario or any other implementation to handle SOAP Fault and throw custom Exception.
The best way to determine if your solution is good or not, just try to find some out-of-the-box implementation on the matter. One of them is:
public class SimpleFaultMessageResolver implements FaultMessageResolver {
public void resolveFault(WebServiceMessage message) {
if (message instanceof FaultAwareWebServiceMessage) {
throw new WebServiceFaultException((FaultAwareWebServiceMessage) message);
}
else {
throw new WebServiceFaultException("Message has unknown fault: " + message);
}
}
}
where WebServiceFaultException is exactly RuntimeException.
So, I think you are fine to go ahead.
I am wondering why the following azure workerrole does not show any diagnostic messages when the role is shutdown:
public class WorkerRole : RoleEntryPoint {
private bool running=true;
public override void Run() {
while (running)
{
Thread.Sleep(10000);
TTrace.WriteLine("working", "Information");
}
Trace.WriteLine("stopped", "Information");
}
public override bool OnStart()
{
Trace.WriteLine("starting", "Information");
return base.OnStart();
}
public override void OnStop() {
Trace.WriteLine("stopping", "Information");
running = false;
base.OnStop();
}
}
I can see the events 'starting' and 'working' in the diagnostic logs, but the Onstop method does not log anything. I was wondering if it's even called so I injected some code in the OnStop() method to write out some data. In fact the data was written as expected which proves that the method is called, it's just that I don't get any logs. Any ideas how to Trace my shutdown code?
My first and best guess is that the Diagnostics Agent does not have time to transfer the trace out to storage for you to see it. Traces are first logged locally on the VM, then the agent will transfer them off (OnDemand or Scheduled) depending on how you have configured it. Once the VM shuts down, the agent is gone too and cannot transfer it off.
Tracing in OnStop is not supported and if you manage to get it working via On-Demand Transfer (http://msdn.microsoft.com/en-us/library/windowsazure/gg433075.aspx ) it's likely to not work in the next release. Note, tracing in Web Role OnStart does not work either. See my blog post http://blogs.msdn.com/b/rickandy/archive/2012/12/21/optimal-azure-restarts.aspx to fix that. Also see my blog post for instructions on view real time OnStop trace data with DbgView.
The OnStop method should be used only to delay shutdown until you've cleaned up - so you shouldn't have much code in there to trace. Again, see my blog for details.