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; } TraceWriter traceWriter = LogInfo.TraceWriter; IDictionary <string, object> properties = PrimaryHostTraceProperties; if (!logTarget.HasFlag(LogTargets.User)) { traceWriter = Host.TraceWriter; properties = PrimaryHostSystemTraceProperties; } else if (!logTarget.HasFlag(LogTargets.System)) { properties = PrimaryHostUserTraceProperties; } foreach (var diagnostic in diagnostics.Where(d => !d.IsSuppressed)) { traceWriter.Trace(diagnostic.ToString(), diagnostic.Severity.ToTraceLevel(), properties); } 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); })); } }
public void MultiLineValues_ReturnsSingleLine() { string entryName = "testlog"; var logEntry = new StructuredLogEntry(entryName); logEntry.AddProperty("test", "multi\r\nline\r\nproperty"); logEntry.AddProperty("jobject", new JObject { { "prop1", "val1" }, { "prop2", "val2" } }); string result = logEntry.ToJsonLineString(); Assert.DoesNotContain("\n", result); }