Skip to content

Commit b0f9836

Browse files
authored
[IN-PROC] Adding support to emit azmon logs in iso time format for Dedicated sku based on a flag. (#10810)
* Adding support to emit azmon logs in iso time format for Dedicated sku based on a flag. * Using IOptions and adding tests * Injectiving env instead of configuration * nit * renaming and reordering * formatting * Using Configuration and other improvements. * Update release notes * Using featureflag * removing unused import * marking classes as internal sealed
1 parent bbcfa82 commit b0f9836

File tree

8 files changed

+63
-7
lines changed

8 files changed

+63
-7
lines changed

release_notes.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
<!-- Please add your release notes in the following format:
44
- My change description (#PR)
55
-->
6-
- Update Java Worker Version to [2.18.1](https://github.com/Azure/azure-functions-java-worker/releases/tag/2.18.1)
6+
- Update Java Worker Version to [2.18.1](https://github.com/Azure/azure-functions-java-worker/releases/tag/2.18.1)
7+
- Add support for new FeatureFlag `EnableAzureMonitorTimeIsoFormat` to enable iso time format for azmon logs for Linux Dedicated/EP Skus. (part of #7864)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Configuration
7+
{
8+
internal sealed class AzureMonitorLoggingOptions
9+
{
10+
public bool IsAzureMonitorTimeIsoFormatEnabled { get; set; }
11+
12+
public string GetUtcDateTime()
13+
{
14+
return IsAzureMonitorTimeIsoFormatEnabled ? DateTime.UtcNow.ToString("s") : DateTime.UtcNow.ToString();
15+
}
16+
}
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using Microsoft.Azure.WebJobs.Script.Config;
5+
using Microsoft.Extensions.Options;
6+
7+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Configuration
8+
{
9+
internal sealed class AzureMonitorLoggingOptionsSetup : IConfigureOptions<AzureMonitorLoggingOptions>
10+
{
11+
public void Configure(AzureMonitorLoggingOptions options)
12+
{
13+
options.IsAzureMonitorTimeIsoFormatEnabled = FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableAzureMonitorTimeIsoFormat);
14+
}
15+
}
16+
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using Microsoft.Azure.WebJobs.Script.Config;
6+
using Microsoft.Azure.WebJobs.Script.WebHost.Configuration;
67
using Microsoft.Extensions.Logging;
78
using Microsoft.Extensions.Options;
89

@@ -13,6 +14,7 @@ internal class LinuxAppServiceEventGenerator : LinuxEventGenerator
1314
private readonly Action<string> _writeEvent;
1415
private readonly HostNameProvider _hostNameProvider;
1516
private readonly IOptions<FunctionsHostingConfigOptions> _functionsHostingConfigOptions;
17+
private readonly IOptions<AzureMonitorLoggingOptions> _azureMonitorLoggingOptions;
1618
private ILinuxAppServiceFileLogger _functionsExecutionEventsCategoryLogger;
1719
private ILinuxAppServiceFileLogger _functionsLogsCategoryLogger;
1820
private ILinuxAppServiceFileLogger _functionsMetricsCategoryLogger;
@@ -22,11 +24,13 @@ public LinuxAppServiceEventGenerator(
2224
ILinuxAppServiceFileLoggerFactory loggerFactory,
2325
HostNameProvider hostNameProvider,
2426
IOptions<FunctionsHostingConfigOptions> functionsHostingConfigOptions,
27+
IOptions<AzureMonitorLoggingOptions> azureMonitorLoggingOptions,
2528
Action<string> writeEvent = null)
2629
{
2730
_writeEvent = writeEvent ?? WriteEvent;
2831
_hostNameProvider = hostNameProvider ?? throw new ArgumentNullException(nameof(hostNameProvider));
2932
_functionsHostingConfigOptions = functionsHostingConfigOptions;
33+
_azureMonitorLoggingOptions = azureMonitorLoggingOptions;
3034
_functionsExecutionEventsCategoryLogger = loggerFactory.Create(FunctionsExecutionEventsCategory, backoffEnabled: !_functionsHostingConfigOptions.Value.DisableLinuxAppServiceLogBackoff);
3135
_functionsLogsCategoryLogger = loggerFactory.Create(FunctionsLogsCategory, backoffEnabled: false);
3236
_functionsMetricsCategoryLogger = loggerFactory.Create(FunctionsMetricsCategory, false);
@@ -110,7 +114,7 @@ private void WriteEvent(string eventPayload)
110114

111115
public override void LogAzureMonitorDiagnosticLogEvent(LogLevel level, string resourceId, string operationName, string category, string regionName, string properties)
112116
{
113-
_writeEvent($"{ScriptConstants.LinuxAzureMonitorEventStreamName} {(int)ToEventLevel(level)},{resourceId},{operationName},{category},{regionName},{NormalizeString(properties.Replace("'", string.Empty))},{DateTime.UtcNow}");
117+
_writeEvent($"{ScriptConstants.LinuxAzureMonitorEventStreamName} {(int)ToEventLevel(level)},{resourceId},{operationName},{category},{regionName},{NormalizeString(properties.Replace("'", string.Empty))},{_azureMonitorLoggingOptions.Value.GetUtcDateTime()}");
114118
}
115119

116120
public static void LogUnhandledException(Exception e)

src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ public static void AddWebJobsScriptHost(this IServiceCollection services, IConfi
107107
{
108108
var hostNameProvider = p.GetService<HostNameProvider>();
109109
IOptions<FunctionsHostingConfigOptions> functionsHostingConfigOptions = p.GetService<IOptions<FunctionsHostingConfigOptions>>();
110-
return new LinuxAppServiceEventGenerator(new LinuxAppServiceFileLoggerFactory(), hostNameProvider, functionsHostingConfigOptions);
110+
IOptions<AzureMonitorLoggingOptions> azureMonitorOptions = p.GetService<IOptions<AzureMonitorLoggingOptions>>();
111+
return new LinuxAppServiceEventGenerator(new LinuxAppServiceFileLoggerFactory(), hostNameProvider, functionsHostingConfigOptions, azureMonitorOptions);
111112
}
112113
else if (environment.IsAnyKubernetesEnvironment())
113114
{
@@ -206,6 +207,7 @@ public static void AddWebJobsScriptHost(this IServiceCollection services, IConfi
206207
services.ConfigureOptionsWithChangeTokenSource<AppServiceOptions, AppServiceOptionsSetup, SpecializationChangeTokenSource<AppServiceOptions>>();
207208
services.ConfigureOptionsWithChangeTokenSource<HttpBodyControlOptions, HttpBodyControlOptionsSetup, SpecializationChangeTokenSource<HttpBodyControlOptions>>();
208209
services.ConfigureOptions<ConsoleLoggingOptionsSetup>();
210+
services.ConfigureOptions<AzureMonitorLoggingOptionsSetup>();
209211
services.AddHostingConfigOptions(configuration);
210212

211213
services.TryAddSingleton<IDependencyValidator, DependencyValidator>();

src/WebJobs.Script/ScriptConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public static class ScriptConstants
137137
public const string FeatureFlagStrictHISModeWarn = "StrictHISModeWarn";
138138
public const string FeatureFlagEnableOrderedInvocationmessages = "EnableOrderedInvocationMessages";
139139
public const string FeatureFlagDisableOrderedInvocationMessages = "DisableOrderedInvocationMessages";
140+
public const string FeatureFlagEnableAzureMonitorTimeIsoFormat = "EnableAzureMonitorTimeIsoFormat";
140141
public const string HostingConfigDisableLinuxAppServiceDetailedExecutionEvents = "DisableLinuxExecutionDetails";
141142
public const string HostingConfigDisableLinuxAppServiceExecutionEventLogBackoff = "DisableLinuxLogBackoff";
142143
public const string FeatureFlagEnableLegacyDurableVersionCheck = "EnableLegacyDurableVersionCheck";

test/WebJobs.Script.Tests/Diagnostics/LinuxAppServiceEventGeneratorTests.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Linq;
77
using System.Text.RegularExpressions;
88
using Microsoft.Azure.WebJobs.Script.Config;
9+
using Microsoft.Azure.WebJobs.Script.WebHost.Configuration;
910
using Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics;
1011
using Microsoft.Extensions.Logging;
1112
using Microsoft.Extensions.Options;
@@ -21,6 +22,7 @@ public class LinuxAppServiceEventGeneratorTests
2122
private readonly LinuxAppServiceEventGenerator _generator;
2223
private readonly List<string> _events;
2324
private IOptions<FunctionsHostingConfigOptions> _functionsHostingConfigOptions;
25+
private IOptions<AzureMonitorLoggingOptions> _azureMonitorOptions;
2426

2527
public LinuxAppServiceEventGeneratorTests()
2628
{
@@ -33,13 +35,14 @@ public LinuxAppServiceEventGeneratorTests()
3335
var loggerFactoryMock = new MockLinuxAppServiceFileLoggerFactory();
3436

3537
_functionsHostingConfigOptions = Options.Create(new FunctionsHostingConfigOptions());
38+
_azureMonitorOptions = Options.Create(new AzureMonitorLoggingOptions());
3639

3740
var environmentMock = new Mock<IEnvironment>();
3841
environmentMock.Setup(f => f.GetEnvironmentVariable(It.Is<string>(v => v == "WEBSITE_HOSTNAME")))
3942
.Returns<string>(s => _hostNameDefault);
4043

4144
var hostNameProvider = new HostNameProvider(environmentMock.Object);
42-
_generator = new LinuxAppServiceEventGenerator(loggerFactoryMock, hostNameProvider, _functionsHostingConfigOptions, writer);
45+
_generator = new LinuxAppServiceEventGenerator(loggerFactoryMock, hostNameProvider, _functionsHostingConfigOptions, _azureMonitorOptions, writer);
4346
}
4447

4548
public static string UnNormalize(string normalized)
@@ -143,9 +146,11 @@ public void ParseDetailsEvents(string siteName, string functionName, string inpu
143146
}
144147

145148
[Theory]
146-
[MemberData(nameof(LinuxEventGeneratorTestData.GetAzureMonitorEvents), MemberType = typeof(LinuxEventGeneratorTestData))]
147-
public void ParseAzureMonitoringEvents(LogLevel level, string resourceId, string operationName, string category, string regionName, string properties)
149+
[MemberData(nameof(LinuxEventGeneratorTestData.GetAzureMonitorEventsForLinuxAppServiceEventGenerator), MemberType = typeof(LinuxEventGeneratorTestData))]
150+
public void ParseAzureMonitoringEvents(LogLevel level, string resourceId, string operationName, string category, string regionName, string properties, bool isAzureMonitorTimeIsoFormatEnabled)
148151
{
152+
_azureMonitorOptions.Value.IsAzureMonitorTimeIsoFormatEnabled = isAzureMonitorTimeIsoFormatEnabled;
153+
149154
_generator.LogAzureMonitorDiagnosticLogEvent(level, resourceId, operationName, category, regionName, properties);
150155

151156
string evt = _events.Single();
@@ -164,7 +169,11 @@ public void ParseAzureMonitoringEvents(LogLevel level, string resourceId, string
164169
p => Assert.Equal(category, p),
165170
p => Assert.Equal(regionName, p),
166171
p => Assert.Equal(properties, UnNormalize(p)),
167-
p => Assert.True(DateTime.TryParse(p, out DateTime dt)));
172+
p =>
173+
{
174+
Assert.True(DateTime.TryParse(p, out DateTime dt));
175+
Assert.Equal(isAzureMonitorTimeIsoFormatEnabled, p.Contains('T'));
176+
});
168177
}
169178

170179
[Theory]

test/WebJobs.Script.Tests/Diagnostics/LinuxEventGeneratorTestData.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ public static IEnumerable<object[]> GetLogEvents()
2727
yield return new object[] { LogLevel.Information, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty };
2828
}
2929

30+
public static IEnumerable<object[]> GetAzureMonitorEventsForLinuxAppServiceEventGenerator()
31+
{
32+
yield return new object[] { LogLevel.Information, "TestResourceId", "TestOperationName", "TestCategory", "TestRegionName", "TestProperties", true };
33+
yield return new object[] { LogLevel.Information, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, false };
34+
}
35+
3036
public static IEnumerable<object[]> GetAzureMonitorEvents()
3137
{
3238
yield return new object[] { LogLevel.Information, "TestResourceId", "TestOperationName", "TestCategory", "TestRegionName", "TestProperties" };

0 commit comments

Comments
 (0)