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

Support performance #633

Merged
merged 55 commits into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
f31adac
wip
Tyrrrz Nov 30, 2020
79d2397
wip
Tyrrrz Nov 30, 2020
d7c9974
wip
Tyrrrz Dec 1, 2020
51783e8
wip
Tyrrrz Dec 1, 2020
c99635d
wip
Tyrrrz Dec 1, 2020
7ad5ab5
wip
Tyrrrz Dec 2, 2020
96c443e
wip
Tyrrrz Dec 2, 2020
98e567d
wip
Tyrrrz Dec 2, 2020
e0eb730
wip
Tyrrrz Dec 2, 2020
748670c
wip
Tyrrrz Dec 2, 2020
dfdec31
wip
Tyrrrz Dec 2, 2020
fa64053
wip
Tyrrrz Dec 2, 2020
8338381
wip
Tyrrrz Dec 3, 2020
8fc5c2b
wip
Tyrrrz Dec 4, 2020
6a05871
wip
Tyrrrz Dec 4, 2020
6c0b928
wip
Tyrrrz Dec 4, 2020
5a47bd9
wip
Tyrrrz Dec 4, 2020
e67597e
wip
Tyrrrz Dec 7, 2020
52ec0a5
wip
Tyrrrz Dec 7, 2020
15d7001
wip
Tyrrrz Dec 7, 2020
3a705f0
wip
Tyrrrz Dec 8, 2020
c4f9371
wip
Tyrrrz Dec 8, 2020
00ef2b5
wip
Tyrrrz Dec 8, 2020
b0487cf
wip
Tyrrrz Dec 8, 2020
0a713f3
wip
Tyrrrz Dec 8, 2020
c314a66
wip
Tyrrrz Dec 8, 2020
9e2b7e1
Merge remote-tracking branch 'origin/main' into performance
Tyrrrz Dec 8, 2020
d0c5358
wip
Tyrrrz Dec 8, 2020
a4e01d8
wip
Tyrrrz Dec 8, 2020
d960d7f
wip
Tyrrrz Dec 8, 2020
a0fb93e
wip
Tyrrrz Dec 9, 2020
6c1b413
wip
Tyrrrz Dec 9, 2020
258ed5c
wip
Tyrrrz Dec 9, 2020
f2e5a8b
wip
Tyrrrz Dec 10, 2020
41bcb99
wip
Tyrrrz Dec 10, 2020
da7ee94
wip
Tyrrrz Dec 10, 2020
1371006
wip
Tyrrrz Dec 10, 2020
bafe82a
wip
Tyrrrz Dec 10, 2020
7abdb4f
wip
Tyrrrz Dec 11, 2020
a1e48f8
wip
Tyrrrz Dec 11, 2020
fd13150
wip
Tyrrrz Dec 11, 2020
134d0ec
wip
Tyrrrz Dec 14, 2020
6b92788
wip
Tyrrrz Dec 14, 2020
b6f3ee2
wip
Tyrrrz Dec 14, 2020
0e91066
wip
Tyrrrz Dec 14, 2020
ea06cfb
wip
Tyrrrz Dec 14, 2020
2cb49ef
wip
Tyrrrz Dec 14, 2020
e908cee
wip
Tyrrrz Dec 14, 2020
e8aa3cc
wip
Tyrrrz Dec 14, 2020
71c87ca
wip
Tyrrrz Dec 14, 2020
0c512b1
wip
Tyrrrz Dec 14, 2020
fbd6f17
wip
Tyrrrz Dec 14, 2020
13b88db
wip
Tyrrrz Dec 14, 2020
eb37814
wip
Tyrrrz Dec 14, 2020
61085a4
wip
Tyrrrz Dec 15, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Add net5.0 TFM to libraries #606
* Add more logging to CachingTransport #619
* Bump Microsoft.Bcl.AsyncInterfaces to 5.0.0 #618
Copy link
Member

Choose a reason for hiding this comment

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

It's on the line below (it got some ` on another PR)

Suggested change
* Bump Microsoft.Bcl.AsyncInterfaces to 5.0.0 #618

* Add support for performance

## 3.0.0-alpha.5

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 0 additions & 2 deletions src/Sentry.AspNetCore/ScopeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ public static void Populate(this Scope scope, HttpContext context, SentryAspNetC
{
scope.SetTag("route.area", area);
}

scope.Transaction = area == null ? $"{controller}.{action}" : $"{area}.{controller}.{action}";
}
}
catch(Exception e)
Expand Down
43 changes: 43 additions & 0 deletions src/Sentry.AspNetCore/SentryMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
using System.Diagnostics;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
using System.Transactions;
Tyrrrz marked this conversation as resolved.
Show resolved Hide resolved
using Microsoft.AspNetCore.Diagnostics;
#if NETSTANDARD2_0
using IHostingEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment;
#else
using IHostingEnvironment = Microsoft.AspNetCore.Hosting.IWebHostEnvironment;
#endif
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Sentry.Extensibility;
Expand Down Expand Up @@ -85,6 +87,7 @@ public async Task InvokeAsync(HttpContext context)
{
context.Request.EnableBuffering();
}

if (_options.FlushOnCompletedRequest)
{
context.Response.OnCompleted(async () =>
Expand All @@ -94,6 +97,19 @@ public async Task InvokeAsync(HttpContext context)
});
}

var routeData = context.GetRouteData();
var controller = routeData.Values["controller"]?.ToString();
var action = routeData.Values["action"]?.ToString();
var area = routeData.Values["area"]?.ToString();

// TODO: What if it's not using controllers (i.e. endpoints)?

var transactionName = area == null
Tyrrrz marked this conversation as resolved.
Show resolved Hide resolved
? $"{controller}.{action}"
: $"{area}.{controller}.{action}";

var transaction = hub.CreateTransaction(transactionName, "http.server");

hub.ConfigureScope(scope =>
{
// At the point lots of stuff from the request are not yet filled
Expand All @@ -105,8 +121,10 @@ public async Task InvokeAsync(HttpContext context)

scope.OnEvaluating += (_, __) => PopulateScope(context, scope);
});

try
{
transaction.StartTimestamp = DateTimeOffset.Now;
await _next(context).ConfigureAwait(false);

// When an exception was handled by other component (i.e: UseExceptionHandler feature).
Expand All @@ -122,6 +140,12 @@ public async Task InvokeAsync(HttpContext context)

ExceptionDispatchInfo.Capture(e).Throw();
}
finally
{
transaction.Finish(
GetSpanStatusFromCode(context.Response.StatusCode)
);
}

void CaptureException(Exception e)
{
Expand Down Expand Up @@ -161,5 +185,24 @@ internal void PopulateScope(HttpContext context, Scope scope)
scope.Populate(Activity.Current);
}
}

private static SpanStatus GetSpanStatusFromCode(int statusCode) => statusCode switch
{
< 400 => SpanStatus.Ok,
400 => SpanStatus.InvalidArgument,
401 => SpanStatus.Unauthenticated,
403 => SpanStatus.PermissionDenied,
404 => SpanStatus.NotFound,
409 => SpanStatus.AlreadyExists,
429 => SpanStatus.ResourceExhausted,
499 => SpanStatus.Cancelled,
< 500 => SpanStatus.InvalidArgument,
500 => SpanStatus.InternalError,
501 => SpanStatus.Unimplemented,
503 => SpanStatus.Unavailable,
504 => SpanStatus.DeadlineExceeded,
< 600 => SpanStatus.InternalError,
_ => SpanStatus.UnknownError
};
}
}
11 changes: 5 additions & 6 deletions src/Sentry.AspNetCore/SentryStartupFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ namespace Sentry.AspNetCore
/// <inheritdoc />
internal class SentryStartupFilter : IStartupFilter
{
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
=> e =>
{
_ = e.UseSentry();
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) => e =>
{
e.UseSentry();

next(e);
};
next(e);
};
}
}
15 changes: 15 additions & 0 deletions src/Sentry/Extensibility/DisabledHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ public void WithScope(Action<Scope> scopeCallback)
{
}

/// <summary>
/// Returns a dummy transaction.
/// </summary>
public Transaction CreateTransaction(string name, string operation) =>
new Transaction(this, name, operation);

/// <summary>
/// Returns null.
/// </summary>
public SentryTraceHeader? GetTraceHeader() => null;

/// <summary>
/// No-Op.
/// </summary>
Expand All @@ -64,6 +75,10 @@ public void BindClient(ISentryClient client)
/// </summary>
public SentryId CaptureEvent(SentryEvent evt, Scope? scope = null) => SentryId.Empty;

public void CaptureTransaction(Transaction transaction)
{
}

/// <summary>
/// No-Op.
/// </summary>
Expand Down
16 changes: 16 additions & 0 deletions src/Sentry/Extensibility/HubAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ public IDisposable PushScope<TState>(TState state)
public void WithScope(Action<Scope> scopeCallback)
=> SentrySdk.WithScope(scopeCallback);

[DebuggerStepThrough]
public Transaction CreateTransaction(string name, string operation)
=> SentrySdk.CreateTransaction(name, operation);

[DebuggerStepThrough]
public SentryTraceHeader? GetTraceHeader()
=> SentrySdk.GetTraceHeader();

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
Expand Down Expand Up @@ -132,6 +140,14 @@ public SentryId CaptureException(Exception exception)
public SentryId CaptureEvent(SentryEvent evt, Scope? scope)
=> SentrySdk.CaptureEvent(evt, scope);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
[DebuggerStepThrough]
[EditorBrowsable(EditorBrowsableState.Never)]
public void CaptureTransaction(Transaction transaction)
=> SentrySdk.CaptureTransaction(transaction);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Sentry/IHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@ public interface IHub :
/// Last event id recorded in the current scope.
/// </summary>
SentryId LastEventId { get; }

Transaction CreateTransaction(string name, string operation);

SentryTraceHeader? GetTraceHeader();
}
}
6 changes: 6 additions & 0 deletions src/Sentry/ISentryClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public interface ISentryClient
/// <param name="userFeedback">The user feedback to send to Sentry.</param>
void CaptureUserFeedback(UserFeedback userFeedback);

/// <summary>
/// Captures a transaction.
/// </summary>
/// <param name="transaction">The transaction.</param>
void CaptureTransaction(Transaction transaction);

/// <summary>
/// Flushes events queued up.
/// </summary>
Expand Down
7 changes: 7 additions & 0 deletions src/Sentry/ISentryTraceSampler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Sentry
{
public interface ISentryTraceSampler
{
double GetSampleRate(TraceSamplingContext context);
}
}
9 changes: 9 additions & 0 deletions src/Sentry/Internal/Extensions/JsonExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ public static void WriteDictionaryValue(
}
}

public static void WriteDictionary(
this Utf8JsonWriter writer,
string propertyName,
IEnumerable<KeyValuePair<string, object?>>? dic)
{
writer.WritePropertyName(propertyName);
writer.WriteDictionaryValue(dic);
}

public static void WriteDictionary(
this Utf8JsonWriter writer,
string propertyName,
Expand Down
27 changes: 27 additions & 0 deletions src/Sentry/Internal/Hub.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Sentry.Extensibility;
Expand Down Expand Up @@ -100,6 +101,20 @@ public void WithScope(Action<Scope> scopeCallback)

public void BindClient(ISentryClient client) => ScopeManager.BindClient(client);

public Transaction CreateTransaction(string name, string operation)
{
var trans = new Transaction(this, name, operation);
ConfigureScope(scope => scope.Transaction = trans);
Copy link
Member

Choose a reason for hiding this comment

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

I believe by default we won't do this. The snippets I saw from JS require the caller to decide whether the transaction should be bound to the scope or not.

For now this looks good and lets try like this.


return trans;
}

public SentryTraceHeader? GetTraceHeader()
Tyrrrz marked this conversation as resolved.
Show resolved Hide resolved
{
var (currentScope, _) = ScopeManager.GetCurrent();
return currentScope.Transaction?.GetTraceHeader();
}

public SentryId CaptureEvent(SentryEvent evt, Scope? scope = null)
{
try
Expand Down Expand Up @@ -129,6 +144,18 @@ public void CaptureUserFeedback(UserFeedback userFeedback)
}
}

public void CaptureTransaction(Transaction transaction)
{
try
{
_ownedClient.CaptureTransaction(transaction);
}
catch (Exception e)
{
_options.DiagnosticLogger?.LogError("Failure to capture transaction: {0}", e, transaction.SpanId);
}
}

public async Task FlushAsync(TimeSpan timeout)
{
try
Expand Down
13 changes: 11 additions & 2 deletions src/Sentry/Internal/Polyfills.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
// Polyfills to bridge the missing APIs in older versions of the framework/standard.
// In some cases, these just proxy calls to existing methods but also provide a signature that matches .netstd2.1

using System.Linq;

#if NET461 || NETSTANDARD2_0
namespace System
{
internal static class Extensions
{
public static string[] Split(this string str, char c, StringSplitOptions options = StringSplitOptions.None) =>
str.Split(new[] {c}, options);
}
}

namespace System.IO
{
using Threading;
Expand All @@ -26,6 +33,8 @@ public static Task WriteAsync(this Stream stream, byte[] buffer, CancellationTok

namespace System.Collections.Generic
{
using Linq;

internal static class Extensions
{
public static void Deconstruct<TKey, TValue>(
Expand Down
18 changes: 18 additions & 0 deletions src/Sentry/Protocol/Envelopes/Envelope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,24 @@ public static Envelope FromUserFeedback(UserFeedback sentryUserFeedback)
return new Envelope(header, items);
}

/// <summary>
/// Creates an envelope that contains a single transaction.
/// </summary>
public static Envelope FromTransaction(Transaction transaction)
{
var header = new Dictionary<string, object?>
{
[EventIdKey] = transaction.SpanId.ToString()
};

var items = new[]
{
EnvelopeItem.FromTransaction(transaction)
};

return new Envelope(header, items);
}

private static async Task<IReadOnlyDictionary<string, object?>> DeserializeHeaderAsync(
Stream stream,
CancellationToken cancellationToken = default)
Expand Down
Loading