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();
            }
        }
Exemple #2
0
        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()}"));
     }
 }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #7
0
        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));
        }
Exemple #8
0
        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));
 }