getsentry / sentry-dart

Sentry SDK for Dart and Flutter
https://sentry.io/for/flutter/
MIT License
742 stars 227 forks source link

Events for blocking calls #1671

Open ueman opened 10 months ago

ueman commented 10 months ago

Problem Statement

Similar to https://twitter.com/brungarc/status/1711484812702171309 it should be possible in Dart to detect blocking file IO calls.

There's also a lint rule (https://dart.dev/tools/linter-rules/avoid_slow_async_io) to enforce sync io but that can't be detected for 3rd party code. Depending on the lint rule, it could make sense to send events based on sync or async file io. In mobile apps, async io is probably the better choice, while on CLIs or backend code sync io could be better.

Solution Brainstorm

Whenever a sync file API is called, an event should be sent to Sentry. This can be done with the existing file plugin by adding extra events when the sync APIs are called.

Are you willing to submit a PR?

None

bruno-garcia commented 10 months ago

Relates to: https://github.com/getsentry/sentry-dotnet/pull/2709

stefanosiano commented 10 months ago

This could be a performance issue generated by the backend, without the need to send an event when one of those APIs is called. We already have file.async in the span, so we could leverage that. Also, this is probably relevant to Flutter projects only

buenaflor commented 9 months ago

How could a backend know if a File I/O call in a flutter app has been made? or am I understanding it wrong

kahest commented 9 months ago

@buenaflor the idea is that we create a perf issue for sync file I/O, but only for Flutter apps. Since we already have the file.async flag in the file spans we send, the detector living in the backend needs to check if it's a Flutter app and can then create a perf issue.

buenaflor commented 9 months ago

Got it, sounds reasonable, I would also opt for that route since we already have the mechanism in place to make it happen - unless there are other concerns

bruno-garcia commented 9 months ago

In .NET the situation we want to track is when an async call is blocked on:

async Execute(delegate d)
{
     SomeAsyncMethod().Wait(); // blocks and can cause thread pool starvation

   // right call would be: 
   await SomeAsyncMethod();
}

So that's any async method (not just I/O) that happens on a async flow that's blocked on. Any .Result or .Wait() for example. A simple blocking file I/O wouldn't fire the detection, unless that was called within an async method (anywhere in the call chain).

In other words: On a program: void Main() { File.ReadAllLines()} -> Blocking I/O wouldn't fire anything because there's nothing async here being blocked on.

stefanosiano commented 9 months ago

Let's understand if it makes sense for Flutter, too. Let's investigate if the await keyword has the same meaning in Dart and .NET, and if Dart has a similar mechanism of .NET's Wait()

denrase commented 8 months ago

We can check if we run on the main or the background isolate, so we can add this info in the file plugin to spans wrapping sync/async calls.

https://github.com/getsentry/sentry-dart/issues/1727#issuecomment-1838656748

https://github.com/getsentry/sentry-dart/issues/1727#issuecomment-1840739291