public async Task PublishesAllFunctionExecutionActivities() { _handlerMock.Protected().Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()).ReturnsAsync(new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); var activity1 = new ContainerFunctionExecutionActivity(DateTime.UtcNow, "func1", ExecutionStage.InProgress, "QueueTrigger", false); var activity2 = new ContainerFunctionExecutionActivity(DateTime.UtcNow, "func2", ExecutionStage.Finished, "QueueTrigger", true); var activities = new List <ContainerFunctionExecutionActivity> { activity1, activity2 }; await _meshServiceClient.PublishContainerActivity(activities); _handlerMock.Protected().Verify <Task <HttpResponseMessage> >("SendAsync", Times.Exactly(1), ItExpr.Is <HttpRequestMessage>(r => IsPublishExecutionStatusRequest(r, activity1, activity2)), ItExpr.IsAny <CancellationToken>()); }
public async Task DoesNotPublishExecutionActivityInStandbyMode() { var activity = new ContainerFunctionExecutionActivity(DateTime.MinValue, "func-1", ExecutionStage.InProgress, "trigger-1", false); var environment = new TestEnvironment(); environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsitePlaceholderMode, "1"); environment.SetEnvironmentVariable(EnvironmentSettingNames.ContainerName, "Container-Name"); var meshClient = new Mock <IMeshServiceClient>(); var standbyOptions = new TestOptionsMonitor <StandbyOptions>(new StandbyOptions { InStandbyMode = true }); using (var publisher = new LinuxContainerActivityPublisher(standbyOptions, meshClient.Object, environment, NullLogger <LinuxContainerActivityPublisher> .Instance, FlushIntervalMs)) { await publisher.StartAsync(CancellationToken.None); publisher.PublishFunctionExecutionActivity(activity); await Task.Delay(DelayIntervalMs); await publisher.StopAsync(CancellationToken.None); meshClient.Verify(c => c.PublishContainerActivity(It.IsAny <IEnumerable <ContainerFunctionExecutionActivity> >()), Times.Never); } }
public void Comparison_Ignores_EventTime() { var activity1 = new ContainerFunctionExecutionActivity(DateTime.UtcNow, "func-1", ExecutionStage.InProgress, "QueueTrigger", false); var activity2 = new ContainerFunctionExecutionActivity(DateTime.UtcNow.Subtract(TimeSpan.FromSeconds(1)), "func-1", ExecutionStage.InProgress, "QueueTrigger", false); Assert.Equal(activity1, activity2); }
public async Task PublishesFunctionExecutionActivity() { var activity = new ContainerFunctionExecutionActivity(DateTime.MinValue, "func-1", ExecutionStage.InProgress, "trigger-1", false); var environment = new TestEnvironment(); environment.SetEnvironmentVariable(EnvironmentSettingNames.ContainerName, "Container-Name"); var meshClient = new Mock <IMeshServiceClient>(); meshClient.Setup(c => c.PublishContainerActivity( It.IsAny <IEnumerable <ContainerFunctionExecutionActivity> >())).Returns(Task.FromResult(true)); var standbyOptions = new TestOptionsMonitor <StandbyOptions>(new StandbyOptions { InStandbyMode = false }); using (var publisher = new LinuxContainerActivityPublisher(standbyOptions, meshClient.Object, environment, NullLogger <LinuxContainerActivityPublisher> .Instance, FlushIntervalMs)) { await publisher.StartAsync(CancellationToken.None); publisher.PublishFunctionExecutionActivity(activity); await Task.Delay(DelayIntervalMs); await publisher.StopAsync(CancellationToken.None); meshClient.Verify( c => c.PublishContainerActivity( It.Is <IEnumerable <ContainerFunctionExecutionActivity> >(e => MatchesFunctionActivities(e, activity))), Times.Once); } }
public void PublishFunctionExecutionActivity(ContainerFunctionExecutionActivity activity) { if (!_standbyOptions.CurrentValue.InStandbyMode) { if (!PublishActivity(activity)) { _logger.LogWarning($"Failed to add activity {activity}"); } } }
private void RaiseFunctionMetricEvent(FunctionStartedEvent runningFunctionInfo, int concurrency, DateTime currentTime) { double executionTimespan = 0; ExecutionStage executionStage; if (!runningFunctionInfo.Completed) { executionStage = ExecutionStage.InProgress; executionTimespan = (currentTime - runningFunctionInfo.Timestamp).TotalMilliseconds; } else { // regardless of the actual Failed/Succeeded status, we always raise the final event // with stage Finished executionStage = ExecutionStage.Finished; executionTimespan = runningFunctionInfo.Duration.TotalMilliseconds; } // Don't allocate the GUID string twice, though we can probably optimize this further upstream. var invocationId = runningFunctionInfo.InvocationId.ToString(); MetricsEventGenerator.LogFunctionExecutionEvent( _executionId, _appServiceOptions.AppName, concurrency, runningFunctionInfo.FunctionMetadata.Name, invocationId, executionStage.ToString(), (long)executionTimespan, runningFunctionInfo.Success); if (_metricsPublisher != null) { _metricsPublisher.AddFunctionExecutionActivity( runningFunctionInfo.FunctionMetadata.Name, invocationId, concurrency, executionStage.ToString(), runningFunctionInfo.Success, (long)executionTimespan, _executionId, currentTime, runningFunctionInfo.Timestamp); } if (_linuxContainerActivityPublisher != null) { var triggerType = runningFunctionInfo.FunctionMetadata.Trigger?.Type; var activity = new ContainerFunctionExecutionActivity(DateTime.UtcNow, runningFunctionInfo.FunctionMetadata.Name, executionStage, triggerType, runningFunctionInfo.Success); _linuxContainerActivityPublisher.PublishFunctionExecutionActivity(activity); } }
public void Comparison_Returns_Expected_Results(bool expected, string functionName1, string functionName2, ExecutionStage stage1, ExecutionStage stage2, string triggerType1, string triggerType2, bool success1, bool success2) { var activity1 = new ContainerFunctionExecutionActivity(DateTime.MinValue, functionName1, stage1, triggerType1, success1); var activity2 = new ContainerFunctionExecutionActivity(DateTime.MaxValue, functionName2, stage2, triggerType2, success2); var hashSet = new HashSet <ContainerFunctionExecutionActivity> { activity1, activity2 }; Assert.Equal(expected, activity1.Equals(activity2)); Assert.Equal(expected ? 1 : 2, hashSet.Count); }
private bool PublishActivity(ContainerFunctionExecutionActivity activity) { if (_activitiesLock.TryEnterWriteLock(LockTimeOutMs)) { try { _uniqueActivities.Add(activity); } finally { _activitiesLock.ExitWriteLock(); } return(true); } return(false); }
private void RaiseFunctionMetricEvent(RunningFunctionInfo runningFunctionInfo, int concurrency, DateTime currentTime) { double executionTimespan = 0; if (runningFunctionInfo.ExecutionStage == ExecutionStage.Finished) { executionTimespan = (runningFunctionInfo.EndTime - runningFunctionInfo.StartTime).TotalMilliseconds; } else { executionTimespan = (currentTime - runningFunctionInfo.StartTime).TotalMilliseconds; } MetricsEventGenerator.LogFunctionExecutionEvent( _executionId, _appServiceOptions.CurrentValue.AppName, concurrency, runningFunctionInfo.Name, runningFunctionInfo.InvocationId.ToString(), runningFunctionInfo.ExecutionStage.ToString(), (long)executionTimespan, runningFunctionInfo.Success); if (_metricsPublisher != null) { _metricsPublisher.AddFunctionExecutionActivity( runningFunctionInfo.Name, runningFunctionInfo.InvocationId.ToString(), concurrency, runningFunctionInfo.ExecutionStage.ToString(), runningFunctionInfo.Success, (long)executionTimespan, _executionId, currentTime, runningFunctionInfo.StartTime); } if (_linuxContainerActivityPublisher != null) { var activity = new ContainerFunctionExecutionActivity(DateTime.UtcNow, runningFunctionInfo.Name, runningFunctionInfo.ExecutionStage, runningFunctionInfo.TriggerType, runningFunctionInfo.Success); _linuxContainerActivityPublisher.PublishFunctionExecutionActivity(activity); } }
public async Task PublishesUniqueFunctionExecutionActivitiesOnly() { // activity1 and activity2 are duplicates. so only activity2 will be published var activity1 = new ContainerFunctionExecutionActivity(DateTime.MinValue, "func-1", ExecutionStage.InProgress, "trigger-1", false); var activity2 = new ContainerFunctionExecutionActivity(DateTime.MaxValue, "func-1", ExecutionStage.InProgress, "trigger-1", false); var activity3 = new ContainerFunctionExecutionActivity(DateTime.MaxValue, "func-1", ExecutionStage.Finished, "trigger-1", true); var activity4 = new ContainerFunctionExecutionActivity(DateTime.MaxValue, "func-1", ExecutionStage.Finished, "trigger-1", false); var environment = new TestEnvironment(); environment.SetEnvironmentVariable(EnvironmentSettingNames.ContainerName, "Container-Name"); var meshClient = new Mock <IMeshServiceClient>(); var standbyOptions = new TestOptionsMonitor <StandbyOptions>(new StandbyOptions { InStandbyMode = false }); using (var publisher = new LinuxContainerActivityPublisher(standbyOptions, meshClient.Object, environment, NullLogger <LinuxContainerActivityPublisher> .Instance, FlushIntervalMs)) { await publisher.StartAsync(CancellationToken.None); publisher.PublishFunctionExecutionActivity(activity1); publisher.PublishFunctionExecutionActivity(activity2); publisher.PublishFunctionExecutionActivity(activity3); publisher.PublishFunctionExecutionActivity(activity4); await Task.Delay(DelayIntervalMs); await publisher.StopAsync(CancellationToken.None); meshClient.Verify( c => c.PublishContainerActivity( It.Is <IEnumerable <ContainerFunctionExecutionActivity> >(e => MatchesFunctionActivities(e, activity2, activity3, activity4))), Times.Once); } }
public async Task IgnoresGlobalSerializer() { Func <JsonSerializerSettings> defaultSettings = null; try { defaultSettings = JsonConvert.DefaultSettings; JsonConvert.DefaultSettings = () => new JsonSerializerSettings() { Converters = new JsonConverter[] { new HelloWorldConverter() } }; _handlerMock.Protected().Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()).ReturnsAsync(new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); var activity1 = new ContainerFunctionExecutionActivity(DateTime.UtcNow, "func1", ExecutionStage.InProgress, "QueueTrigger", false); var activity2 = new ContainerFunctionExecutionActivity(DateTime.UtcNow, "func2", ExecutionStage.Finished, "QueueTrigger", true); var activities = new List <ContainerFunctionExecutionActivity> { activity1, activity2 }; await _meshServiceClient.PublishContainerActivity(activities); _handlerMock.Protected().Verify <Task <HttpResponseMessage> >("SendAsync", Times.Exactly(1), ItExpr.Is <HttpRequestMessage>(r => ContainsActivities(r, activity1, activity2)), ItExpr.IsAny <CancellationToken>()); } finally { JsonConvert.DefaultSettings = defaultSettings; } }
public async Task PublishesSpecializationCompleteEvent() { var activity = new ContainerFunctionExecutionActivity(DateTime.MinValue, "func-1", ExecutionStage.InProgress, "trigger-1", false); var environment = new TestEnvironment(); environment.SetEnvironmentVariable(EnvironmentSettingNames.ContainerName, "Container-Name"); var meshClient = new Mock <IMeshServiceClient>(MockBehavior.Strict); meshClient.Setup(c => c.NotifyHealthEvent(ContainerHealthEventType.Informational, It.IsAny <Type>(), LinuxContainerActivityPublisher.SpecializationCompleteEvent)).Returns(Task.FromResult(true)); var standbyOptions = new TestOptionsMonitor <StandbyOptions>(new StandbyOptions { InStandbyMode = false }); using (var publisher = new LinuxContainerActivityPublisher(standbyOptions, meshClient.Object, environment, NullLogger <LinuxContainerActivityPublisher> .Instance, 1000, InitialFlushIntervalMs)) { await publisher.StartAsync(CancellationToken.None); publisher.PublishFunctionExecutionActivity(activity); await Task.Delay(100); await publisher.StopAsync(CancellationToken.None); meshClient.Verify(c => c.NotifyHealthEvent(ContainerHealthEventType.Informational, It.IsAny <Type>(), LinuxContainerActivityPublisher.SpecializationCompleteEvent), Times.Once); // Since test is waiting for 100ms and Flush interval is 1000ms, there will be no PublishContainerActivity meshClient.Verify( c => c.PublishContainerActivity( It.Is <IEnumerable <ContainerFunctionExecutionActivity> >(e => MatchesFunctionActivities(e, activity))), Times.Never); } }
public async Task PublishesAllFunctionExecutionActivitiesEvenInCaseOfExceptions() { _handlerMock.Protected().Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>()).Throws(new Exception()); var activity1 = new ContainerFunctionExecutionActivity(DateTime.UtcNow, "func1", ExecutionStage.InProgress, "QueueTrigger", false); var activity2 = new ContainerFunctionExecutionActivity(DateTime.UtcNow, "func2", ExecutionStage.Finished, "QueueTrigger", true); var activities = new List <ContainerFunctionExecutionActivity> { activity1, activity2 }; await _meshServiceClient.PublishContainerActivity(activities); // total count = 3 (1 set of activities * 3 retries) _handlerMock.Protected().Verify <Task <HttpResponseMessage> >("SendAsync", Times.Exactly(3), ItExpr.Is <HttpRequestMessage>(r => IsPublishExecutionStatusRequest(r, activity1, activity2)), ItExpr.IsAny <CancellationToken>()); }
public Task PublishContainerFunctionExecutionActivity(ContainerFunctionExecutionActivity activity) { return(Task.CompletedTask); }
public void PublishFunctionExecutionActivity(ContainerFunctionExecutionActivity activity) { //do nothing }
public void Activity_Equals_Itself() { var activity = new ContainerFunctionExecutionActivity(DateTime.UtcNow, "func-1", ExecutionStage.InProgress, "QueueTrigger", false); Assert.Equal(activity, activity); }