Application Insights Telemetry: can you track traces/events/etc. asynchronously? - c#

I am a longtime user of Azure's Application Insights, and I use the TelemetryClient's TrackTrace() and TrackException() liberally in every enterprise application I write.
One thing that has always bothered me slightly is that these methods are synchronous. Since these methods communicate with an external API, it would seem there is an ever-present risk of blocking; e.g., if the network is down/slow, or if App Insights' own API is having issues.
In such cases, it seems possible (at least in theory) that an entire application could hang. In such cases, if they ever occur, I would like my applications to continue operating despite failing to trace within a reasonable time frame.
I've done some research online, and it appears that there is no built-in way to call these methods asynchronously. Do you know of any way to accomplish this? (Or.....does the App Insights API have an under-the-hood black-box way of automatically preventing these sorts of things?)
Of course, I know I could always wrap my calls in a Task (e.g., await Task.Run(() => myTelemetryClient.TrackTrace("my message")); (or write an async extension method that does this). I could also use a timer to cancel such a request. But it would be nice if there was a more integrated way of doing this.
Can anyone enlighten me? Is this really a potential problem that I should be concerned with? Or am I merely tilting at windmills?
Update: I just now saw this, which indicates that AI does indeed handle tracking in an asynchronous manner "under the hood". But how can this be reliable, given the truism that asynchronous operations really need to be made async all the way up and down the call stack in order to be blocking-proof?

Is this really a potential problem that I should be concerned with?
No. None of the TrackABC() methods communicate with any external API or do anything which would take a long time. Track() runs all telemetry initializers, and then queues the item into an in-memory queue.
While the built-in telemetry initializers are designed to finish quickly and make no I/O or HttpCalls, if a user adds a telemetryinitializer which makes an http call or something similar, then Yes, it'll affect you Track() calls. But with normal usage of TelemetryInitializers, this should not be a concern.

If it's anything like the JS API, the tracking events are placed in a queue then dequeued and sent (possibly in batches at configurable intervals) independently of the TrackXXX methods. Enqueuing an event can be synchronous, but the sending end of the process can operated asynchronously. The queue decouples the two from one another. –
spender
I think #spender answered my question! Thanks!

Related

dotnetcore http thread async await conundrum

in a dotnet core http application we have a call that performs work, makes several http calls out to backing services, and returns. It was all async await. which meant that the call was waiting for the backing services to perform their work before returning the call to the client. this was causing the call to timeout.
the solution that was presented was to remove the async await all the way down as low as we could then essentially just wrap the http calls (still async task methods) in pragma tags that suppress the warning/compiler error.
This makes me nervous because you don't guarantee that the final (or any) of http requests are made before the calling thread returns and the async machines associated with that thread are cleaned up.
Am I missing something? is this one of those weird but usable situations? or would it be more appropriate to spin off threads to handle those http calls?
You're talking about fire-and-forget, and you're right to be worried. There are several problems with fire-and-forget. This is because "forget" means "forget", and it's almost always the wrong decision to have your application just forget about something.
If there's an exception calling one of those inner HTTP requests, that exception will be ignored, unless you have special logic handling that situation. And remember, there's no outer request anymore, so returning an error isn't possible (there's nowhere for it to return to). So you have the possibility of silently-swallowed errors. This should make you nervous.
Also, you have the problem of not informing ASP.NET that you have ongoing background work. By returning early, you're telling ASP.NET to send the response and that everything is fine, even though in reality, the work isn't done and you have no idea when it will be done or even whether it will succeed. The point here is that nothing upstream of your code (including ASP.NET, IIS/Kestrel, proxies, load balancers) has any idea that your code is still working - after all, your code did just tell all those things that it's done handling that request. Will ASP.NET respond to a shutdown request? Sure! Can IIS do its periodic app pool recycle? Sure! Can your proxy take that node out of rotation when doing a rolling upgrade? Sure! Will your load balancer send it more work since it's not doing anything? Sure! As far as any of those systems know, your app isn't actually handling that request, and that can cause problems, like your "fire and forget" work suddenly disappearing - again, with no exceptions or logs or anything. This should make you nervous.
I'd say the best approach is to fix downstream calls, if possible. Also look into asynchronous concurrency, e.g., starting several calls and then await Task.WhenAll. If these approaches aren't sufficient, then I'd recommend a proper distributed architecture: have the API write to a persistent queue, and have the background work done by a separate application that processes that queue.

Is there any drawback of using ThreadPool.QueueUserWorkItem in web app.

I did some research on this topic, but I am unable to find the expected answer for this. In my application I have used
ThreadPool.QueueUserWorkItem
Like following way.
ThreadPool.QueueUserWorkItem(o => CaseBll.SendEmailNotificationForCaseUpdate(currentCase, caseUpdate));
My app in asp.net mvc & I have handled all background task which is not required to execute on user operation for faster execution & quick user response.
Now I wants to know that, Is there any bad side of using ThreadPool.QueueUserWorkItem When we have larger audience for application.
No, you should never use it. I can write a lot of reasons why but instead you should read this article from Scott Hansleman who is a genius IMHO
http://www.hanselman.com/blog/ChecklistWhatNOTToDoInASPNET.aspx
Under "Reliability and Performance":
Fire-and-Forget Work - Avoid using ThreadPool.QueueUserWorkItem as your app pool could disappear at any time. Move this work outside or use WebBackgrounder if you must.
So, as recommended, don't use ThreadPool.QueueUserWorkItem. An excellent alternative for this is at:
https://www.asp.net/aspnet/overview/web-development-best-practices/what-not-to-do-in-aspnet-and-what-to-do-instead#fire
Edit: As mentioned by #Scott-Chamberlain, here's a better link:
http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
It really depends on what you are going to be doing but generally speaking, your likely concerns will be:
Persistence. Threads in the managed pool are background threads. They will die when the application recycles which is generally undesirable. In your case you want to send e-mails. Imagine if your process dies for some reason before the thread executes. Your e-mail will never be sent.
Local storage is shared, which means you need to make sure there are no leftovers from the last thread if using it. Applies to fields marked with ThreadStaticAttribute as well.
I would instead recommend that you implement a job scheme where you schedule the job somewhere and have some other component actually read from this list (e.g. database) and perform the job, then mark it as complete. That way it persists across application unload, there is no memory reuse and you can throttle the performance. You could implement the processing component inside your application or even as a Windows service if you prefer.

in C# how to run method async in the same thread

Is it possible to define and call method asynchronously in the same thread as the caller?
Suppose I have just one core and I don't want threading management overhead with like 100 threads.
Edit
The reason I ask is nodejs model of doing things - everything on one thread never blocking anything, which proved to be very efficient, which made me wonder if same stuff possible in C# (and I couldn't achieve it myself).
Edit2 Well, as noted in comments node isn't single-threaded after all (however simple load test shows, that it uses just one core...), but I think what makes it so efficient is implicit requirement to write only non-blocking code. Which is possible in C#, except not required:) Anyway, thanks everyone...
More info in
this SO post and even more in this one
It's not really clear exactly what context you're talking about, but the async/await feature of C# 5 already helps to support this sort of thing. The difference is that whereas in node.js everything is forced to be single threaded by default (as I understand it; quite possibly incorrectly given the links in the comments), server-side applications in .NET using asynchrony will use very few threads without limiting themselves to that. If everything really can be served by a single thread, it may well be - if you never have more than one thing to do in terms of physical processing, then that's fine.
But what if one request comes in while another is doing a bit of work? Maybe it's doing just a small amount of encryption, or something like that. Do you really want to make the second request wait for the first one to complete? If you do, you could model that in .NET fairly easily with a TaskScheduler associated with a single-thread thread-pool... but more commonly, you'd use the thread-pool built into .NET, which will work efficiently while still allowing concurrency.
First off, you should make sure you're using .NET 4.5 - it has far more asynchronous APIs (e.g. for database and file access) than earlier versions of .NET. You want to use APIs which conform to the Task-based Asynchronous Pattern (TAP). Then, using async/await you can write your server-side code so that it reads a bit like synchronous code, but actually executes asynchronous. So for example, you might have:
Guid userId = await FetchUserIdAsync();
IEnumerable<Message> messages = await FetchMessagesAsync(userId);
Even though you need to "wait" while each of these operations talks place, you do so without blocking a thread. The C# compiler takes care of building a state machine for you. There's no need to explicitly write callbacks which frequently turn into spaghetti code - the compiler does it all.
You need to make sure that whatever web/web-service framework you use supports asynchrony, and it should just manage the rest, using as few threads as it can get away with.
Follow the two links above to find out more about the asynchrony support in C# 5 - it's a huge topic, and I'm sure you'll have more questions afterwards, but when you've read a bit more you should be able to ask very specific questions instead of the current broad one.

How can I send the HTTP response back to the user but still do more things on the server after that?

Sometimes there is a lot that needs to be done when a given Action is called. Many times, there is more that needs to be done than what needs to be done to generate the next HTML for the user. In order to make the user have a faster experience, I want to only do what I need to do to get them their next view and send it off, but still do more things afterwards. How can I do this, multi-threading? Would I then need to worry about making sure different threads don't step on each others feet? Is there any built in functionality for this type of thing in ASP.NET MVC?
As others have mentioned, you can use a spawned thread to do this. I would take care to consider the 'criticality' of several edge cases:
If your background task encounters an error, and fails to do what the user expected to be done, do you have a mechanism of report this failure to the user?
Depending on how 'business critical' the various tasks are, using a robust/resilient message queue to store 'background tasks to be processed' will help protected against a scenario where the user requests some action, and the server responsible crashes, or is taken offline, or IIS service is restarted, etc. and the background thread never completes.
Just food for though on other issues you might need to address.
How can I do this, multi-threading?
Yes!
Would I then need to worry about making sure different threads don't step on each others feet?
This is something you need to take care of anyway, since two different ASP.NET request could arrive at the same time (from different clients) and be handled in two different worker threads simultaneously. So, any code accessing shared data needs to be coded in a thread-safe way anyway, even without your new feature.
Is there any built in functionality for this type of thing in ASP.NET MVC?
The standard .net multi-threading techniques should work just fine here (manually starting threads, or using the Task features, or using the Async CTP, ...).
It depends on what you want to do, and how reliable you need it to be. If the operaitons pending after the response was sent are OK to be lost, then .Net Async calls, ThreadPool or new Thread are all going to work just fine. If the process crashes the pending work is lost, but you already accepted that this can happen.
If the work requires any reliable guarantee, for instance the work incurs updates in the site database, then you cannot use the .Net process threading, you need to persist the request to do the work and then process this work even after a process restart (app-pool recycle as IIS so friendly calls them).
One way to do this is to use MSMQ. Other way is to use the a database table as a queue. The most reliable way is to use the database activation mechanisms, as described in Asynchronous procedure execution.
You can start a background task, then return from the action. This example is using the task Parallel Library, found in .NET 4.0:
public ActionResult DoSomething()
{
Task t = new Task(()=>DoSomethingAsynchronously());
t.Start();
return View();
}
I would use MSMQ for this kind of work. Rather than spawning threads in an ASP.NET application, I'd use an Asynchronous out of process way to do this. It's very simple and very clean.
In fact I've been using MSMQ in ASP.NET applications for a very long time and have never had any issues with this approach. Further, having a different process (that is an executable in a different app domain) do the long running work is an ideal way to handle it since your web application is no being used to do this work. So IIS, the threadpool and your web application can continue to do what they need to, while other processes handle long running tasks.
Maybe you should give it a try: Using an Asynchronous Controller in ASP.NET MVC

Looking at what happens when a c#/ASP.NET thread is terminated and how to get around problems

I'm working on a ASP.NET website that on some requests will run a very lengthy caching process. I'm wondering what happens exactly if the execution timeout is reached while it is still running in terms of how the code handles it.
Particularly I am wondering about things like if the code is in the try of a try/finally block will the finally still be run?
Also given I am not sure I want the caching to terminate even if it goes on that long is there a way with spawning new threads, etc. that I can circumvent this execution timeout? I am thinking it would be much nicer to return to the user immediately and say "a cache build is happening" rather than just letting them time out. I have recently started playing with some locking code to make sure only one cache build happens at a time but am thinking about extending this to make it run out of sync.
I've not really played with creating threads and such like myself so am not sure exactly how they work, particularly in terms of interacting with ASP.NET. eg if the parent thread that launched it is terminated will that have any effect on the spawned thread?
I know there is kind of a lot of different questions in here and I can split them if that is deemed best but they all seem to go together... I'll try to summarise the questions though:
Will a finally block still be executed if a thread is terminated by ASP.NET while in the try block
Would newly created threads be subject to the same timeouts as the original thread?
Would newly created threads die at the same time as the parent thread that created them?
And the general one of what is the best way to do long running background processes on an ASP.NET site?
Sorry for some noobish questions, I've never really played with threads and they still intimidate me a bit (my brain says they are hard). I could probably test the answer to a lot of tehse questions but I wouldn't be confident enough of my tests. :)
Edit to add:
In response to Capital G:
The problem I have is that the ASp.NET execution timeout is currently set to one hour which is not always long enough for some of these processes I reckon. I've put some stuff in with locks to prevent more than one person setting off these long processes and I was worried the locks might not be released (which if finally blocks aren't always run might happen I guess).
Your comments on not running long processes in ASP.NET is why I was thinking of moving them to other threads rather than blocking the request thread but I don't know if that still counts as running within the ASP.NET architecture that you said was bad.
The code is not actually mine so I'm not allowed (and not sure I 100% understand it enough) to rework it into a service though that is certainly where it would best live.
Would using a BackgroundWorker process for something that could take an hour be feasible in this situation (with respect to comments on long running processes in ASP.NET). I would then make request return a "Cache is building" page until its finished and then go back to serving normally... Its all a bit of a nightmare but its my job so I've got to find a way to improve it. :)
Interesting question, just tested and no it's not guaranteed to execute the code in the finally block, if a thread is aborted it could stop at any point in the processing. You can design some sanity checking and other mechanisms to handle special cleanup routines and such but it has a lot to do with your thread handling as well.
Not necessarily, it depends on how your implementing your threads. If you are working with threads yourself, then you can easily get into situations where the parent thread is killed while it's child threads are still out there processing, you generally want to do some cleanup in the parent thread that ends the child threads as well. Some objects might do a lot of this for you as well, so it's a tough call to say one way or the other. Never assume this at the very least.
No, not necessarily, don't assume this at least, again has to do with your design and whether your doing threading yourself or using some higher level threading object/pattern. I would never assume this regardless.
I don't recommend long running processes within the ASP.NET architecture, unless its within the typical timeout, if it's 10-20s okay but if it's minutes, no, the reason is resource usage within ASP.NET and it's awfully bad on a user. That being said you could perform asynchronous operations where you hand off the work to the server, then you return back to the user when the processing is finished, (this is great for those 10-20s+ processes), the user can be given a little animation or otherwise not have their browser all stuck for that long waiting for whatever is happening on the server to happen.
If it is a long running process, things that take greater than 30-60s+, unless it absolutely has to be done in ASP.NET due to the nature of the process, I suggest moving it to a windows service and schedule it in some way to occur when required.
Note: Threading CAN be complicated, it's not that it's hard so much as that you have to be very aware of what your doing, which requires a firm understanding of what threads are and how they work, I'm no expert, but I'm also not completely new and I'll tell you that in most situations you don't need to get into the realm of threading, even when it seems like you do, if you must however, I would suggest looking into the BackgroundWorker object as they are simplified for the purposes of doing batched processing etc. (honestly for many situations that DO need threads, this is usually a very simple solution).
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Long or time consuming processes to be started behind the web-page; it should not hit the ASP.NET execution time out; the user page should be freed; running the requests under lock etc. All these situation points towards using async services. In one of the products, where I architected, used services for such scenarios. The service exposes some async method to initiate. The status of the progress can be queried using another method. Every request is given some id and no duplicate requests are fired ever. The progress proceeds even if the user logs out. The user can see the results at a later time.
If you have looked at such options already, let me know if there is any issue. Or if you are yet to look in this direction, please get it this way. For any help, just send in your comments.

Categories

Resources