-
Notifications
You must be signed in to change notification settings - Fork 448
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
ITelemetryProcessor does not appear to be supported in Function Apps #3741
Comments
From @roryprimrose on November 2, 2018 4:13 This is a big issue for me as well. The amount of trace records being written to AI is large and increases the cost. Being able to filter out the unnecessary entries would save a lot of bandwidth and cost. |
My scenario is that I want to remove trace messages written to AI, primarily from the storage extension while allowing custom metrics to be sent to AI. I've tried just about everything to get a resolution to this without success. I'm also using DI for my C# functions. Here are some of the things I've found:
This wiped out all Information tracing to AI. I would prefer to be more targeted than that, but it solved the first problem. Unfortunately it also wiped out reporting of customMetrics to AI. I suspect this is because customMetric records are written with a trace level of Information. This was a little weird though because on reflection I realised I was sending custom metrics directly from the TelemetryClient rather than via any injected ILogger.
|
This is a great scenario so it'd be interesting to walk through it here. and I can build these up on the wiki to help everyone else, too. I'm guessing that the processor isn't working b/c the processor chain gets built here: https://github.com/Azure/azure-webjobs-sdk/blob/dev/src/Microsoft.Azure.WebJobs.Logging.ApplicationInsights/Extensions/ApplicationInsightsServiceCollectionExtensions.cs#L270. Once that happens, I believe it's immutable. If we wanted to allow custom processors, we'd need to expose some other builder mechanism that allowed you to plug in before we build. But we may be able to solve this with filters. What are the specific messages that you're trying to silence? You can filter anything based on the category (or even the category prefix). So if you know what you want to let through and what you want to prevent, we should be able to craft the right filter. To see the category of a particular message, check the |
@brettsam Yes, the categories between traces and customMetrics are different. I'll try using a config filter against the traces category. |
@brettsam Nope, sorry, I was right the first time. My custom metrics, written directly via TelemetryClient, are being recorded with the same category used to write trace records from the queue trigger. I have a queue trigger These are the customMetrics that are recorded for both scenarios. These are the trace records written by the triggers. So I can't use a logging config filter to wipe out the trace records for the storage triggers without also wiping out the custom metrics. Why is TelemetryClient coupled to ILogger configuration filters? |
Can you share how you're logging your metrics? We've added a |
I'm not using the For example, I have some processes where the metric data can be aggregated to one or five minute blocks of data where hundreds of individual metrics could be tracked within those periods. This saves a lot of raw metrics being sent to AI. As far as getting the
The |
I have a related problem so I thought I'd write about it here rather than make a new issue. I've tried implementing the ITelemetryProcess interface to filter them out, and then later found here that this doesn't work. Is there some other way to disable Dependency Tracking in Application Insights for Function Apps? Currently, my two options are 1) Pay a substantial amount of money to needlessly track dependency successes, or 2) get rid of Application Insights. |
I am also having this same problem. I have been trying to filter our Dependency Tracking as it's costing a large sum of money for data I don't really need. |
@michaeldaw hit the nail on the head. We're having the exact same issue and would love to be able to reduce our AI bill by filtering out records. Particularly filtering out successful dependency calls would be a big positive. For now we're going to have to replace our logging implementation to write useful data to another logging service until this gets some traction. |
@brettsam do you have a good feel for what the right feature / fix is that could resolve this? Seems to be a fairly common type ask and not sure I'm clear on exactly if just a doc gap, feature gap, or something that could be solved with other in flight work. |
I apologize for the delay -- I lost track of this issue. Looping in @lmolkova for her thoughts as well. For the core issue filed -- registering a custom There's a couple of other issues brought up that are good as well:
|
@brettsam For me, the category seems to always be Function.FunctionName. I don't see any categorized as Host.Bindings. |
Here is a code sample that demonstrates how to add a processor to the chain. We should probably simplify this and enable the same approach as we have for TelemetryIntializers using System.Linq;
using FunctionApp12;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Hosting;
using Microsoft.Extensions.DependencyInjection;
[assembly: WebJobsStartup(typeof(Startup))]
namespace FunctionApp12
{
public class Startup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
var configDescriptor = builder.Services.SingleOrDefault(tc => tc.ServiceType == typeof(TelemetryConfiguration));
if (configDescriptor?.ImplementationFactory == null)
return;
var implFactory = configDescriptor.ImplementationFactory;
builder.Services.Remove(configDescriptor);
builder.Services.AddSingleton(provider =>
{
if (!(implFactory.Invoke(provider) is TelemetryConfiguration config))
return null;
config.TelemetryProcessorChainBuilder.Use(next => new AiErrorFilteringProcessor(next));
config.TelemetryProcessorChainBuilder.Build();
return config;
});
}
}
internal class AiErrorFilteringProcessor : ITelemetryProcessor
{
private readonly ITelemetryProcessor _next;
public AiErrorFilteringProcessor(ITelemetryProcessor next)
{
_next = next;
}
public void Process(ITelemetry item)
{
if (!(item is TraceTelemetry trace && trace.Message == "AI (Internal): Current Activity is null for event = 'System.Net.Http.HttpRequestOut.Stop'"))
{
_next.Process(item);
}
}
}
}
Agree on this, but the failure criteria problem would immediately arise after that (are 404, 401, 409, 429 failures). Normally we approach this problem by sampling: you either want everything for the particular transaction to be sampled in or nothing at all. So I'd suggest to carefully weight everything before deciding to disable successful dependency tracking. |
What @lmolkova has above will work -- it lets you grab the TelemetryConfiguration that we generate and append an ITelemetryProcessor to it. From there, you can filter out any DependencyTelemetry however you want. Thanks for putting that together @lmolkova! That at least gives folks an escape hatch while we work through the design here. We'll keep this issue open and work to come up with better configuration and extensibility for this. And thanks a ton @michaeldaw (and others) -- having all this data makes it really easy to see how important this is. A couple of other notes to anyone trying the DI approach above (neither of these will be required long-term, but are right now):
|
@brettsam @lmolkova Thanks for looking in to this, everyone. I've implemented the code @lmolkova posted above. Here's my implementation of ITelemetryProcessor specifically for filtering out DependencyTelemetry items:
|
What version of the host are you running locally? Can you check the
|
I wasn't aware of the extensions.json file, but it looks like that was the problem. {
"extensions":[
{ "name": "DurableTask", "typeName":"Microsoft.Azure.WebJobs.Extensions.DurableTask.DurableTaskWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.DurableTask, Version=1.0.0.0, Culture=neutral, PublicKeyToken=014045d636e89289"},
{ "name": "AzureStorage", "typeName":"Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage, Version=3.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"},
{ "name": "Startup", "typeName":"Scadavantage.Startup, Scadavantage.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}
]
} The file in Azure did not have that last line mentioning the Startup class. I deploy to this Function App from Azure DevOps. Something there must ignore the file when deploying. I can look further in to that. I added the last line manually using Kudu. With that last line in place, it seems to work! I'm not seeing Dependency calls in the either the Live Metrics Stream, or when I do a search for events. What a relief! I wanted to mention that with this filter in place, the Live Metrics view seems to be adversely affected. I no longer see vales in the Request Rate or Request Duration graphs in the Live Metrics view. Could this be related to the concerns raised by @lmolkova about related events being affected by the absence of dependency events? Requests and traces still appear fine in the Search section. In any event, I'm very much willing to live with a diminished experience with the Live Metrics Stream if it means so drastically reducing our costs. Thank you very much to everyone who's been looking in to this! It's a huge help. Not sure if it still matters, but here's my local host version:
|
Can you share the package references in your .csproj? And what is your TargetFramework? I'm seeing several reports of build servers incorrectly generating the extensions.csproj so I'm trying to narrow it down. |
Absolutely. The target framework is .NET Core 2.1.
It mentions a "scadavantage.common.core". Here are the package references from that package:
Let me know if I can help further. |
Thanks that helped confirm the problem. I just opened this issue (feel free to comment over there so we don't derail this issue :-)) Azure/azure-functions-vs-build-sdk#277 |
thanks for the great write up! Now I understand your motivation for disabling dependencies better. Not tracking successful calls to the majority of bindings (e.g. tables) is reasonable and would not create any obvious issues with UX as long as these dependencies are leaf nodes. Not tracking http calls to your own services or some output bindings (e.g queues) would break end-to-end tracing. Think about transaction traces as a tree. If one node is missing, reference is lost and instead of one tree, we now have two. We still know they are correlated, but causation is lost. In some cases, it is still good enough and for sure much better than the costs associated with redundant data. As @brettsam mentioned (Azure/azure-webjobs-sdk#2123), we'll provide better configuration to turn off the collection. I'll also check why sampling was not useful for original issue author, maybe something is broken here:
|
@lmolkova: thank you for explaining this. In our case, the functions in question are HTTP-triggered. The dependencies in questions are, for the most part, calls to tables using the .net storage API. It sounds like these kinds of calls would fall under the second part of your explanation (http calls, etc.). I've modified the original Thank you for your help. |
The same here, TelemetryConfiguration is always null for 3.0.7 |
@vitalybibikov, some initial questions:
If both of those are yes, can you share a sample application that reproduces this? Even a csproj file may be enough. |
Adding the "APPINSIGHTS_INSTRUMENTATIONKEY" fixed it for me. I only previously tested it locally, didn't test it in Azure. |
I've checked it out, when APPINSIGHTS_INSTRUMENTATIONKEY is set, Is it reflected in docs? if it's not, maybe it should be reflected, as it's not quite obvious. Thanks. |
What's the current state of this issue? I've tried code posted by @michaeldaw and my custom TelemetryProcessor was indeed called but then Live Metrics in the portal are broken. Now they are showing only CPU/Memory usage. Cannot see traces/dependencies anymore (they are sent for sure because after a few minutes I can see them in the Performance -> Dependencies UI). |
Has there been any progress on fixing this issue? I'm still seeing the issue with Azure Functions V3. |
This change appears to resolve the issue: With this change we should be able to use builder.Services.AddApplicationInsightsTelemetryProcessor() in the same way that we do for ASP.NET Core. |
@luthus's solution above is the correct one, but if you don't want to have to fork the web jobs sdk, you can get it working correctly in durable functions (or azure functions in general) WITHOUT breaking live metrics dependency and error logging like @kamilzzz saw and I did as well with @lmolkova's solution. Adding the // startup.cs
builder.Services.AddSingleton<ITelemetryModule, MyCustomTelemetryModule>();
builder.Services.AddApplicationInsightsTelemetry(Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY"));
// custom module
public class MyCustomTelemetryModule : ITelemetryModule
{
public void Initialize(TelemetryConfiguration configuration)
{
// add custom processors
configuration.TelemetryProcessorChainBuilder.Use(next => new MyCustomTelemetryProcessor(next));
configuration.TelemetryProcessorChainBuilder.Build();
}
}
// custom processor
public class MyCustomTelemetryProcessor : ITelemetryProcessor
{
private readonly ITelemetryProcessor _next;
public MyCustomTelemetryProcessor(ITelemetryProcessor next)
{
_next = next;
}
public void Process(ITelemetry item)
{
bool myCustomSkipTelemetry = false;
if (myCustomSkipTelemetry)
return;
_next.Process(item);
}
} |
@jschieck that works as a workaround for now. |
@jschieck This is good! I just want to clarify something though. The docs specifically say not to add ...but in your testing you found that it is ok to do so when customizing the processors? |
The app we're doing this in runs in a kubernetes cluster not default azure functions so I'm not sure if different rules apply. But we are still getting all of the built in ILogger/app insights functionality from the functions host runtime without any side effects (that we've noticed) Also I haven't tested in a normal function app if |
@jschieck I tested your code sample in a "normal" Azure Function. I can confirm that the telemetry initializers and telemetry processors are called as expected (whereas telemetry processors are not being called for request telemetry items using the previous solution posted in this thread). The drawback of your approach is that telemetry processors are being called for dependencies that are internal to the Azure Functions |
Would it be possible to get the PR for this (Azure/azure-webjobs-sdk#2657) reviewed and merged so users can start utilizing custom telemetry processors? I am in the process of trying to stand up a new functions app that is registering very large numbers of dependency telemetry so utilizing a custom filter to exclude this is a must have. |
So 2 and a half years have passed since original issue was created. As I understand it is still not resolved, just workarounds? |
So I have to filter out an exception, a false positive (for details see Azure/azure-webjobs-sdk#2612, the issue is completely ignored for over half a year now), filtering this exception is a workaround all together, since this exception should not be logged at all... But anyways... I can not use category filtering because exception is thrown by Entity Framework code, the category is I developed a telemetry processor and added it using custom @brettsam @lmolkova the issue is not fixed for over 2 years now. This issue makes us loose money on AI fees and even more money on developing and researching workarounds. Could we please have this issue fixed once and for all? Pretty please? |
@brettsam @lmolkova can the team take a look at this PR? Azure/azure-webjobs-sdk#2657 |
One more thing regarding category filtering. I have a function called let's say
or
But also, inside
My question is: how can I assign custom category to this dependency, because it has |
Another month has passed without even single response from MS... 🤦♂️ Any of you guys can recommend some good Application Insights replacement? |
I came up with a solution that calls telemetry processors on request telemetry items while re-using the existing processor chain (so that the Functions internal dependencies are discarded before hitting the user's telemetry processors). I was hoping that Azure Functions v4 would support telemetry processors but it does not (at least for the in-process hosting model). v4 emits a bit more telemetry and I understand that using telemetry processors can skew the statistics and that sampling is the preferred approach but sometimes I need to discard a specific telemetry item and I'm happy for sampling to apply to everything else. Without any configuration some Functions will incur an Application Insights bill 10 times bigger than the compute bill! Adding telemetry processors support to Azure Functions would make it a more compelling offering. Currently we have to take into consideration the additional Application Insights spending. The solution I came up with has been inspired by the other workarounds posted on this thread. I created a library out of it which hopefully will be easy enough to integrate into any Functions App. The code is a bit too long to post here, the interesting part is the extension method configuring Application Insights. Using this customisation:
The project comes with a couple of sample Functions so that you can see how it behaves. Hopefully this helps someone else, it has helped us reduce our Application Insights spending while retaining the ability to troubleshoot issues. |
We are also impacted by this issue and have tried several options to fix this behaviour. Using the built-in filtering option, we were only able to hide the traces (Executing 'HealthProbe' / Executed 'Health Probe') but couldn't find any out of the box way to filter out the ~70k requests generated in the process. @gabrielweyer solution is indeed allowing us to filter out all the unwanted requests but forces us to import a new package and fix our custom implementation or bring in a lot of code that may break with future releases. Before we spend more time looking into this and implementing an alternative, is there any update on this issue or future plans to allow developers to filter out requests by name? |
We struggle with very high cost for application insights and the solutions and workaround proposed for this issue would help us to reduce the cost and still be able to use application insights. In my opinion, filtering should be possible with configuration, without need to add code which has a high chance to break with future SDK or Function runtime releases... The fact that this issue is open for almost four and a half year now will have some weight in a decision for another monitoring solution... Additionally, I would expect to learn all this things I can read in this thread in the documentation without having to read through a GitHub-issue! |
What is the status on this? It will soon be 5 years since this was opened. Please provide some feedback. |
I've encountered the same issue when first using isolated Azure Functions. The host manages the The repository is available here and is also published as a NuGet package that can be referenced in your isolated azure function project. This worker extension introduces custom HTTP trigger function bindings that incorporate a custom
Discarding successful request events has been a primary objective, significantly reducing our Azure analytics ingestion costs. These costs were primarily driven by front door health probes, which generated gigabytes of data daily. This should assist others looking to optimize their Azure analytics expenses. |
@JackD111 thanks for saving the day your nuget package is exactly what we needed |
@JackD111 I am facing the same issue (RequestTelemetries being handled by host only) and had a look at your project. I tried to replicate it to adapt it to my requirements but I had issues with the extension startup not being invoked.
|
From @StevenTaylor on October 5, 2018 5:50
Documentation (https://docs.microsoft.com/en-us/azure/application-insights/app-insights-api-filtering-sampling) suggests that ITelemetryProcessor can be used to filter\sample the telemetry before it is sent App Insights.
But the implementation code is never called in our Function App.
The code to set up the builder is called, which looks like:
var builder = TelemetryConfiguration.Active.TelemetryProcessorChainBuilder; builder.Use((next) => new AppInsightsFilter(next)); builder.Build();
But the 'Process' method implemented in the class is never called, the class looks like:
` class AppInsightsFilter : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
PS. We have tried setting config values SamplingPercentage (App Insights config) and maxTelemetryItemsPerSecond (host.json) as low as possible to reduce the telemetry data, but there is still too much telemetry.
Copied from original issue: Azure/Azure-Functions#981
The text was updated successfully, but these errors were encountered: