C# Azure Functions and Application Insights - LogError not showing exception - c#

I'm having some trouble with Application Insights when running a C# v3 Function App. Everything is setup within Azure to use Application insights, as per the instructions. Within the host.json file, I've included the following settings:
"logging": {
"LogLevel": {
"Default": "Information"
},
"applicationInsights": {
"samplingExcludedTypes": "Request",
"samplingSettings": {
"isEnabled": true
}
}
},
I am using Dependency Injection, so have a startup class within the app, and then inject ILogger class wherever required:
using Microsoft.Extensions.Logging;
...
builder.Services.AddLogging();
There are a few occasions within code where I'm catching an exception, handling it, and want to log it rather than throw an exception. E.g. looking for a blob container image that may or may not exist - I can still return a valid response rather than throwing the whole thing because of a single, trivial issue.
However, Application Insights does not seem to be logging the exception within the trace, even though it has been passed to the logger:
catch (ArgumentException e)
{
var msg = $"Error encountered blah blah blah";
logger.LogWarning(e, msg);
return Result.Failure<string>(msg);
}
I can see within Application Insights the warning being logged, along with the message, but the stack trace is always missing from the message/custom dimensions within the trace. The same happens if I use LogError.
Custo:
traces
| where cloud_RoleName == "my-app" and severityLevel == 2
I've looked through a fair amount of documentation and questions on here, but struggling to find an answer that works, or that explains well what is going on. It seems very much with Azure Functions + App Insights that either "it just magically works if you turn it on", or the answers are for ASP.NET core, or just plain out of date.
Is the problem that only exceptions thrown by the app will show up in the Exceptions area of App Insights with a stack trace? (if so, can you log errors here without throwing an exception?)
Am I missing a key bit of config in host.json or startup? A library? (I've already tried adding Microsoft.Azure.WebJobs.Logging.ApplicationInsights)
I'm also looking at changing over to use Serilog + an App Insights sink if necessary - but don't especially want to do this when it seems like it should "just work out of the box".
Can anyone help?

Thanks to #PeterBons for his help, in order to get your logged exceptions to appear in the Exceptions table in App Insights you need to make sure that:
If you're using sampling, you add "Exception" to the "samplingExcludedTypes" in your host.json to make sure they all get logged
You need to reference the "Microsoft.Azure.WebJobs.Logging.ApplicationInsights" nuget package in your project (I left everything else the same and removed this - boom, no logging to exceptions)

Related

Serilog not logging anything

I'd like to use Serilog for my project, but I can't quite get it to work properly.
Right now, this is what I've got, just for verifying and testing purposes:
public MainLogger([NotNull] ILogPathProvider logPathProvider)
{
m_logger = Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
m_logger.Warning("blabla");
}
As you can see, there is not a lot going on besides just opening a log and trying to write a warning.
However, this warning does not appear.
Is there anything I forgot to configure / call?
Assuming you installed the correct NuGet Packages (Serilog and Serilog.Sinks.Console), then your code sample should print a Warning message in the console without requiring any changes.
You can confirm this by creating a simple Console application, installing the packages above, and running the same code.
The problem is elsewhere in your application and/or environment... It has nothing to do with Serilog.
Most likely, your method MainLogger is not being called at all, or perhaps your Console output is being redirected to somewhere else.

Owin produces a lot of logging noise in the trace

I've got a small console application running TopShelf and using Serilog as the logging facility where I'd like to run OWIN inside. However as soon as I start the app builder, every log message gets duplicated via the trace listener and thus, printed out twice to the console.
// serilog sink configuration
new LoggerConfiguration()
.WriteTo.Trace()
...
.CreateLogger();
// topshelf
HostLogger.UseLogger(new SerilogLogWriterFactory.SerilogHostLoggerConfigurator());
I already found this answer here and included the following before I start the web host:
webHostOptions.Settings.Add(typeof (ITraceOutputFactory).FullName,
typeof (WebAppBuilder.NullTraceOutputFactory).AssemblyQualifiedName);
Trace.Listeners.Remove("HostingTraceListener");
The funny thing is: When I first started the application after inserting those lines, it worked (e.g. double messages were gone.). However after I cleaned my \bin directory, they started to appear again. What do?
Please check out this highly professional drawing I just made which should further explain the issue:
(zoom)

Using internal log and manage exceptions

I've two problem using Nlog internal logging.
Firstly while starting I execute the following code:
LogManager.Configuration = new
NLog.Config.XmlLoggingConfiguration("NLog.debug.config", true);
LogManager.ReconfigExistingLoggers();
InternalLogger.LogToConsole = true;
InternalLogger.LogToConsoleError = true;
InternalLogger.LogLevel = LogLevel.Trace;
LogManager.ThrowExceptions = true;
InternalLogger.LogFile = Path.Combine(ConfigurationManager.AppPath, "Nlog.log");
My first problem is the logToconsole do not display in my Visual output. Is that normal ?
My second issue is when I try to log on C:\log.txt (to test internal log)
This should crash because Nlog cannot create files at the root of C:.
Unfortunaly It do not crash (and do not create the file) (it works with C:\test\log.txt for example).
Here my internal Nlog.log content:
2015-04-23 18:44:09.8593 Debug TestManager.Info Rejecting message
because of a filter. 2015-04-23 18:44:09.8593 Debug TestManager.Info
Rejecting message because of a filter. 2015-04-23 18:44:09.8593 Debug
TestManager.Info Rejecting message because of a filter. 2015-04-23
18:44:09.8593 Debug TestManager.Info Rejecting message because of a
filter. 2015-04-23 18:44:09.8593 Trace Opening C:test.log with
concurrentWrite=False
Rejected is normal (I've several targets)
So Why haven't I exception and no trace ?
Thanks a lot for the incoming help
NLog probably uses the conventional Console.WriteLine(…) method to send messages to console. It will not work in WinForms application because Console.WriteLine(…) does nothing in WinForms application by default. It only works, however, when you are debugging from Visual Studio since that provides a console window for Output
Try to call Win32 API function AllocConsole at the beginning of your application. It should create a console for your WinForms application and enable Console.WriteLine(…) function. Here you can find an example of the code that shows how to call AllocConsole. "See link for setting this up".
Also quoting Nlog github page on internal logging
There are 3 environment variables which control internal logging. You
can set those variables before running your program to enable internal
logging:
NLOG_INTERNAL_LOG_TO_CONSOLE - if this variable is found in the
environment, will outputs internal diagnostic information to the
console
For your second question, looking at your logs I believe you did not provide the path in correct format by escaping the backslash character
It should be like
fileName="C:\\logssamplefile.txt"
Please note that this worked for me

Catching exceptions in console application C#

I have a console application written in C#. This application runs as automation to test a web service.
Flow:
Log in to network share (impersonate user)
copy mp3 file to local disc
convert mp3 to wav
downsample
trim wave
extract some useful data from wav
send http request
delete local files
write out some stuff to tsv
The application will run great for several hours (usually takes about 24 hours to complete the test). but every once and a while I will get this message: "The application has stopped working. I have been running this is VS 2012 in debug mode so, I can see what line throws any error. problem is, that I have not been able to catch the line (or method) that is throwing the error. I originally thought that the Domain controller was causing this issue due to power settings.
How can I capture exactly what error is bubbling its way up the stack?
Does all that run in a loop of some kind? Or on a timer?
Perhaps put a try-catch around the body of the loop or the method that runs all your code, add a logging framework of your choice (log4net or nlog seem good) and then in the catch log the exception. Most logging frameworks allow you to include the exception and will include stacktrace, etc.
Putting debug logging throughout the process can also help to narrow down where it's happening.
You can go to the Event Viewer on the operating system the console application is running on and then click on "Application". Event viewer logs and displays all exceptions thrown on any application running on the operating system.
try
{
// your code
}
catch (Exception e)
{
System.IO.File.WriteAllText(#"Z:\err.txt", e.ToString());
}
Note that access to windows drives are denied for non administrators so replace Z: with your choice.
I recommend you using a logging framework.
I use log4net in almost all applications. Its very simple to use and configure.
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
try
{
// do whatever
}
catch(Exception ex)
{
// Log an error with an exception
log.Error("Exception thrown", ex);
}
By using these kind of libraries you can get your log data output to file, database or even written to the windows event-viewer for instance.
It looks like the exception code you are getting happens when you try to use something that is already been garbage collected. Are you using anything after it is disposed?
Knowledge Base Article for 0xc0000005

What do you do if your error logging fails, and how do you test that its working in production?

What do you do if you're error logging code fails?
How do you make sure that its currently working?
How do you know if its not working?
How do you test that its working in a production environment?
Should I throw an exception if all else fails?
The code below uses Microsoft's Enterprise Library Logging Application Block. How do you make it "better"?
using Microsoft.Practices.EnterpriseLibrary.Logging;
class Program
{
static void Main(string[] args)
{
try
{
// Trying to write some data to the DB
...
}
catch (Exception ex)
{
LogHelper.LogException(ex, "Trying to write to the DB");
}
}
}
public class LogHelper
{
public static void LogException(Exception ex, string exceptionType)
{
try
{
// Simplified version, only logging the message
Logger.Write(exceptionType);
}
catch
{
// What do you do here???
}
}
}
My apps usually do two things on an error. The first is to write it to a local log file (even if it uses some type of database logging as well). Then it sends an e-mail of the error to a distribution list set up for support.
So if the database log write fails, the error is still in the local log file and also sent via e-mail.
If the e-mail fails, the error is still logged so you can troubleshoot the problem later.
Getting more fault tolerant than that would only be worth the effort for extremely mission critical applications, IMHO.
See the answers in my related question:
If everything else fails, have a 'last resort logging' in your catch block. Log the exception to a text file in a location where this is highly unlikely to fail. If this last resort logging fails by throwing another exception, you can either swallow that exception, or terminate your app and display the error as a message box.
In this specific (exceptional) case, swallowing the exception is the only way to not terminate the app.
I write a log file as well as have an email sent to a common address that will never go away. Neither are bullet proof but I would think that if our mail system is down or the email server changes we would know about it. I do have some apps that write to both a database and a flat file and send the email. So one of the 3 is going to work. I found one of my apps was writing to a db for the log and in the catch it was writing to the same db and the only way I found it was the app was failing because of some changes in the db connection. I made sure to modify that catch statement do the email instead of the db. The only problem I have with flat files is file system storage, we have a lot of applications that write flat files for logs so we are constantly backing them up and saving them or just plain deleting them.

Categories

Resources