public async Task GetMetrics_HandlesExceptions()
        {
            // MessagingEntityNotFoundException
            _mockMessagingProvider
            .Setup(p => p.CreateBatchMessageReceiver(_entityPath, _testConnection))
            .Throws(new ServiceBusException("", reason: ServiceBusFailureReason.MessagingEntityNotFound));
            ServiceBusListener listener = new ServiceBusListener(_functionId, EntityType.Queue, _entityPath, false, _mockExecutor.Object, _serviceBusOptions,
                                                                 _mockServiceBusAccount.Object, _mockMessagingProvider.Object, _loggerFactory, false);

            var metrics = await((ServiceBusScaleMonitor)listener.GetMonitor()).GetMetricsAsync();

            Assert.AreEqual(0, metrics.PartitionCount);
            Assert.AreEqual(0, metrics.MessageCount);
            Assert.AreEqual(TimeSpan.FromSeconds(0), metrics.QueueTime);
            Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

            var warning = _loggerProvider.GetAllLogMessages().Single(p => p.Level == LogLevel.Warning);

            Assert.AreEqual($"ServiceBus queue '{_entityPath}' was not found.", warning.FormattedMessage);
            _loggerProvider.ClearAllLogMessages();

            // UnauthorizedAccessException
            _mockMessagingProvider
            .Setup(p => p.CreateBatchMessageReceiver(_entityPath, _testConnection))
            .Throws(new UnauthorizedAccessException(""));
            listener = new ServiceBusListener(_functionId, EntityType.Queue, _entityPath, false, _mockExecutor.Object, _serviceBusOptions,
                                              _mockServiceBusAccount.Object, _mockMessagingProvider.Object, _loggerFactory, false);

            metrics = await((ServiceBusScaleMonitor)listener.GetMonitor()).GetMetricsAsync();

            Assert.AreEqual(0, metrics.PartitionCount);
            Assert.AreEqual(0, metrics.MessageCount);
            Assert.AreEqual(TimeSpan.FromSeconds(0), metrics.QueueTime);
            Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

            warning = _loggerProvider.GetAllLogMessages().Single(p => p.Level == LogLevel.Warning);
            Assert.AreEqual($"Connection string does not have Manage claim for queue '{_entityPath}'. Failed to get queue description to derive queue length metrics. " +
                            $"Falling back to using first message enqueued time.",
                            warning.FormattedMessage);
            _loggerProvider.ClearAllLogMessages();

            // Generic Exception
            _mockMessagingProvider
            .Setup(p => p.CreateBatchMessageReceiver(_entityPath, _testConnection))
            .Throws(new Exception("Uh oh"));
            listener = new ServiceBusListener(_functionId, EntityType.Queue, _entityPath, false, _mockExecutor.Object, _serviceBusOptions,
                                              _mockServiceBusAccount.Object, _mockMessagingProvider.Object, _loggerFactory, false);

            metrics = await((ServiceBusScaleMonitor)listener.GetMonitor()).GetMetricsAsync();

            Assert.AreEqual(0, metrics.PartitionCount);
            Assert.AreEqual(0, metrics.MessageCount);
            Assert.AreEqual(TimeSpan.FromSeconds(0), metrics.QueueTime);
            Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

            warning = _loggerProvider.GetAllLogMessages().Single(p => p.Level == LogLevel.Warning);
            Assert.AreEqual($"Error querying for Service Bus queue scale status: Uh oh", warning.FormattedMessage);
        }
Example #2
0
        public async Task Starting_MultipleJobhostChannels_Succeeds()
        {
            _testLoggerProvider.ClearAllLogMessages();
            int expectedProcessCount = 3;
            RpcFunctionInvocationDispatcher functionDispatcher = GetTestFunctionDispatcher(expectedProcessCount);
            await functionDispatcher.InitializeAsync(GetTestFunctionsList(RpcWorkerConstants.NodeLanguageWorkerName));

            var finalChannelCount = await WaitForJobhostWorkerChannelsToStartup(functionDispatcher, expectedProcessCount);

            Assert.Equal(expectedProcessCount, finalChannelCount);

            VerifyStartIntervals(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15));
        }
Example #3
0
        public async Task CreateTriggerMetrics_HandlesExceptions()
        {
            // StorageException
            _mockBlobContainer
            .Setup(c => c.GetBlobClient(IsAny <string>()))
            .Throws(new RequestFailedException(404, "Uh oh"));

            var partitionInfo = new List <PartitionProperties>
            {
                new TestPartitionProperties()
            };

            var metrics = await _scaleMonitor.CreateTriggerMetrics(partitionInfo, true);

            Assert.AreEqual(1, metrics.PartitionCount);
            Assert.AreEqual(0, metrics.EventCount);
            Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

            var warning         = _loggerProvider.GetAllLogMessages().Single(p => p.Level == Extensions.Logging.LogLevel.Warning);
            var expectedWarning = $"Function '{_functionId}': Unable to deserialize partition or lease info with the following errors: " +
                                  $"Checkpoint file data could not be found for blob on Partition: '0', EventHub: '{_eventHubName}', " +
                                  $"'{_consumerGroup}'. Error: Uh oh";

            Assert.AreEqual(expectedWarning, warning.FormattedMessage);
            _loggerProvider.ClearAllLogMessages();

            // Generic Exception
            _mockBlobContainer
            .Setup(c => c.GetBlobClient(IsAny <string>()))
            .Throws(new Exception("Uh oh"));

            partitionInfo = new List <PartitionProperties>
            {
                new TestPartitionProperties()
            };

            metrics = await _scaleMonitor.CreateTriggerMetrics(partitionInfo, true);

            Assert.AreEqual(1, metrics.PartitionCount);
            Assert.AreEqual(0, metrics.EventCount);
            Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

            warning         = _loggerProvider.GetAllLogMessages().Single(p => p.Level == Extensions.Logging.LogLevel.Warning);
            expectedWarning = $"Function '{_functionId}': Unable to deserialize partition or lease info with the following errors: " +
                              $"Encountered exception while checking for last checkpointed sequence number for blob on Partition: '0', " +
                              $"EventHub: '{_eventHubName}', Consumer Group: '{_consumerGroup}'. Error: Uh oh";
            Assert.AreEqual(expectedWarning, warning.FormattedMessage);
            _loggerProvider.ClearAllLogMessages();
        }
        public async Task ListCheckpointsAsync_LogsOnInvalidCheckpoints()
        {
            var testLoggerProvider = new TestLoggerProvider();
            Mock <BlobContainerClient> containerClientMock = new Mock <BlobContainerClient>(MockBehavior.Strict);

            containerClientMock.Setup(c => c.GetBlobsAsync(It.IsAny <BlobTraits>(), It.IsAny <BlobStates>(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .Returns(AsyncPageable <BlobItem> .FromPages(new[]
            {
                Page <BlobItem> .FromValues(new[]
                {
                    BlobsModelFactory.BlobItem("testnamespace/testeventhubname/testconsumergroup/checkpoint/0", false, BlobsModelFactory.BlobItemProperties(false), metadata: new Dictionary <string, string>())
                }, null, Mock.Of <Response>())
            }));

            BlobsCheckpointStore store = new BlobsCheckpointStore(
                containerClientMock.Object,
                new BasicRetryPolicy(new EventHubsRetryOptions()),
                _functionId,
                testLoggerProvider.CreateLogger("TestLogger")
                );

            await store.ListCheckpointsAsync(_namespace, _eventHubName, _consumerGroup, CancellationToken.None);

            var warning         = testLoggerProvider.GetAllLogMessages().Single(p => p.Level == Extensions.Logging.LogLevel.Warning);
            var expectedWarning = "Function 'EventHubsTriggerFunction': An invalid checkpoint was found for partition: '0' of " +
                                  "FullyQualifiedNamespace: 'TestNamespace'; EventHubName: 'TestEventHubName'; ConsumerGroup: 'TestConsumerGroup'.  " +
                                  "This checkpoint is not valid and will be ignored.";

            Assert.AreEqual(expectedWarning, warning.FormattedMessage);
            testLoggerProvider.ClearAllLogMessages();
        }
        public async Task ValidateHostIdUsageAsync_ExistingHostIdInfoMatches_Succeeds()
        {
            await ClearHostIdInfoAsync();

            HostIdValidator.HostIdInfo hostIdInfo = new HostIdValidator.HostIdInfo
            {
                Hostname = _testHostname
            };
            await _hostIdValidator.WriteHostIdAsync(_testHostId, hostIdInfo, _blobContainerClient);

            _loggerProvider.ClearAllLogMessages();

            await _hostIdValidator.ValidateHostIdUsageAsync(_testHostId);

            var logs = _loggerProvider.GetAllLogMessages();

            Assert.Empty(logs);
        }
Example #6
0
        public async Task InvalidStorageConnection_Handled()
        {
            var configuration = new ConfigurationBuilder().Build();

            Assert.Null(configuration.GetWebJobsConnectionString(ConnectionStringNames.Storage));

            var            options       = new ScaleOptions();
            ILoggerFactory loggerFactory = new LoggerFactory();

            loggerFactory.AddProvider(_loggerProvider);
            var localRepository = new TableStorageScaleMetricsRepository(configuration, _hostIdProviderMock.Object, new OptionsWrapper <ScaleOptions>(options), loggerFactory, new TestEnvironment());

            var monitor1 = new TestScaleMonitor1();
            var monitor2 = new TestScaleMonitor2();
            var monitor3 = new TestScaleMonitor3();
            var monitors = new IScaleMonitor[] { monitor1, monitor2, monitor3 };
            var result   = await localRepository.ReadMetricsAsync(monitors);

            Assert.Empty(result);

            var logs = _loggerProvider.GetAllLogMessages();

            Assert.Single(logs);
            Assert.Equal("Azure Storage connection string is empty or invalid. Unable to read/write scale metrics.", logs[0].FormattedMessage);

            _loggerProvider.ClearAllLogMessages();
            Dictionary <IScaleMonitor, ScaleMetrics> metricsMap = new Dictionary <IScaleMonitor, ScaleMetrics>();

            metricsMap.Add(monitor1, new TestScaleMetrics1 {
                Count = 10
            });
            metricsMap.Add(monitor2, new TestScaleMetrics2 {
                Num = 50
            });
            metricsMap.Add(monitor3, new TestScaleMetrics3 {
                Length = 100
            });
            await localRepository.WriteMetricsAsync(metricsMap);
        }
        public async Task StartAssignment_AppliesAssignmentContext()
        {
            var envValue = new
            {
                Name  = Path.GetTempFileName().Replace(".", string.Empty),
                Value = Guid.NewGuid().ToString()
            };

            _settingsManager.SetSetting(EnvironmentSettingNames.AzureWebsitePlaceholderMode, "1");
            WebScriptHostManager.ResetStandbyMode();
            var context = new HostAssignmentContext
            {
                Environment = new Dictionary <string, string>
                {
                    { envValue.Name, envValue.Value }
                }
            };
            bool result = _instanceManager.StartAssignment(context);

            Assert.True(result);
            Assert.True(WebScriptHostManager.InStandbyMode);

            // specialization is done in the background
            await Task.Delay(500);

            var value = Environment.GetEnvironmentVariable(envValue.Name);

            Assert.Equal(value, envValue.Value);

            // verify logs
            var logs = _loggerProvider.GetAllLogMessages().Select(p => p.FormattedMessage).ToArray();

            Assert.Collection(logs,
                              p => Assert.StartsWith("Starting Assignment", p),
                              p => Assert.StartsWith("Applying 1 app setting(s)", p),
                              p => Assert.StartsWith("Triggering specialization", p));

            // calling again should return false, since we're no longer
            // in placeholder mode
            _loggerProvider.ClearAllLogMessages();
            result = _instanceManager.StartAssignment(context);
            Assert.False(result);

            logs = _loggerProvider.GetAllLogMessages().Select(p => p.FormattedMessage).ToArray();
            Assert.Collection(logs,
                              p => Assert.StartsWith("Assign called while host is not in placeholder mode", p));
        }
        public void Synchronize_UpdatesValue()
        {
            _mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName)).Returns((string)null);
            _mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteName)).Returns((string)null);

            Assert.Equal(null, _hostNameProvider.Value);

            // no header present
            HttpRequest request = new DefaultHttpContext().Request;

            _hostNameProvider.Synchronize(request, _logger);
            Assert.Equal(null, _hostNameProvider.Value);

            // empty header value
            request = new DefaultHttpContext().Request;
            request.Headers.Add(ScriptConstants.AntaresDefaultHostNameHeader, string.Empty);
            _hostNameProvider.Synchronize(request, _logger);
            Assert.Equal(null, _hostNameProvider.Value);

            // host provided via header - expect update
            request = new DefaultHttpContext().Request;
            request.Headers.Add(ScriptConstants.AntaresDefaultHostNameHeader, "test.azurewebsites.net");
            _hostNameProvider.Synchronize(request, _logger);
            Assert.Equal("test.azurewebsites.net", _hostNameProvider.Value);
            var logs = _loggerProvider.GetAllLogMessages();

            Assert.Equal(1, logs.Count);
            Assert.Equal("HostName updated from '(null)' to 'test.azurewebsites.net'", logs[0].FormattedMessage);

            // no change in header value - no update expected
            _loggerProvider.ClearAllLogMessages();
            _hostNameProvider.Synchronize(request, _logger);
            Assert.Equal("test.azurewebsites.net", _hostNameProvider.Value);
            Assert.Equal("test.azurewebsites.net", _hostNameProvider.Value);
            logs = _loggerProvider.GetAllLogMessages();
            Assert.Equal(0, logs.Count);

            // another change - expect update
            request = new DefaultHttpContext().Request;
            request.Headers.Add(ScriptConstants.AntaresDefaultHostNameHeader, "test2.azurewebsites.net");
            _hostNameProvider.Synchronize(request, _logger);
            Assert.Equal("test2.azurewebsites.net", _hostNameProvider.Value);
            logs = _loggerProvider.GetAllLogMessages();
            Assert.Equal(1, logs.Count);
            Assert.Equal("HostName updated from 'test.azurewebsites.net' to 'test2.azurewebsites.net'", logs[0].FormattedMessage);
        }
        public LinuxContainerMetricsPublisherTests()
        {
            var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict);

            handlerMock.Protected().Setup <Task <HttpResponseMessage> >("SendAsync",
                                                                        ItExpr.IsAny <HttpRequestMessage>(),
                                                                        ItExpr.IsAny <CancellationToken>())
            .Callback <HttpRequestMessage, CancellationToken>((request, token) => ValidateRequest(request))
            .ReturnsAsync(new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK
            });

            _httpClient = new HttpClient(handlerMock.Object);

            var mockEnvironment = new Mock <IEnvironment>(MockBehavior.Strict);

            mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.ContainerName)).Returns(_containerName);
            mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.LinuxNodeIpAddress)).Returns(_testIpAddress);
            mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName)).Returns(_testHostName);
            mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.WebSiteHomeStampName)).Returns(_testStampName);
            mockEnvironment.Setup(p => p.GetEnvironmentVariable(EnvironmentSettingNames.WebSiteStampDeploymentId)).Returns(_testTenant);

            var websiteAuthEncryptionKey       = TestHelpers.GenerateKeyBytes();
            var websiteAuthEncryptionStringKey = TestHelpers.GenerateKeyHexString(websiteAuthEncryptionKey);

            Environment.SetEnvironmentVariable(EnvironmentSettingNames.WebSiteAuthEncryptionKey, websiteAuthEncryptionStringKey);

            _testLoggerProvider = new TestLoggerProvider();
            var loggerFactory = new LoggerFactory();

            loggerFactory.AddProvider(_testLoggerProvider);

            ILogger <LinuxContainerMetricsPublisher> logger = loggerFactory.CreateLogger <LinuxContainerMetricsPublisher>();
            var hostNameProvider = new HostNameProvider(mockEnvironment.Object);
            var standbyOptions   = new TestOptionsMonitor <StandbyOptions>(new StandbyOptions {
                InStandbyMode = true
            });

            _metricsPublisher = new LinuxContainerMetricsPublisher(mockEnvironment.Object, standbyOptions, logger, hostNameProvider, _httpClient);
            _testLoggerProvider.ClearAllLogMessages();
        }
Example #10
0
 public void StopAsync_LogListenerDetails()
 {
     try
     {
         Assert.DoesNotThrow(() => _listener.StopAsync(CancellationToken.None));
         Assert.NotNull(_loggerProvider.GetAllLogMessages()
                        .SingleOrDefault(x => x.FormattedMessage.StartsWith("Attempting to stop ServiceBus listener")));
         Assert.NotNull(_loggerProvider.GetAllLogMessages()
                        .SingleOrDefault(x => x.FormattedMessage.StartsWith("ServiceBus listener stopped")));
     }
     finally
     {
         _loggerProvider.ClearAllLogMessages();
     }
 }
Example #11
0
        public void PublishFunctionActivity_SendsRequestHeaders()
        {
            _metricsPublisher.Initialize();
            _metricsPublisher.AddFunctionExecutionActivity(
                _testFunctionActivity.FunctionName,
                _testFunctionActivity.InvocationId,
                _testFunctionActivity.Concurrency,
                _testFunctionActivity.ExecutionStage,
                _testFunctionActivity.IsSucceeded,
                _testFunctionActivity.ExecutionTimeSpanInMs,
                _testFunctionActivity.EventTimeStamp);

            Assert.Matches("Added function activity", _testLoggerProvider.GetAllLogMessages().Single().FormattedMessage);
            Assert.Equal(LogLevel.Debug, _testLoggerProvider.GetAllLogMessages().Single().Level);

            _testLoggerProvider.ClearAllLogMessages();

            _metricsPublisher.OnFunctionMetricsPublishTimer(null);
            _metricsPublisher.OnFunctionMetricsPublishTimer(null);
            Assert.Empty(_testLoggerProvider.GetAllLogMessages());
        }
        public void PublishFunctionActivity_SendsRequestHeaders()
        {
            _metricsPublisher.Initialize();
            _metricsPublisher.AddFunctionExecutionActivity(
                _testFunctionActivity.FunctionName,
                _testFunctionActivity.InvocationId,
                _testFunctionActivity.Concurrency,
                _testFunctionActivity.ExecutionStage.ToString(),
                _testFunctionActivity.IsSucceeded,
                _testFunctionActivity.ExecutionTimeSpanInMs,
                _testFunctionActivity.ExecutionId,
                _testFunctionActivity.EventTimeStamp,
                _testFunctionActivity.StartTime);

            Assert.Empty(_testLoggerProvider.GetAllLogMessages());

            _testLoggerProvider.ClearAllLogMessages();

            _metricsPublisher.OnFunctionMetricsPublishTimer(null);
            _metricsPublisher.OnFunctionMetricsPublishTimer(null);
            Assert.Empty(_testLoggerProvider.GetAllLogMessages());
        }
        public void GetCheckpointsAsync_LogsOnRequestErrors()
        {
            var testLoggerProvider = new TestLoggerProvider();
            Mock <BlobContainerClient> containerClientMock = new Mock <BlobContainerClient>(MockBehavior.Strict);

            containerClientMock.Setup(c => c.GetBlobClient(It.IsAny <string>()))
            .Throws(new RequestFailedException("Uh oh"));

            BlobCheckpointStoreInternal store = new BlobCheckpointStoreInternal(
                containerClientMock.Object,
                _functionId,
                testLoggerProvider.CreateLogger("TestLogger")
                );

            Assert.ThrowsAsync <RequestFailedException>(async() => await store.GetCheckpointAsync(_namespace, _eventHubName, _consumerGroup, _partitionId, CancellationToken.None));

            var warning         = testLoggerProvider.GetAllLogMessages().Single(p => p.Level == LogLevel.Warning);
            var expectedWarning = "Function 'EventHubsTriggerFunction': An exception occurred when retrieving a checkpoint for " +
                                  "FullyQualifiedNamespace: 'TestNamespace'; EventHubName: 'TestEventHubName'; ConsumerGroup: 'TestConsumerGroup'; PartitionId: '0'.";

            Assert.AreEqual(expectedWarning, warning.FormattedMessage);
            testLoggerProvider.ClearAllLogMessages();
        }
        public async Task CreateTriggerMetrics_HandlesExceptions()
        {
            // StorageException
            _mockCheckpointStore
            .Setup(c => c.GetCheckpointAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ThrowsAsync(new RequestFailedException(404, "Uh oh"));

            _partitions = new List <PartitionProperties>
            {
                new TestPartitionProperties()
            };

            var metrics = await _scaleMonitor.GetMetricsAsync();

            Assert.AreEqual(1, metrics.PartitionCount);
            Assert.AreEqual(0, metrics.EventCount);
            Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

            // Generic Exception
            _mockCheckpointStore
            .Setup(c => c.GetCheckpointAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ThrowsAsync(new Exception("Uh oh"));

            _partitions = new List <PartitionProperties>
            {
                new TestPartitionProperties()
            };

            metrics = await _scaleMonitor.GetMetricsAsync();

            Assert.AreEqual(1, metrics.PartitionCount);
            Assert.AreEqual(0, metrics.EventCount);
            Assert.AreNotEqual(default(DateTime), metrics.Timestamp);

            _loggerProvider.ClearAllLogMessages();
        }
        public void ListCheckpointsAsync_LogsOnRequestErrors()
        {
            var testLoggerProvider = new TestLoggerProvider();
            Mock <BlobContainerClient> containerClientMock = new Mock <BlobContainerClient>(MockBehavior.Strict);

            containerClientMock.Setup(c => c.GetBlobsAsync(It.IsAny <BlobTraits>(), It.IsAny <BlobStates>(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .Throws(new RequestFailedException("Uh oh"));

            BlobsCheckpointStore store = new BlobsCheckpointStore(
                containerClientMock.Object,
                new BasicRetryPolicy(new EventHubsRetryOptions()),
                _functionId,
                testLoggerProvider.CreateLogger("TestLogger")
                );

            Assert.ThrowsAsync <RequestFailedException>(async() => await store.ListCheckpointsAsync(_namespace, _eventHubName, _consumerGroup, CancellationToken.None));

            var warning         = testLoggerProvider.GetAllLogMessages().Single(p => p.Level == Extensions.Logging.LogLevel.Warning);
            var expectedWarning = "Function 'EventHubsTriggerFunction': An exception occurred when listing checkpoints for " +
                                  "FullyQualifiedNamespace: 'TestNamespace'; EventHubName: 'TestEventHubName'; ConsumerGroup: 'TestConsumerGroup'.";

            Assert.AreEqual(expectedWarning, warning.FormattedMessage);
            testLoggerProvider.ClearAllLogMessages();
        }
Example #16
0
 public void ClearLogMessages() => _loggerProvider.ClearAllLogMessages();