コード例 #1
0
        private void HandleHostError(Microsoft.Azure.WebJobs.Extensions.TraceFilter traceFilter)
        {
            foreach (TraceEvent traceEvent in traceFilter.Events)
            {
                if (traceEvent.Exception is FunctionInvocationException)
                {
                    // For all function invocation events, we notify the invoker so it can
                    // log the error as needed to its function specific logs.
                    FunctionInvocationException invocationException = traceEvent.Exception as FunctionInvocationException;
                    NotifyInvoker(invocationException.MethodName, invocationException);
                }
                else if (traceEvent.Exception is FunctionIndexingException)
                {
                    // For all startup time indexing errors, we accumulate them per function
                    FunctionIndexingException indexingException = traceEvent.Exception as FunctionIndexingException;
                    string formattedError = Utility.FlattenException(indexingException);
                    AddFunctionError(indexingException.MethodName, formattedError);

                    // Also notify the invoker so the error can also be written to the function
                    // log file
                    NotifyInvoker(indexingException.MethodName, indexingException);

                    // Mark the error as handled so indexing will continue
                    indexingException.Handled = true;
                }
            }
        }
コード例 #2
0
        public async Task IndexingExceptions_CanBeHandledByLogger()
        {
            FunctionErrorLogger errorLogger = new FunctionErrorLogger("TestCategory");

            Mock <ILoggerProvider> mockProvider = new Mock <ILoggerProvider>(MockBehavior.Strict);

            mockProvider
            .Setup(m => m.CreateLogger(It.IsAny <string>()))
            .Returns(errorLogger);

            var builder = new HostBuilder()
                          .ConfigureDefaultTestHost <BindingErrorsProgram>(b =>
            {
                b.AddAzureStorage();
            })
                          .ConfigureLogging(logging =>
            {
                logging.AddProvider(mockProvider.Object);
            });

            var host = builder.Build();

            using (host)
            {
                await host.StartAsync();

                // verify the handled binding error
                FunctionIndexingException fex = errorLogger.Errors.SingleOrDefault() as FunctionIndexingException;
                Assert.True(fex.Handled);
                Assert.Equal("BindingErrorsProgram.Invalid", fex.MethodName);

                // verify that the binding error was logged
                Assert.Equal(5, errorLogger.GetLogMessages().Count);

                // Skip validating the initial 'Starting JobHost' message.

                LogMessage logMessage = errorLogger.GetLogMessages()[1];
                Assert.Equal("Error indexing method 'BindingErrorsProgram.Invalid'", logMessage.FormattedMessage);
                Assert.Same(fex, logMessage.Exception);
                Assert.Equal("Invalid container name: invalid$=+1", logMessage.Exception.InnerException.Message);

                logMessage = errorLogger.GetLogMessages()[2];
                Assert.Equal("Function 'BindingErrorsProgram.Invalid' failed indexing and will be disabled.", logMessage.FormattedMessage);

                // verify that the valid function was still indexed
                logMessage = errorLogger.GetLogMessages()[3];
                Assert.True(logMessage.FormattedMessage.Contains("Found the following functions"));
                Assert.True(logMessage.FormattedMessage.Contains("BindingErrorsProgram.Valid"));

                // verify that the job host was started successfully
                logMessage = errorLogger.GetLogMessages()[4];
                Assert.Equal("Job host started", logMessage.FormattedMessage);

                await host.StopAsync();
            }
        }
コード例 #3
0
        public void IndexingExceptions_CanBeHandledByLogger()
        {
            JobHostConfiguration config = new JobHostConfiguration();

            config.TypeLocator = new FakeTypeLocator(typeof(BindingErrorsProgram));
            FunctionErrorLogger errorLogger = new FunctionErrorLogger("TestCategory");

            config.AddService <IWebJobsExceptionHandler>(new TestExceptionHandler());

            Mock <ILoggerProvider> mockProvider = new Mock <ILoggerProvider>(MockBehavior.Strict);

            mockProvider
            .Setup(m => m.CreateLogger(It.IsAny <string>()))
            .Returns(errorLogger);

            ILoggerFactory factory = new LoggerFactory();

            factory.AddProvider(mockProvider.Object);

            config.LoggerFactory = factory;

            JobHost host = new JobHost(config);

            host.Start();

            // verify the handled binding error
            FunctionIndexingException fex = errorLogger.Errors.SingleOrDefault() as FunctionIndexingException;

            Assert.True(fex.Handled);
            Assert.Equal("BindingErrorsProgram.Invalid", fex.MethodName);

            // verify that the binding error was logged
            var messages = errorLogger.GetLogMessages();

            Assert.Equal(5, messages.Count);
            LogMessage logMessage = messages.ElementAt(0);

            Assert.Equal("Error indexing method 'BindingErrorsProgram.Invalid'", logMessage.FormattedMessage);
            Assert.Same(fex, logMessage.Exception);
            Assert.Equal("Invalid container name: invalid$=+1", logMessage.Exception.InnerException.Message);
            logMessage = messages.ElementAt(1);
            Assert.Equal("Function 'BindingErrorsProgram.Invalid' failed indexing and will be disabled.", logMessage.FormattedMessage);
            Assert.Equal(Extensions.Logging.LogLevel.Warning, logMessage.Level);

            // verify that the valid function was still indexed
            logMessage = messages.ElementAt(2);
            Assert.True(logMessage.FormattedMessage.Contains("Found the following functions"));
            Assert.True(logMessage.FormattedMessage.Contains("BindingErrorsProgram.Valid"));

            // verify that the job host was started successfully
            logMessage = messages.ElementAt(4);
            Assert.Equal("Job host started", logMessage.FormattedMessage);

            host.Stop();
            host.Dispose();
        }
コード例 #4
0
            public override void Trace(TraceEvent traceEvent)
            {
                FunctionIndexingException fex = traceEvent.Exception as FunctionIndexingException;

                if (fex != null)
                {
                    fex.Handled = true;
                    Errors.Add(fex);
                }
            }
コード例 #5
0
        public void Queue_IfBoundToIAsyncCollectorInt_NotSupported()
        {
            // Act
            FunctionIndexingException ex = Assert.ThrowsAsync <FunctionIndexingException>(() =>
            {
                return(CallAsync(typeof(QueueNotSupportedProgram), "BindToICollectorInt"));
            });

            // Assert
            Assert.AreEqual("Primitive types are not supported.", ex.InnerException.Message);
        }
コード例 #6
0
            public override void Log <TState>(Microsoft.Extensions.Logging.LogLevel logLevel, EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter)
            {
                FunctionIndexingException fex = exception as FunctionIndexingException;

                if (fex != null)
                {
                    fex.Handled = true;
                    Errors.Add(fex);
                }

                base.Log(logLevel, eventId, state, exception, formatter);
            }
コード例 #7
0
        public void IndexMethod_IfMethodReturnsTaskOfTResult_Throws()
        {
            // Arrange
            IFunctionIndexCollector index   = CreateDummyFunctionIndex();
            FunctionIndexer         product = CreateProductUnderTest();

            // Act & Assert
            FunctionIndexingException exception = Assert.Throws <FunctionIndexingException>(
                () => product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod("ReturnGenericTask"), index,
                                               CancellationToken.None).GetAwaiter().GetResult());
            InvalidOperationException innerException = exception.InnerException as InvalidOperationException;

            Assert.NotNull(innerException);
            Assert.Equal("Functions must return Task or void.", innerException.Message);
        }
コード例 #8
0
        private void HandleHostError(Exception exception)
        {
            if (exception == null)
            {
                throw new ArgumentNullException("exception");
            }

            // First, ensure that we've logged to the host log
            // Also ensure we flush immediately to ensure any buffered logs
            // are written
            TraceWriter.Error("A ScriptHost error has occurred", exception);
            TraceWriter.Flush();

            if (exception is FunctionInvocationException)
            {
                // For all function invocation errors, we notify the invoker so it can
                // log the error as needed to its function specific logs.
                FunctionInvocationException invocationException = exception as FunctionInvocationException;
                NotifyInvoker(invocationException.MethodName, invocationException);
            }
            else if (exception is FunctionIndexingException)
            {
                // For all startup time indexing errors, we accumulate them per function
                FunctionIndexingException indexingException = exception as FunctionIndexingException;
                string formattedError = Utility.FlattenException(indexingException);
                AddFunctionError(indexingException.MethodName, formattedError);

                // Also notify the invoker so the error can also be written to the function
                // log file
                NotifyInvoker(indexingException.MethodName, indexingException);

                // Mark the error as handled so indexing will continue
                indexingException.Handled = true;
            }
            else
            {
                // See if we can identify which function caused the error, and if we can
                // log the error as needed to its function specific logs.
                FunctionDescriptor function = null;
                if (TryGetFunctionFromException(Functions, exception, out function))
                {
                    NotifyInvoker(function.Name, exception);
                }
            }
        }
コード例 #9
0
        public void IndexingExceptions_CanBeHandledByTraceWriter()
        {
            JobHostConfiguration config      = new JobHostConfiguration();
            TestTraceWriter      traceWriter = new TestTraceWriter(TraceLevel.Verbose);

            config.Tracing.Tracers.Add(traceWriter);
            config.TypeLocator = new FakeTypeLocator(typeof(BindingErrorsProgram));

            FunctionErrorTraceWriter errorTraceWriter = new FunctionErrorTraceWriter(TraceLevel.Error);

            config.Tracing.Tracers.Add(errorTraceWriter);

            JobHost host = new JobHost(config);

            host.Start();

            // verify the handled binding error
            FunctionIndexingException fex = errorTraceWriter.Errors.SingleOrDefault() as FunctionIndexingException;

            Assert.True(fex.Handled);
            Assert.Equal("BindingErrorsProgram.Invalid", fex.MethodName);

            // verify that the binding error was logged
            Assert.Equal(3, traceWriter.Traces.Count);
            TraceEvent traceEvent = traceWriter.Traces[0];

            Assert.Equal("Error indexing method 'BindingErrorsProgram.Invalid'", traceEvent.Message);
            Assert.Same(fex, traceEvent.Exception);
            Assert.Equal("Invalid container name: invalid$=+1", traceEvent.Exception.InnerException.Message);

            // verify that the valid function was still indexed
            traceEvent = traceWriter.Traces[1];
            Assert.True(traceEvent.Message.Contains("Found the following functions"));
            Assert.True(traceEvent.Message.Contains("BindingErrorsProgram.Valid"));

            // verify that the job host was started successfully
            traceEvent = traceWriter.Traces[2];
            Assert.Equal("Job host started", traceEvent.Message);

            host.Stop();
            host.Dispose();
        }
コード例 #10
0
        public void IndexMethod_Throws_IfMethodHasUnboundOutParameterWithJobsAttribute()
        {
            // Arrange
            Mock <IFunctionIndexCollector> indexMock = new Mock <IFunctionIndexCollector>(MockBehavior.Strict);
            int calls = 0;

            indexMock
            .Setup(i => i.Add(It.IsAny <IFunctionDefinition>(), It.IsAny <FunctionDescriptor>(), It.IsAny <MethodInfo>()))
            .Callback(() => calls++);
            IFunctionIndexCollector index   = indexMock.Object;
            FunctionIndexer         product = CreateProductUnderTest();

            // Act & Assert
            FunctionIndexingException exception = Assert.Throws <FunctionIndexingException>(
                () => product.IndexMethodAsync(typeof(FunctionIndexerTests).GetMethod("FailIndexing"), index,
                                               CancellationToken.None).GetAwaiter().GetResult());
            InvalidOperationException innerException = exception.InnerException as InvalidOperationException;

            Assert.NotNull(innerException);
            Assert.Equal($"Cannot bind parameter 'parsed' to type Foo&. Make sure the parameter Type is supported by the binding. {Resource.ExtensionInitializationMessage}", innerException.Message);
        }
コード例 #11
0
ファイル: HostStartTests.cs プロジェクト: sravan251/Azure
        public void Queue_IfNameIsInvalid_ThrowsDuringIndexing()
        {
            IStorageAccount account = CreateFakeStorageAccount();
            TaskCompletionSource <object> backgroundTaskSource = new TaskCompletionSource <object>();
            IServiceProvider serviceProvider = FunctionalTest.CreateServiceProviderForCallFailure(account,
                                                                                                  typeof(InvalidQueueNameProgram), backgroundTaskSource);

            using (JobHost host = new JobHost(serviceProvider))
            {
                // Act & Assert
                FunctionIndexingException exception = Assert.Throws <FunctionIndexingException>(() => host.Start());
                Assert.Equal("Error indexing method 'InvalidQueueNameProgram.Invalid'", exception.Message);
                Exception innerException = exception.InnerException;
                Assert.IsType <ArgumentException>(innerException);
                ArgumentException argumentException = (ArgumentException)innerException;
                Assert.Equal("name", argumentException.ParamName);
                string expectedMessage = String.Format(CultureInfo.InvariantCulture,
                                                       "The dash (-) character may not be the first or last letter - \"-illegalname-\"{0}Parameter " +
                                                       "name: name", Environment.NewLine);
                Assert.Equal(expectedMessage, innerException.Message);
                Assert.Equal(TaskStatus.WaitingForActivation, backgroundTaskSource.Task.Status);
            }
        }