public void Decorator_BeginEventWithParams_Called()
        {
            string eventName    = "blah";
            string functionName = "blah";
            string data         = "moreBlah";

            _metricsLogger.Setup(a => a.BeginEvent(eventName, functionName, data));
            _metricsLoggerDecorator.BeginEvent(eventName, functionName, data);
            _metricsLogger.Verify(a => a.BeginEvent(eventName, functionName, data), Times.Once());
            _metricsLogger.Reset();
        }
        private void StartFunction(FunctionInstanceLogEntry item)
        {
            if (_metadataManager.TryGetFunctionMetadata(item.LogName, out FunctionMetadata function))
            {
                var startedEvent = new FunctionStartedEvent(item.FunctionInstanceId, function);
                _metrics.BeginEvent(startedEvent);

                var invokeLatencyEvent = LogInvocationMetrics(function);
                item.Properties[Key] = (startedEvent, invokeLatencyEvent);
            }
            else
            {
                throw new InvalidOperationException($"Unable to load metadata for function '{item.LogName}'.");
            }
        }
Exemple #3
0
 public void Start()
 {
     startedEvent = new FunctionStartedEvent(_invocationId, _metadata);
     _metrics.BeginEvent(startedEvent);
     invokeLatencyEvent = FunctionInvokerBase.LogInvocationMetrics(_metrics, _metadata);
     _invocationStopWatch.Start();
 }
Exemple #4
0
        public override async Task Invoke(object[] parameters)
        {
            // TODO: Refactor common code for providers.
            object           input       = parameters[0];
            TraceWriter      traceWriter = (TraceWriter)parameters[1];
            Binder           binder      = (Binder)parameters[2];
            ExecutionContext functionExecutionContext = (ExecutionContext)parameters[3];
            string           invocationId             = functionExecutionContext.InvocationId.ToString();

            FunctionStartedEvent startedEvent = new FunctionStartedEvent(functionExecutionContext.InvocationId, Metadata);

            _metrics.BeginEvent(startedEvent);

            try
            {
                TraceWriter.Info(string.Format("Function started (Id={0})", invocationId));

                object convertedInput = ConvertInput(input);
                ApplyBindingData(convertedInput, binder);
                Dictionary <string, object> bindingData = binder.BindingData;
                bindingData["InvocationId"] = invocationId;

                Dictionary <string, string> environmentVariables = new Dictionary <string, string>();

                string functionInstanceOutputPath = Path.Combine(Path.GetTempPath(), "Functions", "Binding", invocationId);
                await ProcessInputBindingsAsync(convertedInput, functionInstanceOutputPath, binder, _inputBindings, _outputBindings, bindingData, environmentVariables);

                InitializeEnvironmentVariables(environmentVariables, functionInstanceOutputPath, input, _outputBindings, functionExecutionContext);

                PSDataCollection <ErrorRecord> errors = await InvokePowerShellScript(environmentVariables, traceWriter);

                await ProcessOutputBindingsAsync(functionInstanceOutputPath, _outputBindings, input, binder, bindingData);

                if (errors.Any())
                {
                    ErrorRecord error = errors.FirstOrDefault();
                    if (error != null)
                    {
                        throw new RuntimeException("PowerShell script error", error.Exception, error);
                    }
                }
                else
                {
                    TraceWriter.Info(string.Format("Function completed (Success, Id={0})", invocationId));
                }
            }
            catch (Exception)
            {
                startedEvent.Success = false;
                TraceWriter.Error(string.Format("Function completed (Failure, Id={0})", invocationId));
                throw;
            }
            finally
            {
                _metrics.EndEvent(startedEvent);
            }
        }
Exemple #5
0
        internal static object LogInvocationMetrics(IMetricsLogger metrics, FunctionMetadata metadata)
        {
            // log events for each of the binding types used
            foreach (var binding in metadata.Bindings)
            {
                string eventName = binding.IsTrigger ?
                                   string.Format(MetricEventNames.FunctionBindingTypeFormat, binding.Type) :
                                   string.Format(MetricEventNames.FunctionBindingTypeDirectionFormat, binding.Type, binding.Direction);
                metrics.LogEvent(eventName);
            }

            return(metrics.BeginEvent(MetricEventNames.FunctionInvokeLatency, metadata.Name));
        }
Exemple #6
0
        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);
            }
        }
Exemple #7
0
 public DisposableEvent(string eventName, string functionName, IMetricsLogger metricsLogger)
 {
     _metricEvent   = metricsLogger.BeginEvent(eventName, functionName);
     _metricsLogger = metricsLogger;
 }
Exemple #8
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();

            PopulateExecutionContext(functionExecutionContext);

            // These may not be present, so null is okay.
            TraceWriter functionTraceWriter = parameters.OfType <TraceWriter>().FirstOrDefault();
            Binder      binder       = parameters.OfType <Binder>().FirstOrDefault();
            ILogger     logger       = parameters.OfType <ILogger>().FirstOrDefault();
            string      invocationId = functionExecutionContext.InvocationId.ToString();

            var startedEvent = new FunctionStartedEvent(functionExecutionContext.InvocationId, Metadata);

            _metrics.BeginEvent(startedEvent);
            var invokeLatencyEvent  = LogInvocationMetrics(_metrics, Metadata);
            var invocationStopWatch = new Stopwatch();

            invocationStopWatch.Start();

            try
            {
                string startMessage = $"Function started (Id={invocationId})";
                TraceWriter.Info(startMessage);
                Logger?.LogInformation(startMessage);

                FunctionInvocationContext context = new FunctionInvocationContext
                {
                    ExecutionContext = functionExecutionContext,
                    Binder           = binder,
                    TraceWriter      = functionTraceWriter,
                    Logger           = logger
                };

                await InvokeCore(parameters, context);

                invocationStopWatch.Stop();
                LogFunctionResult(startedEvent, true, invocationId, invocationStopWatch.ElapsedMilliseconds);
            }
            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);
                }

                invocationStopWatch.Stop();
                LogFunctionResult(startedEvent, false, invocationId, invocationStopWatch.ElapsedMilliseconds);
                exInfo.Throw();
            }
            catch
            {
                invocationStopWatch.Stop();
                LogFunctionResult(startedEvent, false, invocationId, invocationStopWatch.ElapsedMilliseconds);
                throw;
            }
            finally
            {
                if (startedEvent != null)
                {
                    _metrics.EndEvent(startedEvent);
                }
                if (invokeLatencyEvent != null)
                {
                    _metrics.EndEvent(invokeLatencyEvent);
                }
            }
        }
        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.Info(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.Info(string.Format("Function completed (Success, Id={0})", invocationId));
            }
            catch
            {
                if (startedEvent != null)
                {
                    startedEvent.Success = false;
                    TraceWriter.Error(string.Format("Function completed (Failure, Id={0})", invocationId));
                }
                else
                {
                    TraceWriter.Error("Function completed (Failure)");
                }
                throw;
            }
            finally
            {
                if (startedEvent != null)
                {
                    _metrics.EndEvent(startedEvent);
                }
            }
        }
Exemple #10
0
 public DisposableEvent(string eventName, string functionName, IMetricsLogger metricsLogger)
 {
     _metricEvent   = metricsLogger.BeginEvent(eventName, functionName, $"{{\"IsStopwatchHighResolution:\" {Stopwatch.IsHighResolution}}}");
     _metricsLogger = metricsLogger;
 }
        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);
                }
            }
        }
 public DisposableEvent(string eventName, IMetricsLogger metricsLogger)
 {
     _metricEvent = metricsLogger.BeginEvent(eventName);
     _metricsLogger = metricsLogger;
 }
Exemple #13
0
        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.Info(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);

            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.Error(string.Format("Function completed (Failure, Id={0})", invocationId));

                string error = process.StandardError.ReadToEnd();
                throw new ApplicationException(error);
            }

            string output = process.StandardOutput.ReadToEnd();

            TraceWriter.Info(output);
            traceWriter.Info(output);

            await ProcessOutputBindingsAsync(functionInstanceOutputPath, _outputBindings, input, binder, bindingData);

            TraceWriter.Info(string.Format("Function completed (Success, Id={0})", invocationId));
        }
Exemple #14
0
        internal async Task ExecuteScriptAsync(string path, string arguments, object[] invocationParameters)
        {
            object           input       = invocationParameters[0];
            TraceWriter      traceWriter = (TraceWriter)invocationParameters[1];
            Binder           binder      = (Binder)invocationParameters[2];
            ExecutionContext functionExecutionContext = (ExecutionContext)invocationParameters[3];
            string           invocationId             = functionExecutionContext.InvocationId.ToString();

            FunctionStartedEvent startedEvent = new FunctionStartedEvent(functionExecutionContext.InvocationId, Metadata);

            _metrics.BeginEvent(startedEvent);

            try
            {
                TraceWriter.Info(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);

                object convertedInput = ConvertInput(input);
                ApplyBindingData(convertedInput, binder);
                Dictionary <string, object> bindingData = binder.BindingData;
                bindingData["InvocationId"] = invocationId;

                await ProcessInputBindingsAsync(convertedInput, functionInstanceOutputPath, binder, _inputBindings, _outputBindings, 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();

                string output = process.StandardOutput.ReadToEnd();
                TraceWriter.Info(output);
                traceWriter.Info(output);

                startedEvent.Success = process.ExitCode == 0;

                if (!startedEvent.Success)
                {
                    string error = process.StandardError.ReadToEnd();
                    throw new ApplicationException(error);
                }

                await ProcessOutputBindingsAsync(functionInstanceOutputPath, _outputBindings, input, binder, bindingData);

                TraceWriter.Info(string.Format("Function completed (Success, Id={0})", invocationId));
            }
            catch
            {
                startedEvent.Success = false;
                TraceWriter.Error(string.Format("Function completed (Failure, Id={0})", invocationId));
                throw;
            }
            finally
            {
                _metrics.EndEvent(startedEvent);
            }
        }
Exemple #15
0
 public DisposableEvent(string eventName, string functionName, IMetricsLogger metricsLogger)
 {
     _metricEvent   = metricsLogger.BeginEvent(eventName, functionName, Stopwatch.IsHighResolution ? @"{""IsStopwatchHighResolution"": True}" : @"{""IsStopwatchHighResolution"": False}");
     _metricsLogger = metricsLogger;
 }
Exemple #16
0
 public object BeginEvent(string eventName, string functionName = null, string data = null)
 {
     return(_metricsLogger.BeginEvent(eventName, functionName, data));
 }