private async Task ExecuteWithOutputLogsAsync(IFunctionInstance instance, IReadOnlyDictionary <string, IValueProvider> parameters, TextWriter consoleOutput, IFunctionOutputDefinition outputDefinition, IDictionary <string, ParameterLog> parameterLogCollector, CancellationToken cancellationToken) { IFunctionInvoker invoker = instance.Invoker; IReadOnlyDictionary <string, IWatcher> watches = CreateWatches(parameters); IRecurrentCommand updateParameterLogCommand = outputDefinition.CreateParameterLogUpdateCommand(watches, consoleOutput); using (ITaskSeriesTimer updateParameterLogTimer = StartParameterLogTimer(updateParameterLogCommand, _backgroundExceptionDispatcher)) { try { await ExecuteWithWatchersAsync(invoker, parameters, cancellationToken); if (updateParameterLogTimer != null) { // Stop the watches after calling IValueBinder.SetValue (it may do things that should show up in // the watches). // Also, IValueBinder.SetValue could also take a long time (flushing large caches), and so it's // useful to have watches still running. await updateParameterLogTimer.StopAsync(cancellationToken); } } finally { ValueWatcher.AddLogs(watches, parameterLogCollector); } } }
private async Task ExecuteWithLoggingAsync(IFunctionInstance instance, IReadOnlyDictionary <string, IValueProvider> parameters, TraceWriter trace, ILogger logger, IFunctionOutputDefinition outputDefinition, IDictionary <string, ParameterLog> parameterLogCollector, TraceLevel functionTraceLevel, CancellationTokenSource functionCancellationTokenSource) { IFunctionInvoker invoker = instance.Invoker; IReadOnlyDictionary <string, IWatcher> parameterWatchers = null; ITaskSeriesTimer updateParameterLogTimer = null; if (functionTraceLevel >= TraceLevel.Info) { parameterWatchers = CreateParameterWatchers(parameters); IRecurrentCommand updateParameterLogCommand = outputDefinition.CreateParameterLogUpdateCommand(parameterWatchers, trace, logger); updateParameterLogTimer = StartParameterLogTimer(updateParameterLogCommand, _exceptionHandler); } try { await ExecuteWithWatchersAsync(instance, parameters, trace, logger, functionCancellationTokenSource); if (updateParameterLogTimer != null) { // Stop the watches after calling IValueBinder.SetValue (it may do things that should show up in // the watches). // Also, IValueBinder.SetValue could also take a long time (flushing large caches), and so it's // useful to have watches still running. await updateParameterLogTimer.StopAsync(functionCancellationTokenSource.Token); } } finally { if (updateParameterLogTimer != null) { ((IDisposable)updateParameterLogTimer).Dispose(); } if (parameterWatchers != null) { ValueWatcher.AddLogs(parameterWatchers, parameterLogCollector); } } }