Skip to content

Commit 9975e06

Browse files
committed
logging to ILogger on config error
1 parent 116fab2 commit 9975e06

File tree

4 files changed

+79
-3
lines changed

4 files changed

+79
-3
lines changed

src/WebJobs.Script/Host/ScriptHost.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,17 +334,27 @@ protected virtual void Initialize()
334334
// If there's a parsing error, set up the logger and write out the previous messages so that they're
335335
// discoverable in Application Insights. There's no filter, but that's okay since we cannot parse host.json to
336336
// determine how to build the filtler.
337-
ConfigureLoggerFactory(ScriptConfig, FunctionTraceWriterFactory, _settingsManager, () => FileLoggingEnabled);
337+
ConfigureDefaultLoggerFactory();
338338
ILogger startupErrorLogger = hostConfig.LoggerFactory.CreateLogger(LogCategories.Startup);
339339
startupErrorLogger.LogInformation(readingFileMessage);
340340
startupErrorLogger.LogInformation(readFileMessage);
341341

342342
throw new FormatException(string.Format("Unable to parse {0} file.", ScriptConstants.HostMetadataFileName), ex);
343343
}
344344

345-
ApplyConfiguration(hostConfigObject, ScriptConfig);
345+
try
346+
{
347+
ApplyConfiguration(hostConfigObject, ScriptConfig);
348+
}
349+
catch (Exception)
350+
{
351+
// If we have an error applying the configuration (for example, a value is invalid),
352+
// make sure we have a default LoggerFactory so that the error log can be written.
353+
ConfigureDefaultLoggerFactory();
354+
throw;
355+
}
346356

347-
ConfigureLoggerFactory(ScriptConfig, FunctionTraceWriterFactory, _settingsManager, () => FileLoggingEnabled);
357+
ConfigureDefaultLoggerFactory();
348358

349359
// Use the startupLogger in this class as it is concerned with startup. The public Logger is used
350360
// for all other logging after startup.
@@ -544,6 +554,11 @@ private void LoadExtension(IExtensionConfigProvider instance, string locationHin
544554
config.AddExtension(instance);
545555
}
546556

557+
private void ConfigureDefaultLoggerFactory()
558+
{
559+
ConfigureLoggerFactory(ScriptConfig, FunctionTraceWriterFactory, _settingsManager, () => FileLoggingEnabled);
560+
}
561+
547562
internal static void ConfigureLoggerFactory(ScriptHostConfiguration scriptConfig, IFunctionTraceWriterFactory traceWriteFactory,
548563
ScriptSettingsManager settingsManager, Func<bool> isFileLoggingEnabled)
549564
{
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"logger": {
3+
"aggregator": {
4+
"flushTimeout": "00:30:00"
5+
}
6+
}
7+
}

test/WebJobs.Script.Tests.Integration/WebJobs.Script.Tests.Integration.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,9 @@
973973
<None Include="TestScripts\Node\WebHookTrigger\function.json">
974974
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
975975
</None>
976+
<None Include="TestScripts\OutOfRange\host.json">
977+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
978+
</None>
976979
<None Include="TestScripts\Php\BlobTriggerToBlob\function.json">
977980
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
978981
</None>

test/WebJobs.Script.Tests/ScriptHostTests.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,42 @@ public void Create_InvalidHostJson_ThrowsInformativeException()
382382
Assert.Equal("Invalid property identifier character: ~. Path '', line 2, position 4.", ex.InnerException.Message);
383383
}
384384

385+
[Fact]
386+
public void Create_HostJsonValueError_LogsError()
387+
{
388+
// Try to load valid host.json file that has an out-of-range value.
389+
// Ensure that it's logged to TraceWriter and ILogger
390+
391+
var traceWriter = new TestTraceWriter(TraceLevel.Verbose);
392+
string rootPath = Path.Combine(Environment.CurrentDirectory, @"TestScripts\OutOfRange");
393+
394+
ScriptHostConfiguration scriptConfig = new ScriptHostConfiguration()
395+
{
396+
RootScriptPath = rootPath,
397+
TraceWriter = traceWriter
398+
};
399+
400+
TestLoggerProvider provider = new TestLoggerProvider();
401+
scriptConfig.HostConfig.AddService<ILoggerFactoryBuilder>(new TestLoggerFactoryBuilder(provider));
402+
403+
var environment = new Mock<IScriptHostEnvironment>();
404+
var eventManager = new Mock<IScriptEventManager>();
405+
406+
var ex = Assert.Throws<ArgumentOutOfRangeException>(() =>
407+
{
408+
ScriptHost.Create(environment.Object, eventManager.Object, scriptConfig, _settingsManager);
409+
});
410+
411+
string msg = "ScriptHost initialization failed";
412+
var trace = traceWriter.Traces.Single(t => t.Level == TraceLevel.Error);
413+
Assert.Equal(msg, trace.Message);
414+
Assert.Same(ex, trace.Exception);
415+
416+
var loggerMessage = provider.CreatedLoggers.Single().LogMessages.Single();
417+
Assert.Equal(msg, loggerMessage.FormattedMessage);
418+
Assert.Same(ex, loggerMessage.Exception);
419+
}
420+
385421
[Theory]
386422
[InlineData("host")]
387423
[InlineData("-function")]
@@ -1476,5 +1512,20 @@ public void Dispose()
14761512
{
14771513
}
14781514
}
1515+
1516+
private class TestLoggerFactoryBuilder : ILoggerFactoryBuilder
1517+
{
1518+
private TestLoggerProvider _provider;
1519+
1520+
public TestLoggerFactoryBuilder(TestLoggerProvider provider)
1521+
{
1522+
_provider = provider;
1523+
}
1524+
1525+
public void AddLoggerProviders(ILoggerFactory factory, ScriptHostConfiguration scriptConfig, ScriptSettingsManager settingsManager)
1526+
{
1527+
factory.AddProvider(_provider);
1528+
}
1529+
}
14791530
}
14801531
}

0 commit comments

Comments
 (0)