Azure Functions Logging, get current scope properties - azure

I'm using Azure Functions with Automatic Dependency Tracking disabled and manually tracking my dependencies.
I also use the SDK provided ILogger for traces and metrics, and also heavily use the ILogger.BeginScope(...) to track details about operations.
Is it possible to get the current scope properties so I can add them to my dependency tracking?
Example would be
using(var scope = log.BeginScope("{document}{user}", documentId, userId)){
// do HTTP Call using HttpClient
}
HTTP Client Config
.AddHttpMessageHandler(serviceProvider => new
DependencyLoggingMessageHandler(serviceProvider.GetRequiredService<TelemetryClient>()))
And the Message Handler
public class DependencyLoggingMessageHandler : DelegatingHandler
{
private readonly TelemetryClient client;
public DependencyLoggingMessageHandler(TelemetryClient client)
{
this.client = client;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
try
{
response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
return response;
}
finally
{
client.TrackDependency(new DependencyTelemetry(..){
Data = ...,
Properties = /*how to get scope props? */
});
}
}
}
In the AppInsights dependency created for this, I would like to have document and user as properties like the traces and metrics created by the SDK.
Update:
Currently I have 2 (questionable) solutions
If you want a no frills, easy implementation, use LogMetric("HTTP_REQUEST", duration, properties) which will have the scope properties as usual and add your things to its properties.
Sure it won't show up in app insights dependencies, but you can have the duration of the HTTP request as its value, have the url, host .etc. as custom properties and get most things done. My main requirement is to track duration and urls, which works in this solution so I have settled for this solution for now.
Maintain the scope properties yourself
I think this can be done with essentially duplicating what the Functions Runtime does. i.e Using a custom version of it in a AsyncLocal and iterating from current scope to the root scope and adding them to your telemetry like the runtime does. Looks like a lot more work than its worth to me.
If you have a better/different solution please put your answer below.

Related

Usage of Azure App Configuration's Feature Flags in Azure Functions

I'm working on exploring the following 2 features of Azure App Configuration in Azure Function's Http Trigger
Externalizing the App Settings
Feature Flags
Below is how i'm getting the reference of the configuration
So, when I use _configuration["SomeAppSettingKey"], I'm able to retrieve the value. So, I'm able to achieve #1 feature mentioned above.
My Question is, How do we retrieve the Feature Flag information? I have tried the below ways.
I would appreciate if someone could help me in understanding how to retrieve it in Azure Functions (I'm using V3)? A Sample code or any reference to documentation would be helpful.
Thanks.
Update1:
I can deserialize the json content as shown below. But, is this is the right approach?
Where FeatureManager is a class that I have defined as shown below.
all you need is to call UseFeatureFlags() function as part of AddAzureAppConfiguration to let the App Configuration provider know you want to use feature flags. An example can be found following the link below. It uses the FunctionsStartup and dependency injection (DI) of Azure Functions. An instance of a feature manager is put into the DI.
https://github.com/Azure/AppConfiguration/blob/master/examples/DotNetCore/AzureFunction/FunctionApp/Startup.cs
The link below shows how you can obtain the instance of IFeatureManagerSnapshot from DI and use it as part of your Azure Functions call.
https://github.com/Azure/AppConfiguration/blob/master/examples/DotNetCore/AzureFunction/FunctionApp/ShowBetaFeature.cs
Deserialize JSON is not a good idea, every time you will add new key you need to modify your class.
private static IConfiguration Configuration { set; get; }
static Function1()
{
var builder = new ConfigurationBuilder();
builder.AddAzureAppConfiguration(Environment.GetEnvironmentVariable("ConnectionString"));
Configuration = builder.Build();
}
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string keyName = "TestApp:Settings:Message";
string message = Configuration[keyName];
return message != null
? (ActionResult)new OkObjectResult(message)
: new BadRequestObjectResult($"Please create a key-value with the key '{keyName}' in App Configuration.");
}

Azure Functions - How to change the Invocation ID within the function?

I have a series of Azure Functions, and I'd like to keep track of them by the InovcationId. In Application Insights, the InvocationId is called the operation_Id.
What I'm trying to do is set the operation_Id to be the same across several different Azure Functions.
I can read this property inside the Azure Function when I pass in ExecutionContext by following this answer, but I can't seem to alter it. Is there some way to change this value from inside the Azure Function?
public static class TestOperationId
{
[FunctionName("TestOperationId")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req,
ILogger log,
ExecutionContext exeCtx
)
{
var input = await req.Content.ReadAsStringAsync();
log.Info(input);
exeCtx.InvocationId = Guid.Parse(input);
return req.CreateResponse(HttpStatusCode.OK);
}
}
The definition for the InvocationId field is defined as
Provides the invocation ID, uniquely identifying the current invocation
Azure Functions doesn't provide changing this, as it would mean that code could override the platform's methods to detect unique invocations of Functions, which would interfere with things like Billing and Metrics for the platform.
It sounds like what you really want is cross-function correlation. There is work being done with the Application Insights team to help support this, but in the meantime, you can see solutions that others are currently utilizing, like here.

Configuring lifetime scopes in autofac when used as ServiceStack's IoC

I'm currently using AutoFac as the DI container for our ServiceStack web services app. I'm able to configure the wiring and everything, but after reading the section on Scopes, I'm at a loss at which scope would be best to use when registering my components. In our particular case, I think a PerHttpRequest scope would be OK since (please correct me if im wrong) I would want to dispose the dependencies as soon as the request ends.
My question is, how do I set this up in the container? I can't seem to find the "PerHttpRequest" lifetime scope within the included methods in autofac. I'm also unsure if ServiceStack does some kind of automagic to do this for me behind the scenes.
I'm using Autofac 3.0.1 on ServiceStack 3.9.35 on .Net 4 (running as a regular ASP host, not MVC). I'm also using the class described here as the IContainer adapter.
I wanted to avoid the overhead of the dependency on MVC, so the first answer didn't quite work for me.
Instead I used Funq to register a PerRequest ILifetimeScope, and resolve the ILifetimeScope in the ConatinerAdaptor before resolving the dependency.
public class AutofacLifetimeScopeIocAdapter : IContainerAdapter
{
private readonly Container _requestContainer;
public AutofacLifetimeScopeIocAdapter(Funq.Container requestContainer)
{
_requestContainer = requestContainer;
}
public T Resolve<T>()
{
var currentContainer = _requestContainer.Resolve<ILifetimeScope>();
return currentContainer.Resolve<T>();
}
public T TryResolve<T>()
{
var currentContainer = _requestContainer.Resolve<ILifetimeScope>();
T result;
if (currentContainer.TryResolve<T>(out result))
{
return result;
}
return default(T);
}
}
Then initialise with this
_autofacContainerRoot = builder.Build();
IContainerAdapter adapter = new AutofacLifetimeScopeIocAdapter(container);
container.Register<ILifetimeScope>((c) => _autofacContainerRoot.BeginLifetimeScope())
.ReusedWithin(ReuseScope.Request);
container.Adapter = adapter;
Then cleanup with
public override void OnEndRequest()
{
var currentContainer = _container.Resolve<ILifetimeScope>();
currentContainer.Dispose();
base.OnEndRequest();
}
This seems to behave as required for Autofac - SingleInstance, InstancePerDependency, and now InstancePerLifetimeScope which is perRequest.
Mythz response on the HostContext.Instance.Items collection can likely be used to remove the need for the
var currentContainer = _container.Resolve<ILifetimeScope>();
resolution, which should improve performance.
I think I have figured out how to make this work (using Autofac 2.6, which I am stuck on right now.) It involves using the following adapter and the Autofac.Mvc3 package:
public class AutofacIocAdapter : IContainerAdapter
{
private readonly IContainer _autofacRootContainer;
private readonly Container _funqContainer;
public AutofacIocAdapter(IContainer autofacRootContainer, Container funqContainer)
{
// Register a RequestLifetimeScopeProvider (from Autofac.Integration.Mvc) with Funq
var lifetimeScopeProvider = new RequestLifetimeScopeProvider(autofacRootContainer,null);
funqContainer.Register<ILifetimeScopeProvider>(x => lifetimeScopeProvider);
// Store the autofac application (root) container, and the funq container for later use
_autofacRootContainer = autofacRootContainer;
_funqContainer = funqContainer;
}
public T Resolve<T>()
{
return ActiveScope.Resolve<T>();
}
public T TryResolve<T>()
{
T result;
if (ActiveScope.TryResolve(out result))
{
return result;
}
return default(T);
}
private ILifetimeScope ActiveScope
{
get
{
// If there is an active HttpContext, retrieve the lifetime scope by resolving
// the ILifetimeScopeProvider from Funq. Otherwise, use the application (root) container.
return HttpContext.Current == null
? _autofacRootContainer
: _funqContainer.Resolve<ILifetimeScopeProvider>().GetLifetimeScope();
}
}
}
Steps to implement:
Add the Autofac.Mvc3 NuGet package to your web project (NOTE: does
not matter that your project isn't using MVC. The solution might be slightly different with Autofac 3, which cannot use Mvc3 integration.)
Follow the ServiceStack IoC page in hooking up a custom IContainerAdapter
for Autofac, using the following implementation
Note the RequestScope in ServiceStack's IOC only refers to ServiceStack's built-in Funq IOC.
To use RequestScope in another IOC Container like AutoFac you generally need to notify AutoFac at the end of the request so it can clean up all its request-scoped instances. To do this, ServiceStack provides the AppHostBase.OnEndRequest() hook you can override to get execute custom logic at the end of each request.
I'm not familiar with how AutoFac's custom lifetime scope works but more details about it can be found in:
AutoFac's InstanceScope wiki page
Primer on AutoFac's Lifetime scopes
Answer on how to manage AutoFac' request scope in MVC
Other info that might be useful for managing instances in ServiceStack is that every instance in put in the HostContext.Instance.Items dictionary or disposable added to HostContext.Instance.TrackDisposable are automatically disposed at the end of each request.
Update 2015-11-25: I changed the implementation by using global request and response filters. I put both ServiceStack V3 and V4 solutions into this repository and both versions are available as nuget packages.
I solved this problem by opening a new scope in Application_BeginRequest and disposing in Application_EndRequest. In the container adapter I check if this scope exists and use it, if not, I use the container. This allows using .InstancePerRequest() registration scope.
Described with gists here.

NServiceBus Unit of Work For Multitenancy with Custom ORM

Here are my parameters:
Simple NServiceBus Saga implementation using the default builder
In-house ORM on top of SQL Server
Multitenancy - I have two ASP.NET MVC 4 domains running on the same website, each with their own databases
We configure our ORM using a static method like so:
public class EndpointConfig: IConfigureThisEndpoint, IWantCustomInitialization {
public void Init() {
var bus = Configure.With()
.AutofacBuilder()
.UnicastBus().LoadMessageHandlers().DoNotAutoSubscribe()
.XmlSerializer()
.MsmqTransport().IsTransactional(true).PurgeOnStartup(false)
.MsmqSubscriptionStorage()
.Sagas().RavenSagaPersister().InstallRavenIfNeeded()
.UseInMemoryTimeoutPersister()
.CreateBus()
.Start();
SlenderConfiguration.Init(bus);
}
}
public class SlenderCofnigruation {
private static ORMScope scope { get; set; }
public static void Init(IBus bus)
{
ORMConfig.GetScope = () =>
{
var environment = "dev";
if (bus.CurrentMessageContext.Headers.ContainsKey("Environment"))
environment = bus.CurrentMessageContext.Headers["Environment"];
if (scope == null)
scope = new SlenderScope(ConfigurationManager.ConnectionStrings[environment].ConnectionString);
return scope;
};
}
}
This works fine in our single-tenant Beta environment - it's fine for that static scope to get re-used because the environment header is always the same for a given deployment.
It's my understanding that this won't work for the multitenant situation described above, because NServiceBus will reuse threads across messages. The same scope would then be used, causing problems if the message was intended for a different environment.
What I think I want is a single scope per message, but I'm really not sure how to get there.
I've seen Unit Of Work Implementation for RavenDB, and the unit of work implementation in the full duplex sample, but I'm not sure that's the right path.
I've also seen the DependencyLifecycle enum, but I'm not sure how I can use that to resolve the scope given the way I have to set up the GetScope func.
Obviously I have no idea what's going on here. Any suggestions?
If you need to do something on a per-message basis, consider using message mutators (IMutateIncomingMessages) in addition to your unit-of-work management with some thread-static state.

Fire and forget with ServiceStack's AsyncServiceBase

I have following service
public class AppService : AsyncServiceBase<EvaluateStock>
{
public IBus Bus { get; set; }
public override object ExecuteAsync(EvaluateStock request)
{
// this will block the incoming http request
// unitl task is completed
// long computation
// Bus.Publish(result)
}
}
which gets called by different consumers following way
POST
http://srv1/app/json/asynconeway/EvaluateStock
Using asynconeway I was assuming that it will allow me to achieve fire and forget as WCF does with IsOneWay. But seems is not the case.
Do I miss something ?
AsyncServiceBase has been deprecated as ExecuteAsync is now in ServiceBase which is what gets called when a request is made to /asynconeway/XXX pre-defined endpoint.
Rather than overriding ExecuteAsync the recommended approach is to implement IMessageFactory which is what gets called if an IMessageFactory has been registered in the AppHost IOC. If an IMessageFactory wasn't registered than it just gets executed Sync - at which point if you still wanted it non-blocking you would override it. The impl for ExecuteAsync is at:
// Persists the request into the registered message queue if configured,
// otherwise calls Execute() to handle the request immediately.
//
// IAsyncService.ExecuteAsync() will be used instead of IService.Execute() for
// EndpointAttributes.AsyncOneWay requests
public virtual object ExecuteAsync(TRequest request)
{
if (MessageFactory == null)
{
return Execute(request);
}
BeforeEachRequest(request);
//Capture and persist this async request on this Services 'In Queue'
//for execution after this request has been completed
using (var producer = MessageFactory.CreateMessageProducer()) {
producer.Publish(request);
}
return ServiceUtils.CreateResponseDto(request);
}
IMessageFactory (client)/IMessageService (server) is apart of ServiceStack's Messaging API which allows you to publish messages for deferred execution later. See the Redis and Messaging wiki for an example of an end-to-end solution that uses the built-in Redis IMessageService. There are also InMemory and RCon IMesssageService's available and it should be easy to create your own as well.
Future Async support
There is also an async branch that has ServiceStack running on IHttpAsyncHandler and already has a functional alpha build available for you to try at: ServiceStack-v4.00-alpha.zip
With this change ServiceStack supports Task<> as a return type on services. You only need to register the Task<> plugin. To see a full example look at this integration test.

Resources