Skip to content
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

MVC use concrete types for DiagnosticListener #11730

Merged
merged 11 commits into from
Jul 15, 2019
Merged

Conversation

benaadams
Copy link
Member

@benaadams benaadams commented Jul 1, 2019

Pattern:

Under Diagnostics namespace

Event Type is same name as Event Name

Type has a EventName string const so what to listen to is exposed without having to check the source (and is a const so can be used in switch and Attributes).

Type has its data exposed as readonly properties.

Type implements IReadOnlyList<KeyValuePair<string, object>> so the data can be iterated over.

Type implements IEnumerable<KeyValuePair<string, object>> so the data can be enumerated over,

Interfaces are explicit so they don't interfere with reflection/serialization (i.e. Count being seen as a data item)

Each event has its own type so pattern matching can be used to differentiate events.

e.g.

namespace Microsoft.AspNetCore.Mvc.Diagnostics
{
    public sealed partial class AfterAction : IEnumerable<KeyValuePair<string, object>>, IReadOnlyList<KeyValuePair<string, object>>
    {
        public const string EventName = "Microsoft.AspNetCore.Mvc.AfterAction";
        
        public AfterAction(ActionDescriptor actionDescriptor, HttpContext httpContext, RouteData routeData);
        
        public ActionDescriptor ActionDescriptor { get; }
        public HttpContext HttpContext { get; }
        public RouteData RouteData { get ; }

        int IReadOnlyCollection<KeyValuePair<string, object>>.Count { get; }
        KeyValuePair<string, object> IReadOnlyList<KeyValuePair<string, object>>.this[int index];

        IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator(););
    }
}

/cc @rynowak @davidfowl @NickCraver

@benaadams benaadams force-pushed the diag branch 3 times, most recently from 57df950 to 29dde5b Compare July 1, 2019 04:28
@Eilon Eilon added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Jul 1, 2019
@benaadams
Copy link
Member Author

Are still anonymous diagnostics in other places like Hosting, but will see how this goes down first before seeing about those.

@NickCraver
Copy link
Member

This would be a huge improvement - constants as event names make both the adapter case and general usage (e.g. a case in an IObserver) much better. The strong typing is very welcomed for anyone taking the reference and makes the whole thing sane (over loads of reflection today).

If anyone's curious about context: https://github.com/dotnet/corefx/issues/18114 is the original issue pushing for this, but closed since the teams weren't going to make any more breaking changes. With 3.0, it seems like hopefully that's back on the table.

NickCraver pushed a commit to MiniProfiler/dotnet that referenced this pull request Jul 6, 2019
Note that 3.x doesn't include view profiling for the moment. See dotnet/aspnetcore#11730 for progress on the 3.0 approach.
NickCraver added a commit to MiniProfiler/dotnet that referenced this pull request Jul 7, 2019
This set of changes drops view profiling for the moment in ASP.NET Core 3.x since the types we were wrapping as "pubternal" are no longer exposed in 3.0. On the framework side, dotnet/aspnetcore#11730 is in progress so we can use the diagnostics API to hopefully re-enable this for the 3.0 release.

Samples for ASP.NET Core 2.2 and 3.0 are broken into separate samples for clarity though they are mostly the same.

Overall changes:
- (For Linux): Fix Azure DevOps builds (note they're not successfully running all tests yet - some providers are skipped, but they're working!)
- (For Linux): Change SQL Formatters to always use `\n`
- (For Linux): Add `WindowsOnly` to `[Fact]` and `[Theory]` for skipping inapplicable tests on Linux
- (For Linux): Add `xunit.runner.json` to make things work on Linux/Mono (only copied to output and in effect there)
- (For Linux): Null ref fix for SQL CE errors (happens on Linux)
- (For .NET Core 3.0): Add a `netcoreapp3.0` build for `MiniProfiler.AspNet*` libs
- (For .NET Core 3.0): Exclude view profiling for now (this is what was breaking, ultimately)
- (For .NET Core 3.0): Split ASP.NET Core v2 and v3 samples into different projects, since some fundamentals have changed
- (For all): Bump version to `4.1.0-preview.*` to reflect the preview dependencies for `netcoreapp3.0` builds
- (For all): Dropped `netcoreapp1.1` from testing (note: `netstandard1.5` is still built, it's just not tested)
@rynowak
Copy link
Member

rynowak commented Jul 11, 2019

@benaadams - this is dope, I like the design of this.

@rynowak
Copy link
Member

rynowak commented Jul 11, 2019

@ajcvickers - is it work comparing the design of this with https://github.com/aspnet/EntityFrameworkCore/tree/9026770af72683ba3cf6c2a8125fa7a8d602703f/src/EFCore/Diagnostics ?

I notice that you're using the same payloads for logging and diagnostics source.

}
public sealed partial class AfterOnActionExecuted : Microsoft.AspNetCore.Mvc.Diagnostics.MvcDiagnostic
{
public const string EventName = "Microsoft.AspNetCore.Mvc.AfterOnActionExecuted";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops. This is a really unfortunate event name. I think we should call this type something like ActionFilterOnActionExecuted on so on for the other filter-related events.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that everything that has IFilterMetadata property?

e.g. AfterOnException => AfterFilterOnException

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call it ExceptionFilterAfterOnException. So the scheme is <filter kind> [Before|After] Method

@NickCraver
Copy link
Member

I'm just curious around what constitutes a breaking change on these APIs w.r.t. event names.

Since the property names on the object are going from camelCase to proper C# Pascal case for properties, isn't it already breaking? Or is the latest binder reflection case-insensitive and that keeps working? I'm just confused on the event names being breaking when the property casing isn't...if we're firing the old events but they just don't work, maybe it would be better to change and break the event names? Just tossing that thought out there.

@rynowak
Copy link
Member

rynowak commented Jul 14, 2019

Since the property names on the object are going from camelCase to proper C# Pascal case for properties, isn't it already breaking? Or is the latest binder reflection case-insensitive and that keeps working?

It depends on the consumer. The consumer that I'm aware of is app-insights which I think is still using the Microsoft.Extensions.DiagnosticSourceAdapter package - which is case-insensitive.

Technically speaking, top level entries are defined as case-insensitive, but what really matters to me is whether we break people that have real usage.

If this is a breaking change that impacts existing usage of diagnostic source, then I would lean towards using lowercase properties. This is too late in the development cycle to be cavalier about breaking changes.

@lmolkova - any insights here?

@NickCraver
Copy link
Member

Given the very few people using these (as far as I'm aware) outside diagnostic adapter, IMO we should change them now while making changes and have them reflect the casing that should be on a public type API. Even if it's breaking, as long as DiagnosticAdapter is case-insensitive.

@benaadams
Copy link
Member Author

Aside: Just to make note on my understanding of the status of this PR. I've made the requested changes and @rynowak is picking up class naming changes.

Also outstanding issue on Instrumentation apis #11730 (comment) to be picked up separately?

@rynowak
Copy link
Member

rynowak commented Jul 15, 2019

@benaadams
Copy link
Member Author

There's still a breaking change here:

Surely not with the magic of DI and all that 😉

Reverted

@lmolkova
Copy link

lmolkova commented Jul 15, 2019

I'll look more into this PR later today.

Regarding this:

Microsoft.Extensions.DiagnosticSourceAdapter package - which is case-insensitive.

AppInsights is NOT using DiagnosticAdapter anymore and event handling is case-sensitive. We still have several work items to support ASP.NET Core 3.0 and can fit case-insensitive work if needed.

Also

very few people using these (as far as I'm aware) outside diagnostic adapter

After we introduced Activities, it became hard and inefficient to use DiagnosticAdapter because of aspnet/EventNotification#67 (check out this dotnet/extensions#1895 as an example I just found)

We also removed adapter because of perf - DiagnosticsSource.IsEnabled became twice as fast. And the ability to filter out events in IsEnabled (which brought more improvements) is not supported by the adapter.

So, I'd argue DiagnosticAdapter is the default way is not a good assumption.

@rynowak
Copy link
Member

rynowak commented Jul 15, 2019

I'll look more into this PR later today.

Regarding this:

Microsoft.Extensions.DiagnosticSourceAdapter package - which is case-insensitive.

AppInsights is NOT using DiagnosticAdapter anymore and event handling is case-sensitive. We still have several work items to support ASP.NET Core 3.0 and can fit case-insensitive work if needed.

Ok great. Is there somewhere you want me to file this?

After we introduced Activities, it became hard and inefficient to use DiagnosticAdapter because of aspnet/EventNotification#67 (check out this aspnet/Extensions#1895 as an example I just found)

We also removed adapter because of perf - DiagnosticsSource.IsEnabled became twice as fast. And the ability to filter out events in IsEnabled (which brought more improvements) is not supported by the adapter.

So, I'd argue DiagnosticAdapter is the default way is not a good assumption.

Also great from my POV. I'd like to use deprecate the adapter and stop shipping it in a future release. It hasn't really proved to be essential for diagnostic source.

@rynowak rynowak merged commit 09722d1 into dotnet:master Jul 15, 2019
@benaadams benaadams deleted the diag branch July 15, 2019 20:24
NickCraver pushed a commit to MiniProfiler/dotnet that referenced this pull request Apr 19, 2020
This adds timings based on the DiagnosticListener bits overhauled in dotnet/aspnetcore#11730 with some further cleanup in dotnet/aspnetcore@b23ea5b

This would also resolve #162 and #322.
NickCraver added a commit to MiniProfiler/dotnet that referenced this pull request Apr 22, 2020
This adds timings based on the `DiagnosticListener` bits overhauled in dotnet/aspnetcore#11730 with some further cleanup in dotnet/aspnetcore@b23ea5b

This would also resolve #162 and #322.

Entirely possible there are more efficient ways to do the correlation tracking (I hope!) - putting this up for more eyes.

Example profiling:
![image](https://user-images.githubusercontent.com/454813/79678735-784f5d00-81cc-11ea-93fc-11516b77ea59.png)
ylinax pushed a commit to ylinax/dot-net that referenced this pull request Jun 30, 2022
This set of changes drops view profiling for the moment in ASP.NET Core 3.x since the types we were wrapping as "pubternal" are no longer exposed in 3.0. On the framework side, dotnet/aspnetcore#11730 is in progress so we can use the diagnostics API to hopefully re-enable this for the 3.0 release.

Samples for ASP.NET Core 2.2 and 3.0 are broken into separate samples for clarity though they are mostly the same.

Overall changes:
- (For Linux): Fix Azure DevOps builds (note they're not successfully running all tests yet - some providers are skipped, but they're working!)
- (For Linux): Change SQL Formatters to always use `\n`
- (For Linux): Add `WindowsOnly` to `[Fact]` and `[Theory]` for skipping inapplicable tests on Linux
- (For Linux): Add `xunit.runner.json` to make things work on Linux/Mono (only copied to output and in effect there)
- (For Linux): Null ref fix for SQL CE errors (happens on Linux)
- (For .NET Core 3.0): Add a `netcoreapp3.0` build for `MiniProfiler.AspNet*` libs
- (For .NET Core 3.0): Exclude view profiling for now (this is what was breaking, ultimately)
- (For .NET Core 3.0): Split ASP.NET Core v2 and v3 samples into different projects, since some fundamentals have changed
- (For all): Bump version to `4.1.0-preview.*` to reflect the preview dependencies for `netcoreapp3.0` builds
- (For all): Dropped `netcoreapp1.1` from testing (note: `netstandard1.5` is still built, it's just not tested)
ylinax added a commit to ylinax/dot-net that referenced this pull request Jun 30, 2022
This adds timings based on the `DiagnosticListener` bits overhauled in dotnet/aspnetcore#11730 with some further cleanup in dotnet/aspnetcore@b23ea5b

This would also resolve #162 and #322.

Entirely possible there are more efficient ways to do the correlation tracking (I hope!) - putting this up for more eyes.

Example profiling:
![image](https://user-images.githubusercontent.com/454813/79678735-784f5d00-81cc-11ea-93fc-11516b77ea59.png)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants