private void OnDataReceived(HandleTraceSpanRequest request, ServerCallContext context) { try { Interlocked.Increment(ref this.stats.RequestsReceived); foreach (var instance in request.Instances) { try { this.onProcessInstance?.Invoke(instance); Interlocked.Increment(ref this.stats.InstancesSucceeded); } catch (System.Exception e) { // unexpected exception occured while processing the batch Interlocked.Increment(ref this.stats.InstancesFailed); Diagnostics.LogError(FormattableString.Invariant($"Unknown exception while processing a batch received through the gRPC input. {e.ToString()}")); } } } catch (TaskCanceledException) { // we have been stopped } catch (System.Exception e) { // unexpected exception occured Diagnostics.LogError(FormattableString.Invariant($"Unknown exception while reading from gRPC stream. {e.ToString()}")); this.Stop(); } }
public async Task HostTests_RestartsLibraryIfStoppedUnexpectedly() { // ARRANGE var telemetryClient = Common.SetupStubTelemetryClient(out var sentItems); int port = Common.GetPort(); var config = $@"<?xml version=""1.0"" encoding=""utf-8"" ?> <Configuration> <Host>0.0.0.0</Host> <Port>{port}</Port> <InstrumentationKey>[SPECIFY INSTRUMENTATION KEY HERE]</InstrumentationKey> <LiveMetricsStreamAuthenticationApiKey></LiveMetricsStreamAuthenticationApiKey> <Watchlist> <Namespaces>default</Namespaces> </Watchlist> <AdaptiveSampling Enabled=""true""> <MaxEventsPerSecond>%ISTIO_MIXER_PLUGIN_AI_ADAPTIVE_SAMPLING_EVENTS_LIMIT%</MaxEventsPerSecond> <!--Telemetry items other than events are counted together--> <MaxOtherItemsPerSecond>%ISTIO_MIXER_PLUGIN_AI_ADAPTIVE_SAMPLING_LIMIT%</MaxOtherItemsPerSecond> </AdaptiveSampling> </Configuration> "; Host host = new Host(telemetryClient); host.Run(config, TimeSpan.FromSeconds(1)); FieldInfo libraryFieldInfo = host.GetType().GetField("library", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); Common.AssertIsTrueEventually(() => libraryFieldInfo.GetValue(host) != null); // ACT // stop the existing library (as if something went wrong) var library = libraryFieldInfo.GetValue(host) as Library; library.Stop(); Common.AssertIsTrueEventually(() => !library.IsRunning); // ASSERT // wait for a new library Common.AssertIsTrueEventually(() => libraryFieldInfo.GetValue(host) != null); Common.AssertIsTrueEventually(() => (libraryFieldInfo.GetValue(host) as Library).IsRunning); // verify the new library works var request = new HandleTraceSpanRequest(); request.Instances.Add(Common.GetStandardInstanceMsg()); var writer = new GrpcWriter(port); await writer.Write(request).ConfigureAwait(false); Common.AssertIsTrueEventually(() => sentItems.Count == 2); Assert.AreEqual("source-1", (sentItems.Skip(0).First() as DependencyTelemetry).Context.Cloud.RoleInstance); Assert.AreEqual("destination-1", (sentItems.Skip(1).First() as RequestTelemetry).Context.Cloud.RoleInstance); }
public async Task Write(HandleTraceSpanRequest request) { try { await this.client.HandleTraceSpanAsync(request, new CallOptions()).ResponseAsync.ConfigureAwait(false); } catch (System.Exception e) { throw new InvalidOperationException( FormattableString.Invariant($"Error sending a message via gRpc. {e.ToString()}")); } }
public async Task GrpcInputTests_StopsAndRestarts() { // ARRANGE int instancesReceived = 0; InstanceMsg receivedInstance = null; int port = Common.GetPort(); var input = new GrpcInput("localhost", port, instance => { instancesReceived++; receivedInstance = instance; }); input.Start(); Assert.IsTrue(SpinWait.SpinUntil(() => input.IsRunning, GrpcInputTests.DefaultTimeout)); var grpcWriter = new GrpcWriter(port); var request = new HandleTraceSpanRequest(); request.Instances.Add(new InstanceMsg() { SourceName = "SourceName1" }); await grpcWriter.Write(request).ConfigureAwait(false); Common.AssertIsTrueEventually( () => input.GetStats().InstancesReceived == 1 && instancesReceived == 1 && receivedInstance.SourceName == "SourceName1", GrpcInputTests.DefaultTimeout); // ACT input.Stop(); Common.AssertIsTrueEventually( () => !input.IsRunning && input.GetStats().InstancesReceived == 1 && instancesReceived == 1 && receivedInstance.SourceName == "SourceName1", GrpcInputTests.DefaultTimeout); input.Start(); Assert.IsTrue(SpinWait.SpinUntil(() => input.IsRunning, GrpcInputTests.DefaultTimeout)); grpcWriter = new GrpcWriter(port); request.Instances.Single().SourceName = "SourceName2"; await grpcWriter.Write(request).ConfigureAwait(false); // ASSERT Common.AssertIsTrueEventually( () => input.IsRunning && input.GetStats().InstancesReceived == 1 && instancesReceived == 2 && receivedInstance.SourceName == "SourceName2", GrpcInputTests.DefaultTimeout); }
public async Task HostTests_StopsLibrary() { // ARRANGE var telemetryClient = Common.SetupStubTelemetryClient(out var sentItems); int port = Common.GetPort(); var config = $@"<?xml version=""1.0"" encoding=""utf-8"" ?> <Configuration> <Host>0.0.0.0</Host> <Port>{port}</Port> <InstrumentationKey>[SPECIFY INSTRUMENTATION KEY HERE]</InstrumentationKey> <LiveMetricsStreamAuthenticationApiKey></LiveMetricsStreamAuthenticationApiKey> <AdaptiveSampling Enabled=""true""> <MaxEventsPerSecond>%ISTIO_MIXER_PLUGIN_AI_ADAPTIVE_SAMPLING_EVENTS_LIMIT%</MaxEventsPerSecond> <!--Telemetry items other than events are counted together--> <MaxOtherItemsPerSecond>%ISTIO_MIXER_PLUGIN_AI_ADAPTIVE_SAMPLING_LIMIT%</MaxOtherItemsPerSecond> </AdaptiveSampling> </Configuration> "; Host host = new Host(telemetryClient); host.Run(config, TimeSpan.FromSeconds(5)); Thread.Sleep(TimeSpan.FromMilliseconds(250)); // ACT host.Stop(); Thread.Sleep(TimeSpan.FromMilliseconds(250)); var request = new HandleTraceSpanRequest(); request.Instances.Add(new InstanceMsg() { HttpStatusCode = 203, SpanTags = { { "source.name", new Value { StringValue = "some-app-1" } }, { "destination.name", new Value { StringValue = "some-other-app-1" } } } }); // ASSERT var writer = new GrpcWriter(port); await writer.Write(request).ConfigureAwait(false); Assert.Fail(); }
public async Task LibraryTests_LibraryProcessesRequestsCorrectly() { // ARRANGE var telemetryClient = Common.SetupStubTelemetryClient(out var sentItems); int port = Common.GetPort(); var config = $@"<?xml version=""1.0"" encoding=""utf-8"" ?> <Configuration> <Host>0.0.0.0</Host> <Port>{port}</Port> <InstrumentationKey>ikey1</InstrumentationKey> <LiveMetricsStreamAuthenticationApiKey></LiveMetricsStreamAuthenticationApiKey> <Watchlist> <Namespaces>default</Namespaces> </Watchlist> <AdaptiveSampling Enabled=""true""> <MaxEventsPerSecond>%ISTIO_MIXER_PLUGIN_AI_ADAPTIVE_SAMPLING_EVENTS_LIMIT%</MaxEventsPerSecond> <!--Telemetry items other than events are counted together--> <MaxOtherItemsPerSecond>%ISTIO_MIXER_PLUGIN_AI_ADAPTIVE_SAMPLING_LIMIT%</MaxOtherItemsPerSecond> </AdaptiveSampling> </Configuration> "; var request = new HandleTraceSpanRequest(); request.Instances.Add(Common.GetStandardInstanceMsg()); var lib = new Library(config, telemetryClient); lib.Run(); // ACT var writer = new GrpcWriter(port); await writer.Write(request).ConfigureAwait(false); // ASSERT Common.AssertIsTrueEventually(() => sentItems.Count == 2); lib.Stop(); Assert.AreEqual("source-1", (sentItems.Skip(0).First() as DependencyTelemetry).Context.Cloud.RoleInstance); Assert.AreEqual("destination-1", (sentItems.Skip(1).First() as RequestTelemetry).Context.Cloud.RoleInstance); }
public void GrpcInputTests_ReceivesDataFromMultipleClients() { // ARRANGE int instancesReceived = 0; InstanceMsg receivedInstance = null; int port = Common.GetPort(); var input = new GrpcInput("localhost", port, instance => { Interlocked.Increment(ref instancesReceived); receivedInstance = instance; }); input.Start(); Assert.IsTrue(SpinWait.SpinUntil(() => input.IsRunning, GrpcInputTests.DefaultTimeout)); // ACT var request = new HandleTraceSpanRequest(); request.Instances.Add(new InstanceMsg() { SourceName = "SourceName1" }); Parallel.For(0, 1000, new ParallelOptions() { MaxDegreeOfParallelism = 1000 }, async i => { var grpcWriter = new GrpcWriter(port); await grpcWriter.Write(request).ConfigureAwait(false); }); // ASSERT Common.AssertIsTrueEventually( () => input.GetStats().InstancesReceived == 1000 && instancesReceived == 1000, GrpcInputTests.DefaultTimeout); input.Stop(); Assert.IsTrue(SpinWait.SpinUntil(() => !input.IsRunning, GrpcInputTests.DefaultTimeout)); }
public async Task GrpcInputTests_HandlesExceptionsInProcessingHandler() { // ARRANGE int port = Common.GetPort(); var input = new GrpcInput("localhost", port, instance => throw new InvalidOperationException()); input.Start(); Assert.IsTrue(SpinWait.SpinUntil(() => input.IsRunning, GrpcInputTests.DefaultTimeout)); var grpcWriter = new GrpcWriter(port); var request = new HandleTraceSpanRequest(); request.Instances.Add(new InstanceMsg() { SourceName = "SourceName1" }); // ACT await grpcWriter.Write(request).ConfigureAwait(false); // ASSERT // must have handled the exception by logging it // should still be able to process items Common.AssertIsTrueEventually( () => input.IsRunning && input.GetStats().InstancesReceived == 0 && input.GetStats().InstancesFailed == 1, GrpcInputTests.DefaultTimeout); await grpcWriter.Write(request).ConfigureAwait(false); Common.AssertIsTrueEventually( () => input.IsRunning && input.GetStats().InstancesReceived == 0 && input.GetStats().InstancesFailed == 2, GrpcInputTests.DefaultTimeout); }
public async Task LibraryTests_LibraryLogsInputStatsCorrectly() { // ARRANGE var telemetryClient = Common.SetupStubTelemetryClient(out var sentItems); int port = Common.GetPort(); var config = $@"<?xml version=""1.0"" encoding=""utf-8"" ?> <Configuration> <Host>0.0.0.0</Host> <Port>{port}</Port> <InstrumentationKey>ikey1</InstrumentationKey> <LiveMetricsStreamAuthenticationApiKey></LiveMetricsStreamAuthenticationApiKey> <Watchlist> <Namespaces>default</Namespaces> </Watchlist> <AdaptiveSampling Enabled=""true""> <MaxEventsPerSecond>%ISTIO_MIXER_PLUGIN_AI_ADAPTIVE_SAMPLING_EVENTS_LIMIT%</MaxEventsPerSecond> <!--Telemetry items other than events are counted together--> <MaxOtherItemsPerSecond>%ISTIO_MIXER_PLUGIN_AI_ADAPTIVE_SAMPLING_LIMIT%</MaxOtherItemsPerSecond> </AdaptiveSampling> </Configuration> "; var request = new HandleTraceSpanRequest(); request.Instances.Add(Common.GetStandardInstanceMsg()); request.Instances.Add(Common.GetStandardInstanceMsg()); // redirect loggging to a new file Diagnostics.Flush(TimeSpan.FromSeconds(5)); string logFileName = Common.SwitchLoggerToDifferentFile(); var lib = new Library(config, telemetryClient, TimeSpan.FromMilliseconds(10)); lib.Run(); // ACT var writer = new GrpcWriter(port); await writer.Write(request).ConfigureAwait(false); await writer.Write(request).ConfigureAwait(false); // ASSERT Common.AssertIsTrueEventually(() => sentItems.Count == 8); await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); lib.Stop(); Diagnostics.Flush(TimeSpan.FromSeconds(5)); // close the file Common.SwitchLoggerToDifferentFile(); string logs = await File.ReadAllTextAsync(logFileName).ConfigureAwait(false); Assert.IsTrue(logs.Contains("|INFO|Istio's Mixer input: [ConnectionCount: 0, RequestsReceived: 0, InstancesSucceeded: 0, InstancesFailed: 0]")); Assert.IsTrue(logs.Contains("|INFO|Istio's Mixer input: [ConnectionCount: 0, RequestsReceived: 2, InstancesSucceeded: 4, InstancesFailed: 0]")); }
public override async Task <ReportResult> HandleTraceSpan(HandleTraceSpanRequest request, ServerCallContext context) { return(await this.onDataReceived(request, context).ConfigureAwait(false)); }