internal async Task <MethodInfo> GetFunctionTargetAsync(bool isInvocation = false) { try { return(await _functionLoader.GetFunctionTargetAsync().ConfigureAwait(false)); } catch (CompilationErrorException exc) { // on the invocation path we want to log detailed logs and all compilation diagnostics var properties = isInvocation ? null : PrimaryHostLogProperties; FunctionLogger.Log(LogLevel.Error, 0, properties, exc, (state, ex) => "Function compilation error"); TraceCompilationDiagnostics(exc.Diagnostics, LogTargets.User, isInvocation); throw; } catch (CompilationServiceException) { const string message = "Compilation service error"; FunctionLogger.LogError(message); // Compiler errors are often sporadic, so we'll attempt to reset the loader here to avoid // caching the compiler error and leaving the function hopelessly broken if (++_compilerErrorCount < 3) { _functionLoader.Reset(); const string resetMessage = "Function loader reset. Failed compilation result will not be cached."; FunctionLogger.LogError(resetMessage); } throw; } }
internal void TraceCompilationDiagnostics(ImmutableArray <Diagnostic> diagnostics, LogTargets logTarget = LogTargets.All, bool isInvocation = false) { if (logTarget == LogTargets.None) { return; } // build the log state based on inputs Dictionary <string, object> logState = new Dictionary <string, object>(); if (!isInvocation) { // generally we only want to trace compilation diagnostics on the single primary // host, to avoid duplicate log statements in the case of file save operations. // however if the function is being invoked, we always want to output detailed // information. logState.Add(ScriptConstants.LogPropertyPrimaryHostKey, true); } if (!logTarget.HasFlag(LogTargets.User)) { logState.Add(ScriptConstants.LogPropertyIsSystemLogKey, true); } else if (!logTarget.HasFlag(LogTargets.System)) { logState.Add(ScriptConstants.LogPropertyIsUserLogKey, true); } // log the diagnostics foreach (var diagnostic in diagnostics.Where(d => !d.IsSuppressed)) { FunctionLogger.Log(diagnostic.Severity.ToLogLevel(), 0, logState, null, (s, e) => diagnostic.ToString()); } // log structured logs if (Host.InDebugMode && (Host.IsPrimary || isInvocation)) { Host.EventManager.Publish(new StructuredLogEntryEvent(() => { var logEntry = new StructuredLogEntry("codediagnostic"); logEntry.AddProperty("functionName", Metadata.Name); logEntry.AddProperty("diagnostics", diagnostics.Select(d => { FileLinePositionSpan span = d.Location.GetMappedLineSpan(); return(new { code = d.Id, message = d.GetMessage(), source = Path.GetFileName(d.Location.SourceTree?.FilePath ?? span.Path ?? string.Empty), severity = d.Severity, startLineNumber = span.StartLinePosition.Line + 1, startColumn = span.StartLinePosition.Character + 1, endLine = span.EndLinePosition.Line + 1, endColumn = span.EndLinePosition.Character + 1, }); })); return(logEntry); })); } }
internal void TraceCompilationDiagnostics(ImmutableArray <Diagnostic> diagnostics, LogTargets logTarget = LogTargets.All) { if (logTarget == LogTargets.None) { return; } IDictionary <string, object> hostTraceProperties = PrimaryHostLogProperties; if (!logTarget.HasFlag(LogTargets.User)) { hostTraceProperties = PrimaryHostSystemLogProperties; } else if (!logTarget.HasFlag(LogTargets.System)) { hostTraceProperties = PrimaryHostUserLogProperties; } foreach (var diagnostic in diagnostics.Where(d => !d.IsSuppressed)) { FunctionLogger.Log(diagnostic.Severity.ToLogLevel(), 0, hostTraceProperties, null, (s, e) => diagnostic.ToString()); } if (Host.InDebugMode && Host.IsPrimary) { Host.EventManager.Publish(new StructuredLogEntryEvent(() => { var logEntry = new StructuredLogEntry("codediagnostic"); logEntry.AddProperty("functionName", Metadata.Name); logEntry.AddProperty("diagnostics", diagnostics.Select(d => { FileLinePositionSpan span = d.Location.GetMappedLineSpan(); return(new { code = d.Id, message = d.GetMessage(), source = Path.GetFileName(d.Location.SourceTree?.FilePath ?? span.Path ?? string.Empty), severity = d.Severity, startLineNumber = span.StartLinePosition.Line + 1, startColumn = span.StartLinePosition.Character + 1, endLine = span.EndLinePosition.Line + 1, endColumn = span.EndLinePosition.Character + 1, }); })); return(logEntry); })); } }
protected internal void LogOnPrimaryHost(string message, LogLevel level, Exception exception = null) { IDictionary <string, object> properties = new Dictionary <string, object>(PrimaryHostLogProperties); FunctionLogger.Log(level, 0, properties, exception, (state, ex) => message); }