-
-
Notifications
You must be signed in to change notification settings - Fork 222
feat(logs): initial API for Sentry Logs #4158
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
base: feat/logs
Are you sure you want to change the base?
Changes from all commits
0add668
db7d558
d96b092
2958a47
a63371b
d8d2567
fefd24c
165996a
32e7e25
fc88722
2ba87e4
0f1d4a4
8dec5d5
a664f7e
96693d0
83964cf
dadc69b
c91cdde
0740c3b
eee06bf
8c61d8b
80683ae
cb20118
2cb306f
dcc0ec1
58dce74
f2e1ba2
0220015
6822b23
dd39fae
6eb5b9b
69c05b8
430cf82
31a8f1f
2ae4476
69678ce
97995a8
fbe747d
64adf33
cdfa901
d2ac53b
4011ba6
4ae82d0
bc1c465
79fb190
b4e80f4
b21adef
0032858
a9769f8
9a51033
9a09832
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -33,6 +33,19 @@ | |||||||
|
||||||||
// This option tells Sentry to capture 100% of traces. You still need to start transactions and spans. | ||||||||
options.TracesSampleRate = 1.0; | ||||||||
|
||||||||
// This option enables the (experimental) Sentry Logs. | ||||||||
options.EnableLogs = true; | ||||||||
options.SetBeforeSendLog(static log => | ||||||||
{ | ||||||||
if (log.TryGetAttribute("suppress", out bool attribute) && attribute) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
{ | ||||||||
return null; | ||||||||
} | ||||||||
|
||||||||
// Drop logs with level Info | ||||||||
return log.Level is SentryLogLevel.Info ? null : log; | ||||||||
}); | ||||||||
}); | ||||||||
|
||||||||
// This starts a new transaction and attaches it to the scope. | ||||||||
|
@@ -56,6 +69,7 @@ async Task FirstFunction() | |||||||
var httpClient = new HttpClient(messageHandler, true); | ||||||||
var html = await httpClient.GetStringAsync("https://example.com/"); | ||||||||
WriteLine(html); | ||||||||
SentrySdk.Logger.LogInfo("HTTP Request completed."); | ||||||||
} | ||||||||
|
||||||||
async Task SecondFunction() | ||||||||
|
@@ -75,6 +89,8 @@ async Task SecondFunction() | |||||||
// This is an example of capturing a handled exception. | ||||||||
SentrySdk.CaptureException(exception); | ||||||||
span.Finish(exception); | ||||||||
|
||||||||
SentrySdk.Logger.LogError("Error with message: {0}", [exception.Message], static log => log.SetAttribute("method", nameof(SecondFunction))); | ||||||||
} | ||||||||
|
||||||||
span.Finish(); | ||||||||
|
@@ -88,6 +104,8 @@ async Task ThirdFunction() | |||||||
// Simulate doing some work | ||||||||
await Task.Delay(100); | ||||||||
|
||||||||
SentrySdk.Logger.LogFatal("Crash imminent!", [], static log => log.SetAttribute("suppress", true)); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Odd that we must pass an empty array as a second argument. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might be able to have an overload that doesn't take the second |
||||||||
|
||||||||
// This is an example of an unhandled exception. It will be captured automatically. | ||||||||
throw new InvalidOperationException("Something happened that crashed the app!"); | ||||||||
} | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,20 @@ public interface IHub : ISentryClient, ISentryScopeManager | |
/// </summary> | ||
public SentryId LastEventId { get; } | ||
|
||
/// <summary> | ||
/// Creates and sends logs to Sentry. | ||
/// <para>This API is experimental and it may change in the future.</para> | ||
/// </summary> | ||
/// <remarks> | ||
/// Available options: | ||
/// <list type="bullet"> | ||
/// <item><see cref="Sentry.SentryOptions.EnableLogs"/></item> | ||
/// <item><see cref="Sentry.SentryOptions.SetBeforeSendLog(System.Func{SentryLog, SentryLog})"/></item> | ||
/// </list> | ||
/// </remarks> | ||
[Experimental(Infrastructure.DiagnosticId.ExperimentalFeature)] | ||
public SentryStructuredLogger Logger { get; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just thinking about testing of the Hub classes in general, the Maybe worth creating an |
||
|
||
/// <summary> | ||
/// Starts a transaction. | ||
/// </summary> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
namespace Sentry.Protocol; | ||
|
||
[DebuggerDisplay(@"\{ Value = {Value}, Type = {Type} \}")] | ||
internal readonly struct SentryAttribute | ||
{ | ||
public SentryAttribute(object value, string type) | ||
{ | ||
Value = value; | ||
Type = type; | ||
} | ||
|
||
public object Value { get; } | ||
public string Type { get; } | ||
} | ||
|
||
internal static class SentryAttributeSerializer | ||
{ | ||
internal static void WriteAttribute(Utf8JsonWriter writer, string propertyName, SentryAttribute attribute) | ||
{ | ||
Debug.Assert(attribute.Type is not null); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need this assert on all calls? |
||
writer.WritePropertyName(propertyName); | ||
WriteAttributeValue(writer, attribute.Value, attribute.Type); | ||
} | ||
|
||
internal static void WriteAttribute(Utf8JsonWriter writer, string propertyName, object value, string type) | ||
{ | ||
writer.WritePropertyName(propertyName); | ||
WriteAttributeValue(writer, value, type); | ||
} | ||
|
||
internal static void WriteAttribute(Utf8JsonWriter writer, string propertyName, object value) | ||
{ | ||
writer.WritePropertyName(propertyName); | ||
WriteAttributeValue(writer, value); | ||
} | ||
|
||
private static void WriteAttributeValue(Utf8JsonWriter writer, object value, string type) | ||
{ | ||
writer.WriteStartObject(); | ||
|
||
if (type == "string") | ||
{ | ||
writer.WriteString("value", (string)value); | ||
writer.WriteString("type", type); | ||
} | ||
else if (type == "boolean") | ||
{ | ||
writer.WriteBoolean("value", (bool)value); | ||
writer.WriteString("type", type); | ||
} | ||
else if (type == "integer") | ||
{ | ||
writer.WriteNumber("value", (long)value); | ||
writer.WriteString("type", type); | ||
} | ||
else if (type == "double") | ||
{ | ||
writer.WriteNumber("value", (double)value); | ||
writer.WriteString("type", type); | ||
} | ||
else | ||
{ | ||
writer.WriteString("value", value.ToString()); | ||
writer.WriteString("type", "string"); | ||
} | ||
|
||
writer.WriteEndObject(); | ||
} | ||
|
||
private static void WriteAttributeValue(Utf8JsonWriter writer, object value) | ||
{ | ||
writer.WriteStartObject(); | ||
|
||
if (value is string str) | ||
{ | ||
writer.WriteString("value", str); | ||
writer.WriteString("type", "string"); | ||
} | ||
else if (value is bool boolean) | ||
{ | ||
writer.WriteBoolean("value", boolean); | ||
writer.WriteString("type", "boolean"); | ||
} | ||
else if (value is int int32) | ||
{ | ||
writer.WriteNumber("value", int32); | ||
writer.WriteString("type", "integer"); | ||
} | ||
else if (value is long int64) | ||
{ | ||
writer.WriteNumber("value", int64); | ||
writer.WriteString("type", "integer"); | ||
} | ||
else if (value is double float64) | ||
{ | ||
writer.WriteNumber("value", float64); | ||
writer.WriteString("type", "double"); | ||
} | ||
else | ||
{ | ||
writer.WriteString("value", value.ToString()); | ||
writer.WriteString("type", "string"); | ||
} | ||
|
||
writer.WriteEndObject(); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.