Skip to content

Commit 920b01e

Browse files
krishnajajuKrishna Jaju
andauthored
Add config to disable console logging in Functions on ACA (#11340)
* option to disable console logging in kubernetes environment * minor change * address comments * minor formatting change * minor fix * address comments --------- Co-authored-by: Krishna Jaju <[email protected]>
1 parent 204629a commit 920b01e

File tree

4 files changed

+67
-38
lines changed

4 files changed

+67
-38
lines changed

src/WebJobs.Script.WebHost/Diagnostics/KubernetesEventGenerator.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
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;
5+
using Microsoft.Azure.WebJobs.Script.Config;
56
using Microsoft.Extensions.Logging;
7+
using Microsoft.Extensions.Options;
68
using Newtonsoft.Json;
79
using Newtonsoft.Json.Linq;
810

@@ -13,9 +15,11 @@ internal class KubernetesEventGenerator : LinuxEventGenerator
1315
private const int MaxDetailsLength = 10000;
1416
private readonly Action<string> _writeEvent;
1517

16-
public KubernetesEventGenerator(Action<string> writeEvent = null)
18+
public KubernetesEventGenerator(IOptions<ConsoleLoggingOptions> consoleLoggingOptions)
1719
{
18-
_writeEvent = writeEvent ?? ConsoleWriter;
20+
_writeEvent = consoleLoggingOptions.Value.LoggingDisabled
21+
? _ => { } // no-op
22+
: consoleLoggingOptions.Value.Writer.WriteLine;
1923
}
2024

2125
public override void LogFunctionTraceEvent(LogLevel level, string subscriptionId, string appName, string functionName, string eventName, string source, string details, string summary, string exceptionType, string exceptionMessage, string functionInvocationId, string hostInstanceId, string activityId, string runtimeSiteName, string slotName, DateTime eventTimestamp)
@@ -101,10 +105,5 @@ public override void LogAzureMonitorDiagnosticLogEvent(LogLevel level, string re
101105

102106
_writeEvent(azMonEvent.ToString(Formatting.None));
103107
}
104-
105-
private void ConsoleWriter(string evt)
106-
{
107-
Console.WriteLine(evt);
108-
}
109108
}
110109
}

src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs

Lines changed: 3 additions & 2 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;
@@ -131,7 +131,8 @@ public static void AddWebJobsScriptHost(this IServiceCollection services, IConfi
131131
}
132132
else if (environment.IsAnyKubernetesEnvironment())
133133
{
134-
return new KubernetesEventGenerator();
134+
var consoleLoggingOptions = p.GetService<IOptions<ConsoleLoggingOptions>>();
135+
return new KubernetesEventGenerator(consoleLoggingOptions);
135136
}
136137
else
137138
{

src/WebJobs.Script/Config/ConsoleLoggingOptions.cs

Lines changed: 1 addition & 2 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;
@@ -22,7 +22,6 @@ public class ConsoleLoggingOptions
2222

2323
/// <summary>
2424
/// Gets or sets the <see cref="TextWriter"/> to write logs to.
25-
/// IMPORTANT: this is primarily for unit tests to redirect logs to a different writer.
2625
/// </summary>
2726
internal TextWriter Writer { get; set; } = Console.Out;
2827
}
Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,54 @@
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;
5-
using System.Collections.Generic;
5+
using System.IO;
66
using System.Linq;
7+
using Microsoft.Azure.WebJobs.Script.Config;
78
using Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics;
89
using Microsoft.Extensions.Logging;
10+
using Microsoft.Extensions.Options;
911
using Newtonsoft.Json.Linq;
1012
using Xunit;
1113

1214
namespace Microsoft.Azure.WebJobs.Script.Tests.Diagnostics
1315
{
14-
public class KubernetesEventGeneratorTests
16+
public sealed class KubernetesEventGeneratorTests : IDisposable
1517
{
16-
private readonly KubernetesEventGenerator _generator;
17-
private readonly List<string> _events;
18+
private readonly StringWriter _writer = new();
1819

19-
public KubernetesEventGeneratorTests()
20+
public void Dispose()
2021
{
21-
_events = new List<string>();
22-
Action<string> writer = (s) =>
23-
{
24-
_events.Add(s);
25-
};
22+
_writer.Dispose();
23+
}
2624

27-
_generator = new KubernetesEventGenerator(writer);
25+
[Theory]
26+
[MemberData(nameof(LinuxEventGeneratorTestData.GetLogEvents), MemberType = typeof(LinuxEventGeneratorTestData))]
27+
public void LoggingDisabled(LogLevel level, string subscriptionId, string appName, string functionName, string eventName, string source, string details, string summary, string exceptionType, string exceptionMessage, string functionInvocationId, string hostInstanceId, string activityId, string runtimeSiteName, string slotName)
28+
{
29+
var options = CreateLoggingOptions(consoleDisabled: true);
30+
var generator = new KubernetesEventGenerator(options);
31+
32+
generator.LogFunctionTraceEvent(level, subscriptionId, appName, functionName, eventName, source, details, summary, exceptionType, exceptionMessage, functionInvocationId, hostInstanceId, activityId, runtimeSiteName, slotName, DateTime.UtcNow);
33+
34+
string output = _writer.ToString().Trim();
35+
36+
Assert.True(string.IsNullOrEmpty(output));
2837
}
2938

3039
[Theory]
3140
[MemberData(nameof(LinuxEventGeneratorTestData.GetLogEvents), MemberType = typeof(LinuxEventGeneratorTestData))]
3241
public void ParseLogEvents(LogLevel level, string subscriptionId, string appName, string functionName, string eventName, string source, string details, string summary, string exceptionType, string exceptionMessage, string functionInvocationId, string hostInstanceId, string activityId, string runtimeSiteName, string slotName)
3342
{
34-
_generator.LogFunctionTraceEvent(level, subscriptionId, appName, functionName, eventName, source, details, summary, exceptionType, exceptionMessage, functionInvocationId, hostInstanceId, activityId, runtimeSiteName, slotName, DateTime.UtcNow);
43+
var options = CreateLoggingOptions(consoleDisabled: false);
44+
var generator = new KubernetesEventGenerator(options);
3545

36-
string evt = _events.Single();
37-
var jObject = JObject.Parse(evt);
46+
generator.LogFunctionTraceEvent(level, subscriptionId, appName, functionName, eventName, source, details, summary, exceptionType, exceptionMessage, functionInvocationId, hostInstanceId, activityId, runtimeSiteName, slotName, DateTime.UtcNow);
3847

39-
Assert.Equal(18, jObject.Properties().Count());
48+
string output = _writer.ToString().Trim();
49+
var jObject = JObject.Parse(output);
4050

41-
DateTime dt;
51+
Assert.Equal(18, jObject.Properties().Count());
4252
Assert.Collection(jObject.Properties(),
4353
p => Assert.Equal(ScriptConstants.LinuxLogEventStreamName, p.Value),
4454
p => Assert.Equal((int)LinuxEventGenerator.ToEventLevel(level), int.Parse(p.Value.ToString())),
@@ -50,7 +60,7 @@ public void ParseLogEvents(LogLevel level, string subscriptionId, string appName
5060
p => Assert.Equal(LinuxEventGenerator.NormalizeString(details, addEnclosingQuotes: false), p.Value.ToString()),
5161
p => Assert.Equal(LinuxEventGenerator.NormalizeString(summary, addEnclosingQuotes: false), p.Value.ToString()),
5262
p => Assert.Equal(ScriptHost.Version, p.Value),
53-
p => Assert.True(DateTime.TryParse(p.Value.ToString(), out dt)),
63+
p => Assert.True(DateTime.TryParse(p.Value.ToString(), out _)),
5464
p => Assert.Equal(exceptionType, p.Value.ToString()),
5565
p => Assert.Equal(LinuxEventGenerator.NormalizeString(exceptionMessage, addEnclosingQuotes: false), p.Value.ToString()),
5666
p => Assert.Equal(functionInvocationId, p.Value.ToString()),
@@ -64,14 +74,16 @@ public void ParseLogEvents(LogLevel level, string subscriptionId, string appName
6474
[MemberData(nameof(LinuxEventGeneratorTestData.GetMetricEvents), MemberType = typeof(LinuxEventGeneratorTestData))]
6575
public void ParseMetricEvents(string subscriptionId, string appName, string functionName, string eventName, long average, long minimum, long maximum, long count, string data, string runtimeSiteName, string slotName)
6676
{
67-
_generator.LogFunctionMetricEvent(subscriptionId, appName, functionName, eventName, average, minimum, maximum, count, DateTime.Now, data, runtimeSiteName, slotName);
77+
var options = CreateLoggingOptions(consoleDisabled: false);
78+
var generator = new KubernetesEventGenerator(options);
6879

69-
string evt = _events.Single();
70-
var jObject = JObject.Parse(evt);
80+
generator.LogFunctionMetricEvent(subscriptionId, appName, functionName, eventName, average, minimum, maximum, count, DateTime.Now, data, runtimeSiteName, slotName);
81+
82+
string output = _writer.ToString().Trim();
83+
var jObject = JObject.Parse(output);
7184

7285
Assert.Equal(14, jObject.Properties().Count());
7386

74-
DateTime dt;
7587
Assert.Collection(jObject.Properties(),
7688
p => Assert.Equal(ScriptConstants.LinuxMetricEventStreamName, p.Value),
7789
p => Assert.Equal(subscriptionId, p.Value),
@@ -83,7 +95,7 @@ public void ParseMetricEvents(string subscriptionId, string appName, string func
8395
p => Assert.Equal(maximum, long.Parse(p.Value.ToString())),
8496
p => Assert.Equal(count, long.Parse(p.Value.ToString())),
8597
p => Assert.Equal(ScriptHost.Version, p.Value),
86-
p => Assert.True(DateTime.TryParse(p.Value.ToString(), out dt)),
98+
p => Assert.True(DateTime.TryParse(p.Value.ToString(), out _)),
8799
p => Assert.Equal(LinuxEventGenerator.NormalizeString(data), p.Value),
88100
p => Assert.Equal(runtimeSiteName, p.Value),
89101
p => Assert.Equal(slotName, p.Value));
@@ -93,10 +105,13 @@ public void ParseMetricEvents(string subscriptionId, string appName, string func
93105
[MemberData(nameof(LinuxEventGeneratorTestData.GetAzureMonitorEvents), MemberType = typeof(LinuxEventGeneratorTestData))]
94106
public void ParseAzureMonitoringEvents(LogLevel level, string resourceId, string operationName, string category, string regionName, string properties)
95107
{
96-
_generator.LogAzureMonitorDiagnosticLogEvent(level, resourceId, operationName, category, regionName, properties);
108+
var options = CreateLoggingOptions(consoleDisabled: false);
109+
var generator = new KubernetesEventGenerator(options);
110+
111+
generator.LogAzureMonitorDiagnosticLogEvent(level, resourceId, operationName, category, regionName, properties);
97112

98-
string evt = _events.Single();
99-
var jObject = JObject.Parse(evt);
113+
string output = _writer.ToString().Trim();
114+
var jObject = JObject.Parse(output);
100115

101116
Assert.Equal(7, jObject.Properties().Count());
102117

@@ -109,5 +124,20 @@ public void ParseAzureMonitoringEvents(LogLevel level, string resourceId, string
109124
p => Assert.Equal(regionName, p.Value),
110125
p => Assert.Equal(LinuxEventGenerator.NormalizeString(properties), p.Value));
111126
}
127+
128+
private IOptions<ConsoleLoggingOptions> CreateLoggingOptions(bool? consoleDisabled = null)
129+
{
130+
ConsoleLoggingOptions options = new()
131+
{
132+
Writer = _writer
133+
};
134+
135+
if (consoleDisabled.HasValue)
136+
{
137+
options.LoggingDisabled = consoleDisabled.Value;
138+
}
139+
140+
return Options.Create(options);
141+
}
112142
}
113143
}

0 commit comments

Comments
 (0)