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:
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:
These worked fine a month ago. Now, not so much.
Using the new interface:
Going to a specific function in the new interface by using Functions > Functions > [click on a function]:
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"
}
}
}
Azure Functions integrates with Application Insights to better enable you to monitor your function apps. Application Insights collects telemetry data generated by your function app, including information your app writes to logs. Application Insights integration is typically enabled when your function app is created.
In your function app, select Configuration under Settings, and then select Application settings. If you see a setting named APPINSIGHTS_INSTRUMENTATIONKEY , Application Insights integration is enabled for your function app running in Azure.
This is what breaks your app, remove it and everything should work:
// 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);
});
My guess would be that the workaround actually breaks the logging now that the bugfix has been rolled out.
I created a sample app where logging and log stream work quite nicely, also with dependency injection. I tested it with both Windows and Linux consumption plans. The function app was created using the wizard in the Azure Portal, selecting .NET Core 3.1. Please be aware that TrackEvent
does not show up in the function's log stream. It shows up in Application Insights Live Metrics. It can also take up to 30s after "Connected" shows up until actual logs are shown. The Live Metrics view works better, especially if you open directly from application insights.
I was able to reproduce your issues by applying the "workaround" mentioned above. Without it, everything works fine.
Full sample: https://github.com/LXBdev/Functions-V3-sample
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<MyService>();
}
"logging": {
"applicationInsights": {
"samplingExcludedTypes": "Request",
"samplingSettings": {
"isEnabled": true
}
},
"logLevel": {
"Functions_V3_sample": "Information"
}
}
public MyService(ILogger<MyService> logger, TelemetryClient telemetry)
{
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
Telemetry = telemetry ?? throw new ArgumentNullException(nameof(telemetry));
}
public void Foo()
{
Logger.LogInformation("Foo");
Telemetry.TrackTrace("BarLog", Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
Telemetry.TrackEvent("BarEvent");
}
Update: There was an issue with the host.json in my original answer and sample - logs weren't really persisted to AppInsights because of https://github.com/Azure/azure-functions-host/issues/4345. I updated the code accordingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With