Skip to content

Commit 800db8c

Browse files
authored
Update healthcheck unhealthy log to use JSON (#11380)
* Update healthcheck unhealthy log to use JSON Use custom JSON converter to write health entries log Add comments explaining JSON wrapper Remove accidental changes * Fix log test assertions
1 parent 920b01e commit 800db8c

File tree

2 files changed

+64
-28
lines changed

2 files changed

+64
-28
lines changed

src/WebJobs.Script/Diagnostics/HealthChecks/TelemetryHealthCheckPublisher.cs

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using System;
55
using System.Linq;
6-
using System.Text;
6+
using System.Text.Json;
7+
using System.Text.Json.Serialization;
78
using System.Threading;
89
using System.Threading.Tasks;
9-
using Microsoft.Azure.WebJobs.Script.Pools;
1010
using Microsoft.Extensions.Diagnostics.HealthChecks;
1111
using Microsoft.Extensions.Logging;
1212

@@ -58,29 +58,15 @@ public Task PublishAsync(HealthReport report, CancellationToken cancellationToke
5858
}
5959
else
6060
{
61-
// Construct string showing list of all health entries status and description for logs
62-
using PoolRental<StringBuilder> rental = PoolFactory.SharedStringBuilderPool.Rent();
63-
string separator = string.Empty;
6461
foreach (var entry in report.Entries)
6562
{
6663
if (entry.Value.Status != HealthStatus.Healthy)
6764
{
6865
_metrics.UnhealthyHealthCheck.Record(entry.Key, entry.Value, tag);
6966
}
70-
71-
rental.Value.Append(separator)
72-
.Append(entry.Key)
73-
.Append(": {")
74-
.Append("status: ")
75-
.Append(entry.Value.Status.ToString())
76-
.Append(", description: ")
77-
.Append(entry.Value.Description)
78-
.Append('}');
79-
80-
separator = ", ";
8167
}
8268

83-
Log.Unhealthy(_logger, tag, report.Status, rental.Value);
69+
Log.Unhealthy(_logger, tag, report.Status, new HealthEntries(report));
8470
}
8571

8672
_metrics.HealthCheckReport.Record(report, tag);
@@ -92,14 +78,60 @@ private bool FilterForTag(string name, HealthReportEntry entry)
9278
return entry.Tags.Contains(_options.Tag);
9379
}
9480

95-
internal static partial class Log
81+
/// <summary>
82+
/// Wraps the health report entries for logging purposes.
83+
/// </summary>
84+
/// <param name="report">The report to log.</param>
85+
/// <remarks>
86+
/// By wrapping in a struct, we delay performing JSON serialization
87+
/// until this is actually being logged (and not when it is filtered out).
88+
/// </remarks>
89+
private readonly struct HealthEntries(HealthReport report)
90+
{
91+
private static readonly JsonSerializerOptions _options
92+
= new() { Converters = { new HealthEntriesConverter() } };
93+
94+
public override string ToString()
95+
{
96+
// We use a JSON serializer here to ensure proper escaping of values.
97+
return JsonSerializer.Serialize(report, _options);
98+
}
99+
}
100+
101+
private class HealthEntriesConverter : JsonConverter<HealthReport>
102+
{
103+
public override HealthReport Read(
104+
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
105+
{
106+
throw new NotImplementedException();
107+
}
108+
109+
public override void Write(
110+
Utf8JsonWriter writer, HealthReport value, JsonSerializerOptions options)
111+
{
112+
writer.WriteStartObject();
113+
114+
foreach ((string name, HealthReportEntry entry) in value.Entries)
115+
{
116+
writer.WritePropertyName(name);
117+
writer.WriteStartObject();
118+
writer.WriteString("status", entry.Status.ToString());
119+
writer.WriteString("description", entry.Description);
120+
writer.WriteEndObject();
121+
}
122+
123+
writer.WriteEndObject();
124+
}
125+
}
126+
127+
private static partial class Log
96128
{
97129
[LoggerMessage(0, LogLevel.Warning, "[Tag='{Tag}'] Process reporting unhealthy: {Status}. Health check entries are {Entries}")]
98130
public static partial void Unhealthy(
99131
ILogger logger,
100132
string tag,
101133
HealthStatus status,
102-
StringBuilder entries);
134+
HealthEntries entries);
103135

104136
[LoggerMessage(1, LogLevel.Debug, "[Tag='{Tag}'] Process reporting healthy: {Status}.")]
105137
public static partial void Healthy(

test/WebJobs.Script.Tests/Diagnostics/HealthChecks/TelemetryHealthCheckPublisherTests.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using System;
@@ -33,15 +33,17 @@ public class TelemetryHealthCheckPublisherTests
3333
CreateOptions(true, null),
3434
[HealthStatus.Degraded],
3535
1,
36-
"Process reporting unhealthy: Degraded. Health check entries are id0: {status: Degraded, description: desc0}",
36+
@"Process reporting unhealthy: Degraded. Health check entries are " +
37+
@"{""id0"":{""status"":""Degraded"",""description"":""desc0""}}",
3738
LogLevel.Warning,
3839
0.5
3940
},
4041
{
4142
CreateOptions(false, null),
4243
[HealthStatus.Unhealthy],
4344
1,
44-
"Process reporting unhealthy: Unhealthy. Health check entries are id0: {status: Unhealthy, description: desc0}",
45+
"Process reporting unhealthy: Unhealthy. Health check entries are "
46+
+ @"{""id0"":{""status"":""Unhealthy"",""description"":""desc0""}}",
4547
LogLevel.Warning,
4648
0
4749
},
@@ -57,15 +59,17 @@ public class TelemetryHealthCheckPublisherTests
5759
CreateOptions(true, null),
5860
[HealthStatus.Healthy, HealthStatus.Unhealthy],
5961
1,
60-
"Process reporting unhealthy: Unhealthy. Health check entries are id0: {status: Healthy, description: desc0}, id1: {status: Unhealthy, description: desc1}",
62+
"Process reporting unhealthy: Unhealthy. Health check entries are "
63+
+ @"{""id0"":{""status"":""Healthy"",""description"":""desc0""},""id1"":{""status"":""Unhealthy"",""description"":""desc1""}}",
6164
LogLevel.Warning,
6265
0
6366
},
6467
{
6568
CreateOptions(true, null),
6669
[HealthStatus.Healthy, (HealthStatus.Unhealthy, "some.tag")],
6770
1,
68-
"Process reporting unhealthy: Unhealthy. Health check entries are id0: {status: Healthy, description: desc0}, id1: {status: Unhealthy, description: desc1}",
71+
"Process reporting unhealthy: Unhealthy. Health check entries are " +
72+
@"{""id0"":{""status"":""Healthy"",""description"":""desc0""},""id1"":{""status"":""Unhealthy"",""description"":""desc1""}}",
6973
LogLevel.Warning,
7074
0
7175
},
@@ -74,7 +78,7 @@ public class TelemetryHealthCheckPublisherTests
7478
[HealthStatus.Healthy, (HealthStatus.Degraded, "some.tag"), HealthStatus.Unhealthy],
7579
1,
7680
"Process reporting unhealthy: Unhealthy. Health check entries are " +
77-
"id0: {status: Healthy, description: desc0}, id1: {status: Degraded, description: desc1}, id2: {status: Unhealthy, description: desc2}",
81+
@"{""id0"":{""status"":""Healthy"",""description"":""desc0""},""id1"":{""status"":""Degraded"",""description"":""desc1""},""id2"":{""status"":""Unhealthy"",""description"":""desc2""}}",
7882
LogLevel.Warning,
7983
0
8084
},
@@ -91,7 +95,7 @@ public class TelemetryHealthCheckPublisherTests
9195
[HealthStatus.Healthy, (HealthStatus.Degraded, "some.tag"), HealthStatus.Unhealthy],
9296
1,
9397
"Process reporting unhealthy: Degraded. Health check entries are " +
94-
"id1: {status: Degraded, description: desc1}",
98+
@"{""id1"":{""status"":""Degraded"",""description"":""desc1""}}",
9599
LogLevel.Warning,
96100
0.5
97101
},
@@ -100,7 +104,7 @@ public class TelemetryHealthCheckPublisherTests
100104
[(HealthStatus.Healthy, "some.tag"), (HealthStatus.Degraded, "some.tag"), (HealthStatus.Unhealthy, "some.other.tag"), (HealthStatus.Unhealthy, "some.tag")],
101105
1,
102106
"Process reporting unhealthy: Unhealthy. Health check entries are " +
103-
"id0: {status: Healthy, description: desc0}, id1: {status: Degraded, description: desc1}, id3: {status: Unhealthy, description: desc3}",
107+
@"{""id0"":{""status"":""Healthy"",""description"":""desc0""},""id1"":{""status"":""Degraded"",""description"":""desc1""},""id3"":{""status"":""Unhealthy"",""description"":""desc3""}}",
104108
LogLevel.Warning,
105109
0
106110
}

0 commit comments

Comments
 (0)