Skip to content

Commit 09ad86b

Browse files
committed
perf(logs): avoid string allocation when no parameters are passed to be formatted via the template
1 parent 18ca31b commit 09ad86b

File tree

3 files changed

+48
-8
lines changed

3 files changed

+48
-8
lines changed

src/Sentry/Internal/DefaultSentryStructuredLogger.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,18 @@ private protected override void CaptureLog(SentryLogLevel level, string template
2929
var timestamp = _clock.GetUtcNow();
3030
SentryLog.GetTraceIdAndSpanId(_hub, out var traceId, out var spanId);
3131

32-
string message;
33-
try
34-
{
35-
message = string.Format(CultureInfo.InvariantCulture, template, parameters ?? []);
36-
}
37-
catch (FormatException e)
32+
string message = template;
33+
if (parameters is { Length: > 0 })
3834
{
39-
_options.DiagnosticLogger?.LogError(e, "Template string does not match the provided argument. The Log will be dropped.");
40-
return;
35+
try
36+
{
37+
message = string.Format(CultureInfo.InvariantCulture, template, parameters);
38+
}
39+
catch (FormatException e)
40+
{
41+
_options.DiagnosticLogger?.LogError(e, "Template string does not match the provided argument. The Log will be dropped.");
42+
return;
43+
}
4144
}
4245

4346
ImmutableArray<KeyValuePair<string, object>> @params = default;

test/Sentry.Tests/SentryStructuredLoggerTests.Format.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,33 @@ public void Log_ConfigureLog_Disabled_DoesNotCaptureEnvelope(SentryLogLevel leve
8383

8484
_fixture.Hub.Received(0).CaptureEnvelope(Arg.Any<Envelope>());
8585
}
86+
87+
[Theory]
88+
[InlineData(SentryLogLevel.Trace)]
89+
[InlineData(SentryLogLevel.Debug)]
90+
[InlineData(SentryLogLevel.Info)]
91+
[InlineData(SentryLogLevel.Warning)]
92+
[InlineData(SentryLogLevel.Error)]
93+
[InlineData(SentryLogLevel.Fatal)]
94+
public void Log_WithoutParameters_DoesNotAttachTemplateAttribute(SentryLogLevel level)
95+
{
96+
_fixture.Options.Experimental.EnableLogs = true;
97+
var logger = _fixture.GetSut();
98+
99+
Envelope envelope = null!;
100+
_fixture.Hub.CaptureEnvelope(Arg.Do<Envelope>(arg => envelope = arg));
101+
102+
logger.Log(level, "Message Text");
103+
logger.Flush();
104+
105+
_fixture.Hub.Received(1).CaptureEnvelope(Arg.Any<Envelope>());
106+
var log = envelope.ShouldContainSingleLog();
107+
108+
log.Level.Should().Be(level);
109+
log.Message.Should().Be("Message Text");
110+
log.Template.Should().BeNull();
111+
log.Parameters.Should().BeEmpty();
112+
}
86113
}
87114

88115
file static class SentryStructuredLoggerExtensions

test/Sentry.Tests/SentryStructuredLoggerTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,14 @@ public static void AssertLog(this SentryStructuredLoggerTests.Fixture fixture, S
301301
{
302302
return new KeyValuePair<string, object?>(name, value);
303303
}
304+
305+
public static SentryLog ShouldContainSingleLog(this Envelope envelope)
306+
{
307+
var envelopeItem = envelope.Items.Should().ContainSingle().Which;
308+
var serializable = envelopeItem.Payload.Should().BeOfType<JsonSerializable>().Which;
309+
var log = serializable.Source.Should().BeOfType<StructuredLog>().Which;
310+
311+
log.Items.Length.Should().Be(1);
312+
return log.Items[0];
313+
}
304314
}

0 commit comments

Comments
 (0)