This code comes directly from the Durable Function startup in Visual Studio 2019
[FunctionName("Orchestrator_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
// Function input comes from the request content.
string instanceId = await starter.StartNewAsync("Orchestrator", null);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
Where are the values for IDurableOrchestationClient starter & ILogger log coming from? Since these parameters wont be passed in the HTTP request, I'm assuming that there must be some IoC magic happening behind the scenes, but I'm not entirely sure what/where it is.
I'm assuming that there must be some IoC magic happening behind the scenes.
Correct.
Where is the value for IDurableOrchestrationClient coming from?
The IoC is from AddDurableTask (source). IDurableClientFactory creates IDurableClient which inherits from IDurableOrchestrationClient. You can find an example on usage of AddDurableTask here.
serviceCollection.TryAddSingleton<IDurableClientFactory, DurableClientFactory>();
Where is the value for ILogger coming from?
(as #Ian Kemp and #Nkosi already pointed out)
The IoC is from AddWebScriptHost (source). ILoggerFactory creates ILogger.
loggingBuilder.Services.AddSingleton<ILoggerFactory, ScriptLoggerFactory>();
Related
I an trying to log details of my function app into Application Insights.
My basic code:
public class AzureAppInsightsExplore
{
private readonly ILogger<AzureAppInsightsExplore> logger;
public AzureAppInsightsExplore(ILogger<AzureAppInsightsExplore> logger)
{
this.logger = logger;
}
[FunctionName("AzureAppInsightsExplore")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) //Can we directly use log
{
// Unable to find this log in trace but in live metrics it is shown.
logger.LogInformation("C# HTTP trigger function processed a request.");
int a = 0, b = 0;
//Unhandled exception
int c = a / b;
return new OkObjectResult(string.Empty);
}
}
Host.Json:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
}
}
Here are few strange things I have noticed (not sure where I am doing wrong).
Unhandled Exception is logging twice in Application Insights.
Any specific reason to inject ILogger<ClassName> logger when function run method is having ILogger log by default.
Main concern is that I am seeing a lot of unwanted logs in trace table, where I am just expecting it would have information that I log in code with log.LogXXX(message).
Is there a way that I can stop loading unwanted data Trace table, because it would increase the cost.
I am not see those logs messages that I am logging from code (I have tried after 10 mins, as it might take some time to load into trace tables) , but I can see those logs in Live metrics.
Can someone suggest me on the above, It would be really helpful.
Kind regards.
Thanks #Hooman Bahreini, According to SO-Thread it says,
ILogger: is responsible to write a log message of a given Log Level.
ILoggerProvider: is responsible to create an instance of ILogger (you are not supposed to use ILoggerProvider directly to create a logger).
ILoggerFactory: you can register one or more ILoggerProviders with the factory, which in turn uses all of them to create an instance of ILogger. ILoggerFactory holds a collection of ILoggerProviders.
We can able to see logging messages you need give correct format in quotations and column name too:
I am working in an app with different functions apps. Each function APP has it own VS solution and now I have to add Health Check to each Function App. Basically a function like this:
public class HealthFunction
{
private readonly HealthCheckService _healthCheckService;
public HealthFunction(HealthCheckService healthCheck)
{
_healthCheckService = healthCheck;
}
[FunctionName("health")]
public async Task<IActionResult> Health(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health")]
HttpRequest req,
ILogger log)
{
log.Log(LogLevel.Information, "Received health request");
var status = await _healthCheckService.CheckHealthAsync();
return new OkObjectResult(Enum.GetName(typeof(HealthStatus), status.Status));
}
}
Is there some way to share this HealthFunction in something like nuget package? or something else?
Basically, function application is basing on the folder structure and existence of function.json files where function trigger and bindings are defined to create a function within a Function App.
You'd need to prepare a package that besides adding a dll, will also add the function.json to the build output.
I didn't try that, it's not simple but it seems doable.
Following links might help you:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-class-library?tabs=v2%2Ccmd#autogenerated-functionjson
https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference#function-code
Currently i have scenario where i need to unit test a Service Bus Trigger Function. Fa code as below
public async Task Run([ServiceBusTrigger("sample", Connection = "sample", IsSessionsEnabled = false)] Message message, IMessageReceiver messageReceiver, ILogger _log)
{
//Some code
}
I was primarily using MessageReceiver, but it's hard to unit test as it's not much flexible to Mock,so i switched to IMessageReceiver. Getting below Error
Microsoft.Azure.WebJobs.Host: Can't bind parameter 'messageReceiver' to type 'Microsoft.Azure.ServiceBus.Core.IMessageReceiver'.
NB:- It have a Weird issue that the variable name should be messageReceiver, while using MessageReceiver .
Is there anything that i need to follow for IMessageReceiver as well?
As of today, IMessageReceiver is not supported via dependency injection. You can only get MessageReceiver. You can upvote the request to add the support here.
Meanwhile, there's a workaround that you could use, showed here. The workaround is to have an additional, internal method, accepting IMessageReceiver and Function call that is injected MessageReceiver to pass the parameter to the internal method.
I am looking to use Microsoft.Azure.WebJobs.ExecutionContext to get the InvocationId while a function is running, but is there a way to get this while outside of the actual function call.
So if a calling class needs to have some kind of context it can use this. Is it possible?
When you run a function you have ExecutionContext
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log, ExecutionContext context)
{
return req.CreateResponse(System.Net.HttpStatusCode.OK, context.InvocationId);
}
So if you call any method you probably will need to path this id to it. I am not sure if there is any kind of static helper for that.
You have to thread that as a parameter through all your calls, trying to solve this with some kind of ambient storage, like TLS or AsyncLocal is probably not the best approach but it will probably work.
If you don't use async APIs you might get away with:
[ThreadLocal]
public static Guid InvocationId;
...but if you do use async, you can try:
public static AsyncLocal<Guid> InvocationId = new AsyncLocal<Guid>();
Good luck!
I have went through most of the documentation, and I am still unsure about specific usage of dependency scopes.
When my request hits my controller, I usually can use dependencies of the controller (provided via Constructor Injection) and not worry myself about it much.
However, I am writing a Delegating Handler:
public class MyHandler: DelegatingHandler
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
// I need IMyService here
return await base.SendAsync(request, cancellationToken);
}
I initially tried doing:
using(var scope = request.GetDependencyScope()){
var service = scope.GetService(typeof(IMyService));
}
But that - while it works - seems to close the scope and prevent my Controller from even initializing correctly.
I could do:
{
var requestScope = request.GetDependencyScope();
var scope = requestScope.GetRequestLifetimeScope();
var service = scope.Resolve<IMyService>();
// use service
return await base.SendAsync(request, cancellationToken);
}
but will that not create resource leak? Will the RequestLifetimeScope be disposed of when the request finishes?
If you could provide me with a sample of correct, best-practices style basic DelegatingHandler using Autofac-resolved service, that would help me greatly.
The request-level dependency scope is created for you and disposed for you. Just get it (not inside a using) and resolve from it if you need to. Of course, make sure the Autofac middleware executes before your middleware so the scope can be created for you; and if that's the case, it'll clean up after you, too. Automatically.