-
Notifications
You must be signed in to change notification settings - Fork 192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to get AppInsights working in .NET 8 Functions v4 #1182
Comments
@LockTar, is that repo public? |
Oeps! Forgot to change that. It's public now |
@SeanFeldman
Program.cs using Microsoft.Extensions.Hosting;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Func.Isolated.Net7.With.AI;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(builder =>
{
// Is added by package "Microsoft.Azure.Functions.Worker.ApplicationInsights".
// Documented here because it is still preview: https://github.com/Azure/azure-functions-dotnet-worker/pull/944#issue-1282987627
builder
.AddApplicationInsights()
.AddApplicationInsightsLogger();
})
.ConfigureServices((ctx, serviceProvider) =>
{
// You will need extra configuration because above will only log per default Warning (default AI configuration) and above because of following line:
// https://github.com/microsoft/ApplicationInsights-dotnet/blob/main/NETCORE/src/Shared/Extensions/ApplicationInsightsExtensions.cs#L427
// This is documented here:
// https://github.com/microsoft/ApplicationInsights-dotnet/issues/2610#issuecomment-1316672650
// So remove the default logger rule (warning and above). This will result that the default will be Information.
serviceProvider.Configure<LoggerFilterOptions>(options =>
{
var toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
== "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
if (toRemove is not null)
{
options.Rules.Remove(toRemove);
}
});
// Setup DI
serviceProvider.AddTransient<IUserDataService, UserDataService>();
})
.ConfigureAppConfiguration((hostContext, config) =>
{
// Add appsettings.json configuration so we can set logging in configuration.
// Add in example a file called appsettings.json to the root and set the properties to:
// Build Action: Content
// Copy to Output Directory: Copy if newer
//
// Content:
// {
// "Logging": {
// "LogLevel": {
// "Default": "Error" // Change this to ie Trace for more logging
// }
// }
// }
config.AddJsonFile("appsettings.json", optional: true);
})
.ConfigureLogging((hostingContext, logging) =>
{
// Make sure the configuration of the appsettings.json file is picked up.
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
})
.Build();
host.Run(); Add {
"Logging": {
"LogLevel": {
"Default": "Information",
"Func.Isolated.Net7.With.AI.MyOtherFunctions": "Error",
"Func.Isolated.Net7.With.AI.MyUserFunctions": "Debug",
"Func.Isolated.Net7.With.AI.UserDataService": "Trace"
}
}
} |
@LockTar thank you for summarizing all of this for others to reference. Glad you were able to get it working. Was the Anyways - is there any action items you want from our side as an outcome of this issue? Keep in mind we do already have intentions to address telemetry in Functions (ideally go with OpenTelemetry). |
Just tested it for you. {
"Logging": {
"LogLevel": {
"Default": "Information",
"Func.Isolated.Net7.With.AI.MyOtherFunctions": "Error",
"Func.Isolated.Net7.With.AI.MyUserFunctions": "Debug",
"Func.Isolated.Net7.With.AI.UserDataService": "Trace"
},
"ApplicationInsights": {
"LogLevel": {
"Default": "Debug"
}
}
}
} Then I would see BUT That's not what you want... Maybe you have fix for that as well but that is exactly the thing that everyone is saying. It is to unclear how everything is working for Azure (Isolated) Functions. |
Yes.
I don't know if OpenTelemetry is going to fix everything but I guess this will not be finished tomorrow. We create new Azure Functions on almost daily level. We need to have clear logging (documentation) from the start. |
For the log filters: For the console logging missing completely in local debugging, something I was missing this entire time was that stdout for the worker is piped to the host, which is not always forwarding them to the terminal you are running in. @fabiocav / @brettsam what is the recommended way to get console logs from worker in local debugging? And we do intend for the OpenTelemetry work to address all of these concerns. You will have much more control over the logs. However, something that won't change is the multiple places to configure logging. Ultimately, you have two processes running - the host and the worker and they have their own respective logging configuration. We will always have to expose the ability to configure them separately ( To summarize, sounds like we just need to help you with the worker --> host stdout pipe causing issues with console logging. |
I understand that you don't want to make conflicts with the AppInsights packages. Otherwise, you will get mixed results in MS Azure services. But removing the Warning filter could be added to the project template in VS20xx. Maybe not enabled but in comment. Maybe with a link to the docs (that I can't find anywhere for Azure Functions...). (See below bullet 2)
Thank you for the explanation. I understand that there are 2 types of places to configure.
Don't get me wrong (not attacking you or colleagues at all) but my employers want me to write (small) business solutions. Azure Functions are ideal for this. That's why I'm using Functions from the beginning. Logging should be more an addition for troubleshooting. It now takes me longer to figure out how logging works (it changes a lot) than I'm writing a complete API... |
hi @LockTar , Thank you so much for putting this together. `Exception has occurred: CLR/System.InvalidOperationException Any ideas how to move forward? |
Your welcome.
I have exactly the same problem. See above comment 1 and comment 2 about this. I think this is related with #1090 but I want that answer from Microsoft because they understand this better than I do.
I never use Visual Studio Code with Azure Functions so I don't know if this is the issue. This is a normal new Azure Function template created with the latest version of Visual Studio 2022. P.S. I think it's not a good idea to mix issues here. Could you please remove you stack trace from above because it's not really well formatted and has nothing to do with this issue. Thank you very much in advance. |
@LockTar , thank you so much, I was able to get the console logs working with that fix of AddConsole(). |
Is there documentation by any chance to explain how the isolated worker functions work with logging, with some visualization? The sample @LockTar has put together is great, but I'd want to see this made into the official documentation. There are samples, and there are code snippets. There should be solid documentation to distill this down. cc @fabiocav |
I'm getting flooded with messages with the category |
@SeanFeldman Is there a simple overview to see all the messages of a category? I think the |
@drew-fc please create new issues for this and remove your comments. This has nothing to do with Azure Functions and logging. This is C# DI. I think StackOverflow is a better place for this question. |
My personal opinion is to inject loggers in the constructor. Just like this. How to inject multiple classes is a DI related question. That's why I said that. But I really think you should create a seperate issue for this and delete your comments (and then I can delete my comments) because this is really something else. Tag me in the other issue so I can maybe assist you. Thanks |
This is what I'm getting from reading through all these comments and doing some experimentation. Please correct me if I'm wrong. Happy to edit/change/delete this comment to avoid confusion. (edited: host.json and overrides)
I'm just trying to understand what I'm dealing with. Having to jump back and forth between computers to write this so forgive me if I get a detail wrong. |
I think you are correct about everything. A lot is speculating so I'm not sure about everything. Hopefully Microsoft will bring some official documentation about this and a new project template. But there is not much response anymore about this...
This should solve it (not tested it myself). |
Calling out how category names are chosen to contrast with other frameworks. This was confusing to me and I thought a little more explicitness might help. Also updated the first example for host.json settings to reflect [Issue 1182](Azure/azure-functions-dotnet-worker#1182).
@LockTar This thread has been very useful and enabled me to get my log levels working. Thanks very much. I have 1 outstanding issue though which I don't understand. Apologies if I did something stupid, but would be grateful if you can shed some light on it. Here is an example Invocation Log: Notice that the "Type" column is not populated for all messages other than the first (that message was generated by the TimerTrigger framework, and not by my code). When I look in ... versus ... Do you see this too? |
At this point, I'm not sure what's going on. Not only are the Azure SDKs at fault for logging multiple messages with the @brettsam, @fabiocav, the issue with AppInsights and logging is becoming more of a pain with financial impact rather than just an inconvenience. |
hey @LockTar , sorry to tag you, but I am following your example and I am stuck. However, everything is being written to AppInsights as "trace" with "Information" as the severity level. Here's an example:
Any ideas? |
I haven't created any .NET 8 function yet. We are still on .NET 6 because of certain missing functionality. We should be able to upgrade to .NET 8 now but we have other priorities. Ontopic: I was hoping that Microsoft/Functions team already picked this GitHub issue up for better explanation/documentation and samples. |
hey @LockTar , thanks for the reply. |
@LockTar looks like I found a hacky work-around to get this working. |
This issue is still valid for .NET 8. So, I changed the title. Hopefully this will be picked up? This important issue is already open since 2022... |
@LockTar Following this, because we have the same issue here... The documentation is very unclear about how to achieve simple things as configure logging. More specifically what to define in the @jviau maybe he can elaborate after a few years? :) Thanks in advance! |
I have been suffering with this for a couple days.
In the end, I found that there are now two paths, each requiring their own dependencies and ways of working.
@brettsam Can you confirm this? And if so, get the documentation updated? Something else I noticed is that when doing a build and deployment on docker, the worker tends to end up in a different folder than the host (
|
Hi @LockTar I have found this thread after reaching mostly the same solution you mentioned in the sample repo and I would like to ask if it is correct or not to use an appsettings.json file, because in the end I am not using it. I came to this similar issue after starting to migrate our Azure Functions .NET6 In-Process to .NET 8 isolated worker model, mostly like @drew-fc on his comment #1182 (comment) . With .NET 6 our Functions are able to write logs on Application Insight without any issue, and we were also able to modify the LogLevel, by changing the Environment variables on the Function App in case some bug appears on any environment. When I started to migrate them to .NET 8 on Isolated model I realized all logs were constantly written in Error LogLevel or higher. Then, I realized on this documentation: https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide?tabs=windows#application-insights Once I applied that configuration, all logs started to be written in Information Level or higher. The last point I needed was to setup the LogLevel based on environment variables that I could also modify on Azure If I needed without any deployment. I achieved firstly with an appsetting.json file and the following configuration:
But it was a little bit strange for me since we don't have any appsetting.json file on none of our .NET 6 Azure Functions. Also motivated by this two threads:
And also by this documentation: https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=azure-portal%2Cto-premium which is not suggesting to use an appsetting.json file, I tryed to remove that part and it's working. So Finally, I have an example Function App which is able to write Logs on Application Insights in the LogLevel configured in an Environment Variable which I can modify without deploying the Function App. The code is mostly similar but removing the appsettings.json part: Program.cs:
Function1.cs:
host.json
|
Well, that is more a choice for you, I guess. The whole idea of this issue is to get logging working and I personally think that you want to set the loglevel for specific parts of the application. Not everything to Trace and everything to Error. It's easy to use
I don't see the part that they don't suggest to use an appsettings.json. Or I'm missing your point.
Do you have a sample application for me? Or fork my repo and create a new project next to it? That would be great. |
I am just getting so frustrated by hard configuring these logs are. So far I just want
I have done like 50 iterations of different configurations, but either performance logs completely disappear or So far my function looks like this, but I am completely unsure what I should configure at host.json/appsettings.json vs in the function code. public class Program
{
public static IHostBuilder GetHostBuilder()
{
return new HostBuilder()
.ConfigureFunctionsWebApplication(builder => { builder.UseMiddleware<ExceptionHandlerMiddleware>(); })
.ConfigureLogging((context, logging) =>
{
//logging.AddFilter("System.Net.Http.HttpClient", LogLevel.Warning);
//logging.AddFilter("Microsoft", LogLevel.Warning);
})
.ConfigureServices((hostContext, services) =>
{
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
services.Configure<LoggerFilterOptions>(options =>
{
// The Application Insights SDK adds a default logging filter that instructs ILogger to capture only Warning and more severe logs.
// Application Insights requires an explicit override.
// Log levels can also be configured using appsettings.json.
// For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service#ilogger-logs
LoggerFilterRule? defaultRule = options.Rules.FirstOrDefault(rule =>
rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
if (defaultRule is not null)
{
options.Rules.Remove(defaultRule);
}
});
});
}
} |
Added following .ConfigureLogging((context, logging) =>
{
logging.AddFilter<ApplicationInsightsLoggerProvider>("Microsoft", LogLevel.Warning);
logging.AddFilter<ApplicationInsightsLoggerProvider>("Host", LogLevel.Warning);
logging.AddFilter<ApplicationInsightsLoggerProvider>("Host.Results", LogLevel.Information);
logging.AddFilter<ApplicationInsightsLoggerProvider>("System", LogLevel.Warning);
}) and // host.json
{
"version": "2.0",
"logging": {
"logLevel": {
"default": "Warning"
},
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
},
"enableLiveMetricsFilters": true
}
}
}
EDIT: Nvm. Local implementation does not work in cloud. EDIT2: alright took forever, but final working config for myself {
"version": "2.0",
"logging": {
"logLevel": {
"Function.*": "Warning",
"Host.Triggers": "Warning",
"Microsoft": "Warning"
},
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
},
"enableLiveMetricsFilters": true
}
}
} .ConfigureLogging((context, logging) =>
{
logging.AddFilter<ApplicationInsightsLoggerProvider>("Microsoft", LogLevel.Warning);
logging.AddFilter<ApplicationInsightsLoggerProvider>("System", LogLevel.Warning);
}) Kinda explanation what everything does. In some cases you can add more explicit filters if you want to keep some specific information. Function:
Host:
|
After reading all of this sad logging story, I'm now wondering where should It seems they don't work if I leave the settings in The fact that Function initialization differs so much from Web Apps ( |
I tried all the solutions from here and nothing works when function is running in docker container and as result when application insights used in azure i can see only warning and highers logs. Can anybody has as example that works? |
In #2531, I illustrate how to reliably have full control on your logging experience. This also aligns with both the latest practices and versions of the NuGet packages. For those who prefer using the using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureAppConfiguration((hostContext, config) =>
{
// Add appsettings.json configuration so we can set logging in configuration.
// For instance, add a new file called "appsettings.json" to the root of your project
// and set the following properties to:
// Build Action: None
// Copy to Output Directory: Copy if newer
//
// Content:
// {
// "Logging": {
// "LogLevel": {
// "Default": "Warning" // Change this to i.e. "Trace" for more logging
// }
// }
// }
var basePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
config.SetBasePath(basePath!);
config.AddJsonFile("appsettings.json", optional: false);
config.AddEnvironmentVariables();
})
.ConfigureServices(services =>
{
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
services.Configure<LoggerFilterOptions>(options => {
// The Application Insights SDK adds a default logging filter that instructs ILogger to capture only Warning and more severe logs. Application Insights requires an explicit override.
// Log levels can also be configured using appsettings.json. For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service#ilogger-logs
LoggerFilterRule? toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
== "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
if (toRemove is not null)
{
options.Rules.Remove(toRemove);
}
});
services.ConfigureStartupServices(); // bring up your own Startup class to register DI services
})
.ConfigureLogging((hostingContext, logging) =>
{
var services = logging.Services;
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
})
.Build();
host.Run(); |
@springcomp Is it expected to work also on .NET 9 in Isolated Model? It seems that I am not able to control log levels using |
A few years back I started this thread. It's amazing that a product like this is changing this much but simple logging is still so difficult. Last November, I created a new version of my sample app just to get logging working. I know it's .NET 8 and I think a few packages are not up to date anymore but it works. Logging lower than information is still a problem but I can live without it. The most important thing is that I can log every function call. I can control it how I like it. Another important thing is that it's supported by Microsoft. No custom classes, no difficult setup. Just following all the cryptic pages of documentation of Microsoft. And that's the real problem, the documentation is to wide for just setting up logging in Azure Functions (and of course the missing features). Creating a new project template of my project would help... Last time that I did this was 10 years back. Anyone with more recent knowledge with this? I would love to have a PR. |
Yes indeed, this works in .NET 9. I have contributed a consolidated lesson at Azure Functions University. That is fundamentally a rehash of @LockTar ’s solution that everyone rediscovers by putting all the pieces of the puzzle in the right place. Please, use comments in that pull request to highlight your issues ; I would be happy to take some time to guide you. But it all boils down to this:
Please, feel free to chime in in the commnets of the referred to pull request. |
From what I can tell, yes, this lights up logs in AI as we want however it does not enable structure logging which is pretty critical. For example, this log line: logger.LogInformation("[{CustomOperationId}] Analysis received. {NumLines} line(s) in result.", message.GetProperty("OperationId").GetString(), message.GetProperty("Text").GetString().Split('\n').Length) SHOULD result in an entry in AI with |
I can attest that @LockTar's recently updated sample application produces the expected result in the I can also attest that the consolidated sample i linked to in my previous comment does indeed produce the desired structured logging properties in the Please, be aware of a few changes, though:
In your example, you do not even have a custom |
Hi,
Sorry for the new issue but I think this will bring a lot of open issues together to a final solution in a sample repository.
Hopefully we can make something default/officially/easier for new people because it took me a long time to figure everything out.
appsettings.json
configuration file for default configuration as suggested in Update samples and docs to add Host.CreateDefaultBuilder() #1025appsettings.json
configuration file.appsettings.json
configuration fileI want to thank @brettsam, @jviau and @kshyju for posting helpful comments that let me finally see some logging in Azure Application Insights lower than Warning (so Trace, Debug, Information).
See the sample repository for more details to get it running. See the details of the
Func.Isolated.Net7.With.AI
project.Screenshots from Azure:
The text was updated successfully, but these errors were encountered: