About a month ago, I noticed that some of the monitoring functionality in the old Azure Functions portal interface stopped working. I wrote more details about the issues on the Azure Functions Host GitHub but my particular questions are as of yet unanswered.
Now it seems the Azure Functions portal interface default to the new "management experience" that looks more similar to the rest of Azure, and with that, it's even more apparent that something is wrong in the way we use logging and tracing.
My question is: Does anybody have any code samples as to how to set up Azure Function logging, live metrics, and app insights tracing so that it:
- Works with dependency injection
- Works with the new "management experience" interface
Currently, in order to see what a particular Azure Function is doing, I have to go to the old Azure interface and study the log stream. The Functions do work, and they spit out information in the log stream, but only in the old interface, and not much else in terms of monitoring seems to work. Using the old interface:
- The invocation logs, the one you get when you press the "Monitor" link under "Functions(Read Only) > [function] > Monitor, shows no invocations at all even though the functions are definitely being called according to the logs.
- The Live app metrics link results in the default "Not available: your app is offline or using an older SDK" with some animated demo charts.
These worked fine a month ago. Now, not so much.
Using the new interface:
- Monitoring > Log stream shows nothing except the word "Connected!", regardless of verbosity.
- Monitoring > Log Stream > Open in Live Metrics again just yields the default "Not available: your app is offline or using an older SDK".
Going to a specific function in the new interface by using Functions > Functions > [click on a function]:
- Developer > Code + Test > Test-button > Run, the Logs window pops up, just says "Connected!" and nothing else, again regardless of verbosity.
- Monitor > Invocations, there are no invocation traces registered here, even though the function is obviously being called according to the old interface log stream.
- Monitor > Logs, again, just says "Connected!", regardless of verbosity.
I don't understand why it suddenly stopped working a month back, and why so many things don't seem to work with the new interface. Our Functions' NuGet packages are all up to date.
In terms of logging, the logger is dependency injected so that we can use it in multiple classes and not just in the default Functions.cs class:
using Microsoft.Extensions.Logging;
public class EventForwarder
{
private readonly ILogger<EventForwarder> log;
And we log through the use of extension methods, nothing fancy really:
using Microsoft.Extensions.Logging;
public static class LoggerExtensions
{
public static void Info(this ILogger log, string msg) => log.LogInformation(msg);
The app insights tracer is also dependency injected using a workaround suggested here, i.e. our Startup.cs looks lite this:
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(EventForwarder.Startup))]
namespace EventForwarder
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
// https://github.com/Azure/azure-functions-host/issues/5353
builder.Services.AddSingleton(sp =>
{
var key = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
return string.IsNullOrWhiteSpace(key) ? new TelemetryConfiguration() : new TelemetryConfiguration(key);
});
We're performing traces of Http retries, among other things, like so:
public class HttpRetryPolicyService
{
private readonly ILogger<HttpRetryPolicyService> log;
private readonly TelemetryClient insights;
public HttpRetryPolicyService(ILogger<HttpRetryPolicyService> log,
TelemetryConfiguration insightsConfig)
{
this.log = log;
insights = new TelemetryClient(insightsConfig);
}
...
private void LogRetry(DelegateResult<HttpResponseMessage> message, TimeSpan delay, int attempt, Context context)
{
if (message.Exception != null)
{
log.Warn($"Exception details: {message.Exception}");
insights.Track(message.Exception);
And we're using extension methods to trace, like so:
using Microsoft.ApplicationInsights;
namespace EventForwarder.Static
{
public static class TelemetryExtensions
{
public static void Track(this TelemetryClient insights, string eventName)
{
insights.TrackEvent(eventName);
insights.Flush();
}
What am I missing?
Edit #1: Btw, adding Application Insights as a Service Dependency in the Publish dialog unfortunately does not solve these issues.
Edit #2: Also, preemtively, our Functions host.json files all look like this:
{
"version": "2.0",
"healthMonitor": {
"enabled": true,
"healthCheckInterval": "00:00:10",
"healthCheckWindow": "00:02:00",
"healthCheckThreshold": 6,
"counterThreshold": 0.80
},
"logging": {
"fileLoggingMode": "always",
"applicationInsights": {
"enableLiveMetrics": true,
"samplingSettings": {
"isEnabled": true
}
},
"logLevel": {
"EventForwarder": "Information"
}
}
}