how to use structured logging in Azure Functions - azure

I am using the relatively new ILogger (vs. TraceWriter) option in Azure functions and trying to understand how logs are captured.
Here's my function:
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, ILogger log)
{
log.LogTrace("Function 1 {level}", "trace");
log.LogWarning("Function 1 {level}", "warning");
log.LogError("Function 1 {level}", "error");
return req.CreateResponse(HttpStatusCode.OK, "Success!!!!");
}
When I look at the server logs, the LogFiles directory has a hierarchy.
The yellow highlighted file includes my log statements:
2017-08-19T13:58:31.814 Function started (Id=d40f2ca6-4cb6-4fbe-a05f-006ae3273562)
2017-08-19T13:58:33.045 Function 1 trace
2017-08-19T13:58:33.045 Function 1 warning
2017-08-19T13:58:33.045 Function 1 error
2017-08-19T13:58:33.075 Function completed (Success, Id=d40f2ca6-4cb6-4fbe-a05f-006ae3273562, Duration=1259ms)
The structured directory contains nothing here, but it seems to have various "codeddiagnostic" log statements in my real function applications directory.
What should I expect here? Ultimately, I would like to have a single sink for logging from all of my application components and take advantage of structured logging across the board.

The best way to collect structured logging from Azure Functions is to use Application Insights. One you defined that your Logger is based on ILogger, you can define a Template that specifies the properties you want to log. Then on Application Insights traces, using the Application Insights Query Language (aka Kusto) you can access the values of each of these properties with the name customDimensions.prop__{name}.
You can find a sample of how to do this with Azure Functions v2 on this post https://platform.deloitte.com.au/articles/correlated-structured-logging-on-azure-functions

Just FYI: Azure Functions running in isolated mode (.NET5 and .NET6) don't support structured logging using the ILogger from DI or provided in the FunctionContext. As of November 2021, there is an open bug about it: https://github.com/Azure/azure-functions-dotnet-worker/issues/423
As I understand it, the bug happens because all ILogger calls goes through the GRPC connection between the host and the isolated function, and in that process the message gets formatted instead of sending the original format and arguments. The Azure Insights connection that would record the structured log runs on the host and only receives the final message.
I plan on investigating some king of workaround, playing with direct access to Azure Insights inside the isolated process. If it works, I'll post the workaround in a comment at the bug linked above.

I had the same question. The log file logger doesn't really respect structured logging, but if you use AppInsights for Azure Functions it will in fact add custom properties for your structured logging
I had a conversation going about it here
https://github.com/Azure/azure-webjobs-sdk-script/issues/1675

Related

Stopping the listener 'Microsoft.Azure.WebJobs.Host.Blobs.Listeners.BlobListener' for function <XXX>

I have function app where I have one HttpTrigger and 3 BlobTrigger functions. After I deployed it, http trigger is working fine but for others functions which are blob triggers, it gives following errors
"Stopping the listener 'Microsoft.Azure.WebJobs.Host.Blobs.Listeners.BlobListener' for function " for one function
Stopping the listener 'Microsoft.Azure.WebJobs.Host.Listeners.CompositeListener' for function
" for another two
I verified with other environments and config values are same/similar so not sure why we are getting this issue in one environment only. I am using consumption mode.
Update: When file is placed in a blob function is not getting triggered.
Stopping the listener 'Microsoft.Azure.WebJobs.Host.Blobs.Listeners.BlobListener' for function
I was observed the same message when working on the Azure Functions Queue Trigger:
This message doesn't mean the error in function. Due to timeout of Function activity, this message will appear in the App Insights > Traces.
I have stopped sending the messages in the Queue for some time and has been observed the traces like Web Job Host Stopped and if you run the function again or any continuous activity is present in the Function, then this message will not appear in the traces.
If you are using elastic Premium and has VNET integrated, the non-http trigers needs Runtime scale monitoring enabled.
You can find Function App-->Configuration--> Function runtime settings and turn on Runtime scale monitoring.
If function app and storage account which holds the metadata of the function Private linked, you will need to add the app settings WEBSITE_CONTENTOVERVNET = 1.
Also, make sure you have private linked for blob, file, table and queue on storage account.
I created ticket with MS to fix this issue. After analysis I did some code changes as
Function was async but returning void so changed to return Task.
For the trigger I was using connection string from app settings. But then I changed it to azureWebJobStorage(even though bobth were same) in function trigger attribute param
It started working. So posting here in case it is helpful for others

No exceptions or stack traces in Azure Application Insights

I have an ASP.NET Core 3.1 solution deployed into an Azure Web App hooked up to Application Insights. I can't for the life of me get exceptions and stack traces to log into Application Insights, instead I get a basic request trace with no exception information attached:
I've tried most combinations of setting up logging/application insights telemetry, here are some of the things I've tried:
services.AddApplicationInsightsTelemetry(); in the ConfigureServices() method of Startup.cs
Adding logging.AddApplicationInsights(); to my logging builder in Program.cs
Removing the custom error page exception handler in case that was affecting things
I have the APPINSIGHTS_INSTRUMENTATIONKEY environment variable set on my Web App in Azure.
I'm using the following code to generate exceptions in Application Insights:
[AllowAnonymous]
[Route("autoupdate")]
public async Task<IActionResult> ProfileWebhook()
{
var formData = await this.Request.ReadFormAsync();
var config = TelemetryConfiguration.CreateDefault();
var client = new TelemetryClient(config);
client.TrackException(new Exception(string.Join("~", formData.Keys)));
logger.LogError(new Exception(string.Join("~", formData.Keys)), "Fail");
throw new Exception(string.Join("~", formData.Keys));
}
Nothing is working and I'm going crazy! Any help greatly appreciated.
Usually, Application insights will guarantee that all the kinds of telemetries(like exceptions, trace, event etc.) will be arrived around 5 minutes, please refer this doc: How long does it take for telemetry to be collected?. But there is still a chance that it will take a longer time due to beckend issue(a very small chance).
If you're using visual studio, you can check if the telemetry is sent or not via Application Insights search.
You can also check if you're using a correct IKey, or if you have enabled sampling.
But if it keeps this behavior in your side, you should consider contacting MS support to find the root cause.
Hope it helps.

Http Trigger Azure function returns 404 randomly

We have a .net core azure function on function runtime 3. This works perfectly fine ran locally and most of the time on our deployed app service. However we've experienced intermittent 404 responses for requests that go through perfectly fine at other times.
There's no entries appearing in our logs or application insights telemetry for the failing requests.
It feels a lot like this issue on the azure-function-host github project:
https://github.com/Azure/azure-functions-host/issues/5247
though that's targeting functions runtime 1 or 2.
Has anyone had similar issues or know of any way to get additional log info that might highlight what problem we're running into.
That might happen during scaling out or your function app about to change the server from one to another (for some reason). That's the actually cons of serverless applications.
But what I can suggest to you is:
Create HeartBeat Function similar to this:
private readonly IAsyncRepository<Business> _businessAsyncRepository;
public HeartBeat(IAsyncRepository<Business> businessAsyncRepository)
{
// Your all DI injections are here
_businessAsyncRepository = businessAsyncRepository;
}
[FunctionName(nameof(HeartBeat))]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
return new OkObjectResult("OK");
}
And then create availability test on Application Insights and call the HeartBeat.
This will also give you a warm instance of Azure Functions at all time. But obviously you spend your 1m free call on consumption plan every time you call the heartbeat depending on how frequently you call the AF.

Nlog in Azure function V1

Thanks in advance.
I want to use Nlog in Azure function V1,I have added Nlog and config file.I can see the ilogger object getting created, but that is not writing to console:(
Only tracewriter provided by Azure function alone working in console log.
Have never tried deploying an Azure Function, but many seems to have issues with deploying NLog.config (or other resource/config-files).
Maybe try putting the NLog-configuration into appsetting.json (Requires explicit load of NLogLoggingConfiguration) :
https://github.com/NLog/NLog.Extensions.Logging/wiki/Json-NLog-Config
The NLog Trace Target (with rawWrite=true) should support Azure Streaming Log.
See also: https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-cloud-logging-with-Azure-function-or-AWS-lambda

How to get runtime status of queue triggered azure function?

My azure function is calculating results of certain request jobs (cca. 5s-5min) where each job has unique jobId based on the hash of the request message. Execution leads to deterministic results. So it is functionally "pure function". Therefore we are caching results of already evaluated jobs in a blob storage based on the jobId. All great so far.
Now if a request for jobId comes three scenarios are possible.
Result is in the cache already => then it is served from the cache.
Result is not in the cache and no function is running the evaluation => new invocation
Result is not in the cache, but some function is already working on it => wait for result
We do some custom table storage based progress tracking magic to tell if function is working on given jobId or not yet.
It works somehow, up to the point of 5 x restart -> poison queue scenarios. There we are quite hopeless.
I feel like we are hacking around some of already reliably implemented feature of Azure Functions internals, because exactly the same info can be seen in the monitor page in azure portal or used to be visible in kudu webjobs monitor page.
How to reliably find out in c# if a given message (jobId) is currently being processed by some function and when it is not?
Azure Durable Functions provide a mechanism how to track progress of execution of smaller tasks.
https://learn.microsoft.com/en-us/azure/azure-functions/durable-functions-overview
Accroding to the "Pattern #3: Async HTTP APIs" the orchestrator can provide information about the function status in form like this:
{"runtimeStatus":"Running","lastUpdatedTime":"2017-03-16T21:20:47Z", ...}
This solves my problem about finding if given message is being processed.
How to reliably find out in c# if a given message (jobId) is currently being processed by some function and when it is not?
If you’d like to detect which message is being processed and get the message ID in queue triggered Azure function, you can try the following code:
#r "Microsoft.WindowsAzure.Storage"
using System;
using Microsoft.WindowsAzure.Storage.Queue;
public static void Run(CloudQueueMessage myQueueItem, TraceWriter log)
{
log.Info($"messageid: {myQueueItem.Id}, messagebody: {myQueueItem.AsString}");
}

Resources