Skip to content
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

Logging not working in Azure Function Isolated Model #2389

Open
chayankar opened this issue Apr 10, 2024 · 8 comments
Open

Logging not working in Azure Function Isolated Model #2389

chayankar opened this issue Apr 10, 2024 · 8 comments
Assignees
Labels
area: migration Items related to migration from the in-process model logging Needs: Attention 👋

Comments

@chayankar
Copy link

chayankar commented Apr 10, 2024

What version of .NET does your existing project use?

.NET 6

What version of .NET are you attempting to target?

.NET 6

Description

Upgrading azure function in-process model into isolated model. Followed the steps mentioned [here](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide?tabs=windows#logging)

When running the function locally, I can see the logs reaching Application Insight, but after deploying it into azure I don't see logs reaching Application Insight, neither in Log Stream.

When working locally, I imported application settings from deployed function app in azure. I am sure that APPINSIGHTS_INSTRUMENTATIONKEY & APPLICATIONINSIGHTS_CONNECTION_STRING are correct.

I tried using Serilog for writing logs into Application Insight using Serilog.Sinks.ApplicationInsights (4.0.0) but the result is same as above.

Used both approaches for obtaining logger instance: Using dependency insjection & via FuctionContext.GetLogger(categoryName) method.

My question is: If function is generating logs when ran locally, then why is it not working as expected in azure?
Is the worker process not communicating with host? Is there any other unknown configuration which is overriding my code?
Do we have to define log level for the categaoryName parameter passed into FuctionContext.GetLogger(categoryName) host.json?

Below is the snippet from startup class.

string appInsightConnectionString = "<application insight connection string>";
var host = new HostBuilder()
.ConfigureServices((context, services) => 
{
	services.AddApplicationInsightsTelemetryWorkerService();
	services.ConfigureFunctionsApplicationInsights();
	services.AddLogging(builder =>{
		builder.AddApplicationInsights(
			telemetryConfig => {telemetryConfig.ConnectionString = appInsightConnectionString;},
                	loggerOptions =>{loggerOptions.FlushOnDispose = true;});
		});
})
.ConfigureLogging(logging =>
{
    logging.Services.Configure<LoggerFilterOptions>(options =>
    {
        LoggerFilterRule defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
            == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
        if (defaultRule is not null)
        {
            options.Rules.Remove(defaultRule);
        }
        options.MinLevel = LogLevel.Information;
    });
})
.Build();
await host.RunAsync();

host.json

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "default": "Information",
      "Function": "Information",
      "Host.Result": "Information",
      "Host.Aggregator": "Information"
    },
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": false,
        "excludedTypes": "Request;Exception;Trace"
      },
      "httpAutoCollectionOptions": {
        "enableHttpTriggerExtendedInfoCollection": false,
        "enableW3CDistributedTracing": true
      }
    },
    "extensions": {
      "durableTask": {
        "maxConcurrentActivityFunctions": 1000,
        "maxConcurrentOrchestratorFunctions": 100
      }
    }
  }
}

Links referred:
#1123
#944
#702
#760
#1123

Project configuration and dependencies

Startup project .csproj file content

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <LangVersion>10</LangVersion>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <AssemblyVersion>2.0.0</AssemblyVersion>
    <FileVersion>2.0.0</FileVersion>
    <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
    <RuntimeIdentifiers>win-x86;win-x64;linux-x64</RuntimeIdentifiers>
    <OutputType>Exe</OutputType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.1.1" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.17.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.2" />
    <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="6.0.6" />
    <PackageReference Include="Serilog" Version="3.1.1" />
    <PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
    <PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="4.0.0" />
    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.35.0" />
    <PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
    <None Update="local.settings.arc.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

Link to a repository that reproduces the issue

No response

@chayankar chayankar added the area: migration Items related to migration from the in-process model label Apr 10, 2024
@kshyju kshyju self-assigned this Apr 11, 2024
@kshyju
Copy link
Member

kshyju commented Apr 11, 2024

Could you please try using the setup code mentioned in our documentation here?

When deploying your app, simply add the APPINSIGHTS_INSTRUMENTATIONKEY app setting entry with the correct value (which you can obtain from your Application Insights resource). That should do the trick.

By following this model, your dotnet isolated function will send logs directly to Application Insights, bypassing the host, similar to how AI integration works for any .NET application.

Let us know how that goes.

@Frulfump
Copy link

Frulfump commented Apr 14, 2024

Could you please try using the setup code mentioned in our documentation here?

When deploying your app, simply add the APPINSIGHTS_INSTRUMENTATIONKEY app setting entry with the correct value (which you can obtain from your Application Insights resource). That should do the trick.

By following this model, your dotnet isolated function will send logs directly to Application Insights, bypassing the host, similar to how AI integration works for any .NET application.

Let us know how that goes.

Is there an issue with using the Application Insights connection string? Since instrumentation key support will end in less than a year.
"On March 31, 2025, support for instrumentation key ingestion will end. Instrumentation key ingestion will continue to work, but we'll no longer provide updates or support for the feature. Transition to connection strings to take advantage of new capabilities."
https://learn.microsoft.com/en-us/azure/azure-monitor/app/sdk-connection-string?tabs=dotnet5

https://azure.microsoft.com/en-us/updates/technical-support-for-instrumentation-key-based-global-ingestion-in-application-insights-will-end-on-31-march-2025/

azure-deprecation/dashboard#212

@chayankar
Copy link
Author

Could you please try using the setup code mentioned in our documentation here?

When deploying your app, simply add the APPINSIGHTS_INSTRUMENTATIONKEY app setting entry with the correct value (which you can obtain from your Application Insights resource). That should do the trick.

By following this model, your dotnet isolated function will send logs directly to Application Insights, bypassing the host, similar to how AI integration works for any .NET application.

Let us know how that goes.

I have followed the mentioned documentation

Deployed function app has right set of APPINSIGHTS_INSTRUMENTATIONKEY & APPLICATIONINSIGHTS_CONNECTION_STRING as well. How do I know it is right? Because the setting is imported into local.settings.json & when the function is running locally, I can see the logs in AI.

But logs are not reaching AI from deployed function app. I know that the function app is executing because i can see entries in exception table in AI. But I don't see any entries in traces.

I am obtaining logger instance from FunctionContext.GetLogger(
). Am I missing any settings in host.json?

@kshyju
Copy link
Member

kshyju commented Apr 23, 2024

@chayankar

How do I know it is right?

How do you know "what" is right? Can you be more specific?

The local.settings.json is a file to define your app settings when running locally. It has no role when your app is running on azure. You need to specify your app settings under "Settings -> Environment variables -> App settings"

Can you try creating a new AI resource, copy it's connection string and update your deployed app's APPLICATIONINSIGHTS_CONNECTION_STRING app setting to have this new value, then restart the app and see that works? Also remove the APPINSIGHTS_INSTRUMENTATIONKEY (You don't need both of them(

@sopya88
Copy link

sopya88 commented Jun 12, 2024

Use below code in Program.cs, it will start working, Also do proper DI in function class for ILogger,

var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services =>
{

services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();

})
.ConfigureLogging(logging =>
{
logging.Services.Configure(options =>
{
LoggerFilterRule defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
== "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
if (defaultRule is not null)
{
options.Rules.Remove(defaultRule);
}
});
})
.Build();
host.Run();

@kshyju kshyju added the logging label Aug 7, 2024
@ccarmannt
Copy link

FYI, the workaround supplied by @sopya88 above doesn't fix anything, at least in the solution I'm running.

@theerakr
Copy link

theerakr commented Aug 29, 2024

Currently I'm using .net 8 isolated
Have you consider move host var into Program.cs instead of Startup.cs

using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services => {
        services.AddLogging();
    })
    .Build();

host.Run();

and if you need to use activity log, like getting the operationId or RootId (using System.Diagnostics),
, I've found that Azure.Core under Functions.Worker need to be 1.41.0 or later
image
which should included the supported DiagnosticSource version
image

@springcomp
Copy link

springcomp commented Dec 5, 2024

@chayankar I think you would benefit from following the sample I shared. It works reliably across both Windows and Linux app service plans. Please, let me know if that solves your issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: migration Items related to migration from the in-process model logging Needs: Attention 👋
Projects
None yet
Development

No branches or pull requests

7 participants