public static void FunctionStarted(FunctionStartedEvent startedEvent) { lock (functionActivityTrackerLockObject) { if (instance == null) { instance = new FunctionActivityTracker(); } instance.FunctionStarted(startedEvent); } }
public static void FunctionCompleted(FunctionStartedEvent completedEvent) { lock (functionActivityTrackerLockObject) { if (instance != null) { instance.FunctionCompleted(completedEvent); if (!instance.IsActive) { instance.StopEtwTaskAndRaiseFinishedEvent(); instance = null; } } } }
internal void FunctionCompleted(FunctionStartedEvent functionStartedEvent) { var functionStage = (functionStartedEvent.Success == false) ? ExecutionStage.Failed : ExecutionStage.Succeeded; long executionTimeInMS = (long)functionStartedEvent.Duration.TotalMilliseconds; var monitoringEvent = new FunctionMetrics(functionStartedEvent.FunctionMetadata.Name, functionStage, executionTimeInMS); _functionMetricsQueue.Enqueue(monitoringEvent); var key = GetDictionaryKey(functionStartedEvent.FunctionMetadata.Name, functionStartedEvent.InvocationId); if (_runningFunctions.ContainsKey(key)) { lock (_functionMetricEventLockObject) { if (_runningFunctions.ContainsKey(key)) { var functionInfo = _runningFunctions[key]; functionInfo.ExecutionStage = ExecutionStage.Finished; functionInfo.Success = functionStartedEvent.Success; var endTime = functionStartedEvent.Timestamp + functionStartedEvent.Duration; functionInfo.EndTime = functionStartedEvent.Timestamp + functionStartedEvent.Duration; RaiseFunctionMetricEvent(functionInfo, _runningFunctions.Keys.Count, endTime); _runningFunctions.Remove(key); } } } }
internal void FunctionStarted(FunctionStartedEvent startedEvent) { _totalExecutionCount++; var metricEventPerFunction = new FunctionMetrics(startedEvent.FunctionMetadata.Name, ExecutionStage.Started, 0); _functionMetricsQueue.Enqueue(metricEventPerFunction); var key = GetDictionaryKey(startedEvent.FunctionMetadata.Name, startedEvent.InvocationId); if (!_runningFunctions.ContainsKey(key)) { lock (_functionMetricEventLockObject) { if (!_runningFunctions.ContainsKey(key)) { _runningFunctions.Add(key, new RunningFunctionInfo(startedEvent.FunctionMetadata.Name, startedEvent.InvocationId, startedEvent.Timestamp, startedEvent.Success)); } } } }
internal void FunctionStarted(FunctionStartedEvent startedEvent) { lock (_functionActivityTrackerLockObject) { if (instance == null) { instance = new FunctionActivityTracker(_eventGenerator, _functionActivityFlushIntervalSeconds); } instance.FunctionStarted(startedEvent); } }
public override async Task Invoke(object[] parameters) { FunctionStartedEvent startedEvent = null; string invocationId = null; try { // Separate system parameters from the actual method parameters object[] originalParameters = parameters; MethodInfo function = await GetFunctionTargetAsync(); int actualParameterCount = function.GetParameters().Length; object[] systemParameters = parameters.Skip(actualParameterCount).ToArray(); parameters = parameters.Take(actualParameterCount).ToArray(); ExecutionContext functionExecutionContext = (ExecutionContext)systemParameters[0]; invocationId = functionExecutionContext.InvocationId.ToString(); startedEvent = new FunctionStartedEvent(functionExecutionContext.InvocationId, Metadata); _metrics.BeginEvent(startedEvent); TraceWriter.Verbose(string.Format("Function started (Id={0})", invocationId)); parameters = ProcessInputParameters(parameters); object functionResult = function.Invoke(null, parameters); // after the function executes, we have to copy values back into the original // array to ensure object references are maintained (since we took a copy above) for (int i = 0; i < parameters.Length; i++) { originalParameters[i] = parameters[i]; } if (functionResult is Task) { functionResult = await((Task)functionResult).ContinueWith(t => GetTaskResult(t)); } if (functionResult != null) { _resultProcessor(function, parameters, systemParameters, functionResult); } TraceWriter.Verbose(string.Format("Function completed (Success, Id={0})", invocationId)); } catch { if (startedEvent != null) { startedEvent.Success = false; TraceWriter.Verbose(string.Format("Function completed (Failure, Id={0})", invocationId)); } else { TraceWriter.Verbose("Function completed (Failure)"); } throw; } finally { if (startedEvent != null) { _metrics.EndEvent(startedEvent); } } }
public override async Task Invoke(object[] parameters) { object input = parameters[0]; TraceWriter traceWriter = (TraceWriter)parameters[1]; IBinderEx binder = (IBinderEx)parameters[2]; ExecutionContext functionExecutionContext = (ExecutionContext)parameters[3]; string invocationId = functionExecutionContext.InvocationId.ToString(); FunctionStartedEvent startedEvent = new FunctionStartedEvent(functionExecutionContext.InvocationId, Metadata); _metrics.BeginEvent(startedEvent); try { TraceWriter.Verbose(string.Format("Function started (Id={0})", invocationId)); var scriptExecutionContext = CreateScriptExecutionContext(input, traceWriter, TraceWriter, functionExecutionContext); Dictionary<string, string> bindingData = GetBindingData(input, binder, _inputBindings, _outputBindings); bindingData["InvocationId"] = invocationId; scriptExecutionContext["bindingData"] = bindingData; await ProcessInputBindingsAsync(binder, scriptExecutionContext, bindingData); object functionResult = await ScriptFunc(scriptExecutionContext); await ProcessOutputBindingsAsync(_outputBindings, input, binder, bindingData, scriptExecutionContext, functionResult); TraceWriter.Verbose(string.Format("Function completed (Success, Id={0})", invocationId)); } catch { startedEvent.Success = false; TraceWriter.Verbose(string.Format("Function completed (Failure, Id={0})", invocationId)); throw; } finally { _metrics.EndEvent(startedEvent); } }
internal async Task ExecuteScriptAsync(string path, string arguments, object[] invocationParameters) { object input = invocationParameters[0]; TraceWriter traceWriter = (TraceWriter)invocationParameters[1]; IBinderEx binder = (IBinderEx)invocationParameters[2]; ExecutionContext functionExecutionContext = (ExecutionContext)invocationParameters[3]; string invocationId = functionExecutionContext.InvocationId.ToString(); FunctionStartedEvent startedEvent = new FunctionStartedEvent(functionExecutionContext.InvocationId, Metadata); _metrics.BeginEvent(startedEvent); // perform any required input conversions object convertedInput = input; if (input != null) { HttpRequestMessage request = input as HttpRequestMessage; if (request != null) { // TODO: Handle other content types? (E.g. byte[]) if (request.Content != null && request.Content.Headers.ContentLength > 0) { convertedInput = ((HttpRequestMessage)input).Content.ReadAsStringAsync().Result; } } } TraceWriter.Verbose(string.Format("Function started (Id={0})", invocationId)); string workingDirectory = Path.GetDirectoryName(_scriptFilePath); string functionInstanceOutputPath = Path.Combine(Path.GetTempPath(), "Functions", "Binding", invocationId); Dictionary<string, string> environmentVariables = new Dictionary<string, string>(); InitializeEnvironmentVariables(environmentVariables, functionInstanceOutputPath, input, _outputBindings, functionExecutionContext); Dictionary<string, string> bindingData = GetBindingData(convertedInput, binder, _inputBindings, _outputBindings); bindingData["InvocationId"] = invocationId; await ProcessInputBindingsAsync(convertedInput, functionInstanceOutputPath, binder, bindingData, environmentVariables); // TODO // - put a timeout on how long we wait? // - need to periodically flush the standard out to the TraceWriter Process process = CreateProcess(path, workingDirectory, arguments, environmentVariables); process.Start(); process.WaitForExit(); bool failed = process.ExitCode != 0; startedEvent.Success = !failed; _metrics.EndEvent(startedEvent); if (failed) { startedEvent.Success = false; TraceWriter.Verbose(string.Format("Function completed (Failure, Id={0})", invocationId)); string error = process.StandardError.ReadToEnd(); throw new ApplicationException(error); } string output = process.StandardOutput.ReadToEnd(); TraceWriter.Verbose(output); traceWriter.Verbose(output); await ProcessOutputBindingsAsync(functionInstanceOutputPath, _outputBindings, input, binder, bindingData); TraceWriter.Verbose(string.Format("Function completed (Success, Id={0})", invocationId)); }
private void LogFunctionFailed(FunctionStartedEvent startedEvent, string resultString, string invocationId) { if (startedEvent != null) { startedEvent.Success = false; } TraceWriter.Error($"Function completed ({resultString}, Id={invocationId ?? "0"})"); }
public async Task Invoke(object[] parameters) { // We require the ExecutionContext, so this will throw if one is not found. ExecutionContext functionExecutionContext = parameters.OfType<ExecutionContext>().First(); // These may not be present, so null is okay. TraceWriter functionTraceWriter = parameters.OfType<TraceWriter>().FirstOrDefault(); Binder binder = parameters.OfType<Binder>().FirstOrDefault(); string invocationId = functionExecutionContext.InvocationId.ToString(); FunctionStartedEvent startedEvent = new FunctionStartedEvent(functionExecutionContext.InvocationId, Metadata); _metrics.BeginEvent(startedEvent); LogInvocationMetrics(_metrics, Metadata.Bindings); try { TraceWriter.Info($"Function started (Id={invocationId})"); FunctionInvocationContext context = new FunctionInvocationContext { ExecutionContext = functionExecutionContext, Binder = binder, TraceWriter = functionTraceWriter }; await InvokeCore(parameters, context); TraceWriter.Info($"Function completed (Success, Id={invocationId})"); } catch (AggregateException ex) { ExceptionDispatchInfo exInfo = null; // If there's only a single exception, rethrow it by itself Exception singleEx = ex.Flatten().InnerExceptions.SingleOrDefault(); if (singleEx != null) { exInfo = ExceptionDispatchInfo.Capture(singleEx); } else { exInfo = ExceptionDispatchInfo.Capture(ex); } LogFunctionFailed(startedEvent, "Failure", invocationId); exInfo.Throw(); } catch { LogFunctionFailed(startedEvent, "Failure", invocationId); throw; } finally { if (startedEvent != null) { _metrics.EndEvent(startedEvent); } } }
internal void FunctionCompleted(FunctionStartedEvent completedEvent) { if (runningFunctionCount > 0) { runningFunctionCount--; } var functionStage = (completedEvent.Success == false) ? ExecutionStage.Failed : ExecutionStage.Succeeded; long executionTimeInMS = (long)completedEvent.EndTime.Subtract(completedEvent.StartTime).TotalMilliseconds; var monitoringEvent = new FunctionMetrics(completedEvent.FunctionMetadata.Name, functionStage, executionTimeInMS); functionMetricsQueue.Enqueue(monitoringEvent); }
internal void FunctionStarted(FunctionStartedEvent startedEvent) { totalExecutionCount++; runningFunctionCount++; var metricEventPerFunction = new FunctionMetrics(startedEvent.FunctionMetadata.Name, ExecutionStage.Started, 0); functionMetricsQueue.Enqueue(metricEventPerFunction); }