Skip to content

Commit 8577fbe

Browse files
Add TZ Diagnostic Event (#9662)
* Fix typo in HostIdCollisionErrorCode * Add diagnostic event for when the function app has 10 non-decryptable secrets backups * Add a test case for a diagnostic event when the function app has 10 non-decryptable secrets backups * Log a diagnostic event if the read operation failed because the blob access tier is set to archived * Add BlobRepository_TierSetToArchive_ReadAsync_Logs_DiagnosticEvent * Update help links * Add diagnostic event for when there is a problem with the app package * Update Moq version to 4.20.69 * Add ZipPackageFailure_Logs_DiagnosticEvent test case * Add ApplyRunFromPackageContext_Throws_Logs_DiagnosticEvent test case * Add helper method to validate that the expected diagnostic event is present * Add a diagnostic event for parsing errors in the host configuration file * Add InvalidHostJsonLogsDiagnosticEvent test case * Fix build * Update logic to create a format exception with the inner exception, log it and throw * Update logic to catch the RequestFailedException directly * changes * adding unit tests * changes * trying to get diff to match * revert * comments * adding potential null case * addressing comments * fixing unit test --------- Co-authored-by: Francisco-Gamino <[email protected]>
1 parent 940e1a0 commit 8577fbe

File tree

7 files changed

+116
-24
lines changed

7 files changed

+116
-24
lines changed

src/WebJobs.Script.WebHost/Health/TokenExpirationService.cs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,26 @@ public TokenExpirationService(IEnvironment environment, ILogger<TokenExpirationS
4343

4444
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
4545
{
46-
await Task.Yield(); // force a yield, so our synchronous code does not slowdown startup
47-
await _standby.Task.WaitAsync(cancellationToken);
48-
49-
if (_environment.IsCoreTools())
46+
try
5047
{
51-
return;
52-
}
48+
await Task.Yield(); // force a yield, so our synchronous code does not slowdown startup
49+
await _standby.Task.WaitAsync(cancellationToken);
5350

54-
while (!cancellationToken.IsCancellationRequested)
51+
if (_environment.IsCoreTools())
52+
{
53+
return;
54+
}
55+
56+
while (!cancellationToken.IsCancellationRequested)
57+
{
58+
// check at every hour
59+
AnalyzeSasTokenInUri();
60+
await Task.Delay(TimeSpan.FromHours(1), cancellationToken);
61+
}
62+
}
63+
catch (Exception ex) when (ex is not OperationCanceledException)
5564
{
56-
// check at every hour
57-
AnalyzeSasTokenInUri();
58-
await Task.Delay(TimeSpan.FromHours(1), cancellationToken);
65+
_logger.LogWarning(ex.ToString());
5966
}
6067
}
6168

src/WebJobs.Script.WebHost/WebJobsScriptHostService.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ private void CheckFileSystem()
224224
}
225225
}
226226

227-
private void ValidateLinuxSKUConfiguration()
227+
private void ValidateLinuxSKUConfiguration(ILogger logger)
228228
{
229229
var websiteRunFromPackageValue = _environment.GetEnvironmentVariable(AzureWebsiteRunFromPackage);
230230
var scmRunFromPackageValue = _environment.GetEnvironmentVariable(ScmRunFromPackage);
@@ -234,7 +234,24 @@ private void ValidateLinuxSKUConfiguration()
234234
_environment.IsLinuxConsumptionOnAtlas() &&
235235
!_environment.IsManagedAppEnvironment())
236236
{
237-
_logger.LogError($"Unable to load the functions payload since the app was not provisioned with valid {AzureWebJobsSecretStorage} connection string.");
237+
logger?.LogError($"Unable to load the functions payload since the app was not provisioned with valid {AzureWebJobsSecretStorage} connection string.");
238+
}
239+
240+
var functionsTimeZone = _environment.GetEnvironmentVariable(EnvironmentSettingNames.FunctionsTimeZone);
241+
var functionsWebsiteTimeZone = _environment.GetEnvironmentVariable(EnvironmentSettingNames.FunctionsWebsiteTimeZone);
242+
243+
// If we have a linux consumption app and the time zone env variable is set, log a warning and diagnostic event
244+
if (_environment.IsLinuxConsumptionOnAtlas() &&
245+
(!string.IsNullOrEmpty(functionsTimeZone) ||
246+
!string.IsNullOrEmpty(functionsWebsiteTimeZone)))
247+
{
248+
string message = Script.Properties.Resources.LinuxConsumptionRemoveTimeZone;
249+
250+
// Log diagnostic event
251+
logger?.LogDiagnosticEventError(DiagnosticEventConstants.LinuxConsumptionTimeZoneErrorCode, message, DiagnosticEventConstants.LinuxConsumptionTimeZoneErrorHelpLink, new InvalidOperationException(message));
252+
253+
// Log warning so this message goes to App insights
254+
logger?.LogWarning(message);
238255
}
239256
}
240257

@@ -326,7 +343,7 @@ private async Task UnsynchronizedStartHostAsync(ScriptHostStartupOperation activ
326343

327344
LogInitialization(localHost, isOffline, attemptCount, ++_hostStartCount, activeOperation.Id);
328345

329-
ValidateLinuxSKUConfiguration();
346+
ValidateLinuxSKUConfiguration(GetHostLogger(localHost));
330347

331348
if (!_scriptWebHostEnvironment.InStandbyMode)
332349
{

src/WebJobs.Script/Diagnostics/DiagnosticEventConstants.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,8 @@ internal static class DiagnosticEventConstants
2222

2323
public const string UnableToParseHostConfigurationFileErrorCode = "AZFD0009";
2424
public const string UnableToParseHostConfigurationFileHelpLink = "https://go.microsoft.com/fwlink/?linkid=2248917";
25+
26+
public const string LinuxConsumptionTimeZoneErrorCode = "AZFD0010";
27+
public const string LinuxConsumptionTimeZoneErrorHelpLink = "https://go.microsoft.com/fwlink/?linkid=2250165";
2528
}
2629
}

src/WebJobs.Script/Environment/EnvironmentSettingNames.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ public static class EnvironmentSettingNames
7474
public const string WebsiteNodeDefaultVersion = "WEBSITE_NODE_DEFAULT_VERSION";
7575
public const string FunctionsMetricsPublishPath = "FUNCTIONS_METRICS_PUBLISH_PATH";
7676
public const string FunctionsAlwaysReadyInstance = "FUNCTIONS_ALWAYSREADY_INSTANCE";
77+
public const string FunctionsTimeZone = "TZ";
78+
public const string FunctionsWebsiteTimeZone = "WEBSITE_TIME_ZONE";
7779

7880
//Function in Kubernetes
7981
public const string PodNamespace = "POD_NAMESPACE";

src/WebJobs.Script/Properties/Resources.Designer.cs

Lines changed: 20 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/WebJobs.Script/Properties/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,7 @@
176176
<data name="SasTokenExpiringInfoFormat" xml:space="preserve">
177177
<value>SAS token within '{1}' setting is set to expire in {0} days.</value>
178178
</data>
179+
<data name="LinuxConsumptionRemoveTimeZone" xml:space="preserve">
180+
<value>The environment variables 'WEBSITE_TIME_ZONE' and 'TZ' are not supported on this platform. For more information, see https://go.microsoft.com/fwlink/?linkid=2250165.</value>
181+
</data>
179182
</root>

test/WebJobs.Script.Tests.Integration/Host/StandbyManager/StandbyManagerE2ETests_Linux.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
using System.Linq;
88
using System.Net;
99
using System.Net.Http;
10+
using System.Reactive.Joins;
1011
using System.Text;
1112
using System.Threading.Tasks;
13+
using DryIoc;
14+
using Microsoft.Azure.WebJobs.Script.Tests.Integration.Diagnostics;
1215
using Microsoft.Azure.WebJobs.Script.WebHost;
1316
using Microsoft.Azure.WebJobs.Script.WebHost.Authentication;
1417
using Microsoft.Azure.WebJobs.Script.WebHost.Models;
@@ -17,6 +20,8 @@
1720
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
1821
using Microsoft.Extensions.Configuration;
1922
using Microsoft.Extensions.DependencyInjection;
23+
using Microsoft.Extensions.Hosting;
24+
using Microsoft.Extensions.Logging;
2025
using Microsoft.Extensions.Options;
2126
using Microsoft.WebJobs.Script.Tests;
2227
using Newtonsoft.Json;
@@ -153,6 +158,52 @@ public async Task StandbyModeE2E_LinuxContainer()
153158
Assert.NotSame(GetCachedTimeZoneInfo(), _originalTimeZoneInfoCache);
154159
}
155160

161+
[Fact]
162+
public async Task LinuxContainer_TimeZoneEnvVariableE2E()
163+
{
164+
byte[] bytes = TestHelpers.GenerateKeyBytes();
165+
var encryptionKey = Convert.ToBase64String(bytes);
166+
var containerName = "testContainer";
167+
168+
var vars = new Dictionary<string, string>
169+
{
170+
{ EnvironmentSettingNames.AzureWebsitePlaceholderMode, "1" },
171+
{ EnvironmentSettingNames.ContainerName, containerName },
172+
{ EnvironmentSettingNames.AzureWebsiteHostName, "testapp.azurewebsites.net" },
173+
{ EnvironmentSettingNames.AzureWebsiteName, "TestApp" },
174+
{ EnvironmentSettingNames.ContainerEncryptionKey, encryptionKey },
175+
{ EnvironmentSettingNames.AzureWebsiteContainerReady, null },
176+
{ EnvironmentSettingNames.AzureWebsiteSku, "Dynamic" },
177+
{ EnvironmentSettingNames.AzureWebsiteZipDeployment, null },
178+
{ EnvironmentSettingNames.AzureWebJobsFeatureFlags, ScriptConstants.FeatureFlagEnableProxies },
179+
{ "AzureWebEncryptionKey", "0F75CA46E7EBDD39E4CA6B074D1F9A5972B849A55F91A248" },
180+
{ EnvironmentSettingNames.FunctionsTimeZone, "Europe/Berlin" }
181+
};
182+
183+
var environment = new TestEnvironment(vars);
184+
185+
Assert.True(environment.IsLinuxConsumptionOnAtlas());
186+
Assert.False(environment.IsFlexConsumptionSku());
187+
Assert.True(environment.IsAnyLinuxConsumption());
188+
189+
await InitializeTestHostAsync("Linux", environment);
190+
191+
var expectedTraceMessage = "The environment variables 'WEBSITE_TIME_ZONE' and 'TZ' are not supported on this platform. For more information, see https://go.microsoft.com/fwlink/?linkid=2250165.";
192+
193+
// verify the expected logs
194+
var logLines = _loggerProvider.GetAllLogMessages().Where(p => p.FormattedMessage != null).Select(p => p.FormattedMessage).ToArray();
195+
Assert.Equal(2, logLines.Count(p => p.Contains(expectedTraceMessage)));
196+
197+
DiagnosticEventTestUtils.ValidateThatTheExpectedDiagnosticEventIsPresent(
198+
_loggerProvider,
199+
expectedTraceMessage,
200+
LogLevel.Error,
201+
DiagnosticEventConstants.LinuxConsumptionTimeZoneErrorHelpLink,
202+
DiagnosticEventConstants.LinuxConsumptionTimeZoneErrorCode
203+
);
204+
205+
}
206+
156207
private async Task Assign(string encryptionKey)
157208
{
158209
// create a zip package

0 commit comments

Comments
 (0)