[RunOnlyOnPlatforms(Windows = true)] // VisualStudioCredential works only on Windows
        public async Task DefaultAzureCredential_UseVisualStudioCredential()
        {
            var options = Recording.InstrumentClientOptions(new DefaultAzureCredentialOptions
            {
                ExcludeEnvironmentCredential        = true,
                ExcludeInteractiveBrowserCredential = true,
                ExcludeSharedTokenCacheCredential   = true,
            });

            var fileSystem = CredentialTestHelpers.CreateFileSystemForVisualStudio();

            var(expectedToken, expectedExpiresOn, processOutput) = CredentialTestHelpers.CreateTokenForVisualStudio();
            var testProcess = new TestProcess {
                Output = processOutput
            };

            var factory = new TestDefaultAzureCredentialFactory(options, fileSystem, new TestProcessService(testProcess), default)
            {
                ManagedIdentitySourceFactory = () => default
            };
            var credential = InstrumentClient(new DefaultAzureCredential(factory, options));

            AccessToken token;
            List <ClientDiagnosticListener.ProducedDiagnosticScope> scopes;

            using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
            {
                token = await credential.GetTokenAsync(new TokenRequestContext(new[] { "https://vault.azure.net/.default" }), CancellationToken.None);

                scopes = diagnosticListener.Scopes;
            }

            Assert.AreEqual(token.Token, expectedToken);
            Assert.AreEqual(token.ExpiresOn, expectedExpiresOn);

            Assert.AreEqual(2, scopes.Count);
            Assert.AreEqual($"{nameof(DefaultAzureCredential)}.{nameof(DefaultAzureCredential.GetToken)}", scopes[0].Name);
            Assert.AreEqual($"{nameof(VisualStudioCredential)}.{nameof(VisualStudioCredential.GetToken)}", scopes[1].Name);
        }
        public async Task RecognizeContentOperationCreatesDiagnosticScopeOnUpdate()
        {
            using var testListener = new ClientDiagnosticListener(DiagnosticNamespace);
            using var stream       = new MemoryStream(Encoding.UTF8.GetBytes("{}"));

            var mockResponse = new MockResponse(200);

            mockResponse.ContentStream = stream;

            var mockTransport = new MockTransport(new[] { mockResponse, mockResponse });
            var options       = new FormRecognizerClientOptions()
            {
                Transport = mockTransport
            };
            var client = CreateFormRecognizerClient(options);

            var operation = new RecognizeContentOperation("00000000-0000-0000-0000-000000000000", client);

            await operation.UpdateStatusAsync();

            testListener.AssertScope($"{nameof(RecognizeContentOperation)}.{nameof(RecognizeContentOperation.UpdateStatus)}");
        }
        public async Task DefaultAzureCredential_UseVisualStudioCodeCredential()
        {
            var options = Recording.InstrumentClientOptions(new DefaultAzureCredentialOptions
            {
                ExcludeEnvironmentCredential        = true,
                ExcludeInteractiveBrowserCredential = true,
                ExcludeSharedTokenCacheCredential   = true,
                VisualStudioCodeTenantId            = TestEnvironment.TestTenantId
            });

            var cloudName  = Guid.NewGuid().ToString();
            var fileSystem = CredentialTestHelpers.CreateFileSystemForVisualStudioCode(TestEnvironment, cloudName);
            var process    = new TestProcess {
                Error = "Error"
            };

            var factory = new TestDefaultAzureCredentialFactory(options, fileSystem, new TestProcessService(process), default)
            {
                ManagedIdentitySourceFactory = () => default
            };
            var credential = InstrumentClient(new DefaultAzureCredential(factory, options));

            AccessToken token;
            List <ClientDiagnosticListener.ProducedDiagnosticScope> scopes;

            using (await CredentialTestHelpers.CreateRefreshTokenFixtureAsync(TestEnvironment, Mode, ExpectedServiceName, cloudName))
                using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
                {
                    token = await credential.GetTokenAsync(new TokenRequestContext(new[] { "https://vault.azure.net/.default" }), CancellationToken.None);

                    scopes = diagnosticListener.Scopes;
                }

            Assert.IsNotNull(token.Token);

            Assert.AreEqual(2, scopes.Count);
            Assert.AreEqual($"{nameof(DefaultAzureCredential)}.{nameof(DefaultAzureCredential.GetToken)}", scopes[0].Name);
            Assert.AreEqual($"{nameof(VisualStudioCodeCredential)}.{nameof(VisualStudioCodeCredential.GetToken)}", scopes[1].Name);
        }
        public async Task DefaultAzureCredential_UseAzureCliCredential()
        {
            var options = InstrumentClientOptions(new DefaultAzureCredentialOptions
            {
                ExcludeEnvironmentCredential        = true,
                ExcludeInteractiveBrowserCredential = true,
                ExcludeSharedTokenCacheCredential   = true,
                ExcludeManagedIdentityCredential    = true,
                VisualStudioCodeTenantId            = TestEnvironment.TestTenantId
            });

            var(expectedToken, expectedExpiresOn, processOutput) = CredentialTestHelpers.CreateTokenForAzureCli();
            var testProcess = new TestProcess {
                Output = processOutput
            };
            var vscAdapter = new TestVscAdapter(ExpectedServiceName, "AzureCloud", null);
            var fileSystem = CredentialTestHelpers.CreateFileSystemForVisualStudioCode(TestEnvironment);

            var factory    = new TestDefaultAzureCredentialFactory(options, fileSystem, new TestProcessService(testProcess), vscAdapter);
            var credential = InstrumentClient(new DefaultAzureCredential(factory, options));

            AccessToken token;
            List <ClientDiagnosticListener.ProducedDiagnosticScope> scopes;

            using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
            {
                token = await credential.GetTokenAsync(new TokenRequestContext(new[] { TestEnvironment.KeyvaultScope }), CancellationToken.None);

                scopes = diagnosticListener.Scopes;
            }

            Assert.AreEqual(token.Token, expectedToken);
            Assert.AreEqual(token.ExpiresOn, expectedExpiresOn);

            Assert.AreEqual(2, scopes.Count);
            Assert.AreEqual($"{nameof(DefaultAzureCredential)}.{nameof(DefaultAzureCredential.GetToken)}", scopes[0].Name);
            Assert.AreEqual($"{nameof(AzureCliCredential)}.{nameof(AzureCliCredential.GetToken)}", scopes[1].Name);
        }
Ejemplo n.º 5
0
        public async Task EventHubProducerCreatesDiagnosticScopeOnSend()
        {
            using var testListener = new ClientDiagnosticListener(DiagnosticSourceName);
            var activity = new Activity("SomeActivity").Start();

            var eventHubName   = "SomeName";
            var endpoint       = "endpoint";
            var fakeConnection = new MockConnection(endpoint, eventHubName);
            var transportMock  = new Mock <TransportProducer>();

            transportMock
            .Setup(m => m.SendAsync(It.IsAny <IEnumerable <EventData> >(), It.IsAny <SendEventOptions>(), It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask);

            var producer = new EventHubProducerClient(fakeConnection, transportMock.Object);

            var eventData = new EventData(ReadOnlyMemory <byte> .Empty);
            await producer.SendAsync(eventData);

            activity.Stop();

            ClientDiagnosticListener.ProducedDiagnosticScope sendScope = testListener.AssertScope(DiagnosticProperty.ProducerActivityName,
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.ClientKind),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.ServiceContextAttribute, DiagnosticProperty.EventHubsServiceContext),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint));

            ClientDiagnosticListener.ProducedDiagnosticScope messageScope = testListener.AssertScope(DiagnosticProperty.EventActivityName,
                                                                                                     new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                     new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint));

            Assert.That(eventData.Properties[DiagnosticProperty.DiagnosticIdAttribute], Is.EqualTo(messageScope.Activity.Id), "The diagnostics identifier should match.");
            Assert.That(messageScope.Activity.Tags, Has.One.EqualTo(new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.ProducerKind)), "The activities tag should be internal.");
            Assert.That(messageScope.Activity, Is.Not.SameAs(sendScope.Activity), "The activities should not be the same instance.");
            Assert.That(sendScope.Activity.ParentId, Is.EqualTo(activity.Id), "The send scope's parent identifier should match the activity in the active scope.");
            Assert.That(messageScope.Activity.ParentId, Is.EqualTo(activity.Id), "The message scope's parent identifier should match the activity in the active scope.");
        }
Ejemplo n.º 6
0
        public async Task UpdateCheckpointAsyncCreatesScope()
        {
            using var cancellationSource = new CancellationTokenSource();
            cancellationSource.CancelAfter(TimeSpan.FromSeconds(15));

            var completionSource = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
            var mockContext      = new Mock <PartitionContext>("65");
            var mockLogger       = new Mock <EventProcessorClientEventSource>();
            var mockProcessor    = new Mock <EventProcessorClient>(Mock.Of <StorageManager>(), "cg", "host", "hub", Mock.Of <TokenCredential>(), null)
            {
                CallBase = true
            };

            mockProcessor
            .Protected()
            .Setup <EventHubConnection>("CreateConnection")
            .Returns(Mock.Of <EventHubConnection>());

            mockLogger
            .Setup(log => log.UpdateCheckpointComplete(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>()))
            .Callback(() => completionSource.TrySetResult(true));

            mockProcessor.Object.Logger = mockLogger.Object;

            using var listener = new ClientDiagnosticListener(EventDataInstrumentation.DiagnosticNamespace);
            await mockProcessor.Object.UpdateCheckpointAsync(new MockEventData(new byte[0], sequenceNumber : 65, offset : 998), mockContext.Object, default);

            await Task.WhenAny(completionSource.Task, Task.Delay(Timeout.Infinite, cancellationSource.Token));

            Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled.");

            ClientDiagnosticListener.ProducedDiagnosticScope scope = listener.Scopes.Single();
            Assert.That(scope.Name, Is.EqualTo(DiagnosticProperty.EventProcessorCheckpointActivityName));

            cancellationSource.Cancel();
        }
        public void DefaultAzureCredential_AllCredentialsHaveFailed_CredentialUnavailableException()
        {
            var options = InstrumentClientOptions(new DefaultAzureCredentialOptions
            {
                ExcludeEnvironmentCredential        = true,
                ExcludeInteractiveBrowserCredential = true,
                ExcludeManagedIdentityCredential    = true,
                ExcludeSharedTokenCacheCredential   = true,
            });

            var vscAdapter = new TestVscAdapter(ExpectedServiceName, "AzureCloud", "{}");
            var factory    = new TestDefaultAzureCredentialFactory(options, new TestFileSystemService(), new TestProcessService(new TestProcess {
                Error = "'az' is not recognized"
            }, new TestProcess {
                Error = "'PowerShell' is not recognized"
            }), vscAdapter)
            {
                ManagedIdentitySourceFactory = () => default
            };
            var credential = InstrumentClient(new DefaultAzureCredential(factory, options));

            List <ClientDiagnosticListener.ProducedDiagnosticScope> scopes;

            using (ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure.Identity")))
            {
                Assert.CatchAsync <CredentialUnavailableException>(async() => await credential.GetTokenAsync(new TokenRequestContext(new[] { "https://vault.azure.net/.default" }), CancellationToken.None));
                scopes = diagnosticListener.Scopes;
            }

            Assert.AreEqual(5, scopes.Count);
            Assert.AreEqual($"{nameof(DefaultAzureCredential)}.{nameof(DefaultAzureCredential.GetToken)}", scopes[0].Name);
            Assert.AreEqual($"{nameof(VisualStudioCredential)}.{nameof(VisualStudioCredential.GetToken)}", scopes[1].Name);
            Assert.AreEqual($"{nameof(VisualStudioCodeCredential)}.{nameof(VisualStudioCodeCredential.GetToken)}", scopes[2].Name);
            Assert.AreEqual($"{nameof(AzureCliCredential)}.{nameof(AzureCliCredential.GetToken)}", scopes[3].Name);
            Assert.AreEqual($"{nameof(AzurePowerShellCredential)}.{nameof(AzurePowerShellCredential.GetToken)}", scopes[4].Name);
        }
Ejemplo n.º 8
0
        public async Task TestEventGridEventBatchDispatchWithTracing(string functionName)
        {
            // individual elements
            var ext = new EventGridExtensionConfigProvider(new HttpRequestProcessor(NullLoggerFactory.Instance.CreateLogger <HttpRequestProcessor>()), NullLoggerFactory.Instance);

            using var host = TestHelpers.NewHost <MyProg1>(ext);
            await host.StartAsync(); // add listener

            using var testListener = new ClientDiagnosticListener("Azure.Messaging.EventGrid");
            var request = CreateDispatchRequest(functionName,
                                                JObject.Parse(@"{'subject':'one','eventType':'1','id':'1','dataVersion':'0','data':{'prop':'alpha'}}"),
                                                JObject.Parse(@"{'subject':'two','eventType':'2','id':'2','dataVersion':'0','data':{'prop':'alpha'}}"));

            var response = await ext.ConvertAsync(request, CancellationToken.None);

            Assert.AreEqual(1, testListener.Scopes.Count);
            var executionScope = testListener.AssertScope("EventGrid.Process",
                                                          new KeyValuePair <string, string>("az.namespace", "Microsoft.EventGrid"));

            Assert.IsEmpty(executionScope.Links);
            Assert.Null(executionScope.Exception);
            Assert.True(_log.TryGetValue(executionScope.Activity.Id, out var activityName));
            Assert.AreEqual("EventGrid.Process", activityName);
        }
        public async Task UpdateCheckpointAsyncCreatesScope()
        {
            using ClientDiagnosticListener listener = new ClientDiagnosticListener(DiagnosticSourceName);

            var eventHubName = "SomeName";
            var endpoint     = new Uri("amqp://some.endpoint.com/path");
            Func <EventHubConnection> fakeFactory = () => new MockConnection(endpoint, eventHubName);
            var context = new MockPartitionContext("partition");
            var data    = new MockEventData(new byte[0], sequenceNumber: 0, offset: 0);

            var storageManager = new Mock <PartitionManager>();
            var eventProcessor = new Mock <EventProcessorClient>(Mock.Of <PartitionManager>(), "cg", endpoint.Host, eventHubName, fakeFactory, null);

            // UpdateCheckpointAsync does not invoke the handlers, but we are setting them here in case
            // this fact changes in the future.

            eventProcessor.Object.ProcessEventAsync += eventArgs => Task.CompletedTask;
            eventProcessor.Object.ProcessErrorAsync += eventArgs => Task.CompletedTask;

            await eventProcessor.Object.UpdateCheckpointAsync(data, context, default);

            ClientDiagnosticListener.ProducedDiagnosticScope scope = listener.Scopes.Single();
            Assert.That(scope.Name, Is.EqualTo(DiagnosticProperty.EventProcessorCheckpointActivityName));
        }
Ejemplo n.º 10
0
        public async Task PartitionPumpCreatesScopeForEventProcessing()
        {
            using ClientDiagnosticListener listener = new ClientDiagnosticListener(DiagnosticSourceName);
            var  processorCalledSource = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var  consumerMock          = new Mock <TransportConsumer>();
            bool returnedItems         = false;

            consumerMock.Setup(c => c.ReceiveAsync(It.IsAny <int>(), It.IsAny <TimeSpan?>(), It.IsAny <CancellationToken>()))
            .Returns(() =>
            {
                if (returnedItems)
                {
                    throw new InvalidOperationException("Something bad happened");
                }

                returnedItems = true;
                return(Task.FromResult(
                           (IEnumerable <EventData>) new[]
                {
                    new EventData(Array.Empty <byte>())
                    {
                        Properties =
                        {
                            { "Diagnostic-Id", "id" }
                        }
                    },
                    new EventData(Array.Empty <byte>())
                    {
                        Properties =
                        {
                            { "Diagnostic-Id", "id2" }
                        }
                    }
                }));
            });

            var connectionMock = new Mock <EventHubConnection>("namespace", "eventHubName", Mock.Of <TokenCredential>(), new EventHubConnectionOptions());

            connectionMock.Setup(c => c.CreateTransportConsumer("cg", "pid", It.IsAny <EventPosition>(), It.IsAny <EventHubsRetryPolicy>(), It.IsAny <bool>(), It.IsAny <long?>(), It.IsAny <uint?>())).Returns(consumerMock.Object);

            Func <ProcessEventArgs, ValueTask> processEventAsync = eventArgs =>
            {
                processorCalledSource.SetResult(null);
                return(new ValueTask());
            };

            // TODO: partition pump type does not exist anymore. Figure out how to call RunPartitionProcessingAsync.

            await Task.CompletedTask;

            /*
             *
             * var manager = new PartitionPump(connectionMock.Object, "cg", new PartitionContext("eventHubName", "pid"), EventPosition.Earliest, processEventAsync, new EventProcessorClientOptions());
             *
             * await manager.StartAsync();
             * await processorCalledSource.Task;
             *
             * // TODO: figure out why an exception is being thrown. The problem has always existed, but now the Pump won't swallow exceptions
             * // and throws them back to the caller.
             *
             * try
             * {
             *  await manager.StopAsync();
             * }
             * catch (InvalidOperationException) { }
             *
             */

            ClientDiagnosticListener.ProducedDiagnosticScope scope = listener.Scopes.Single();
            Assert.That(scope.Name, Is.EqualTo(DiagnosticProperty.EventProcessorProcessingActivityName));
            Assert.That(scope.Links, Has.One.EqualTo("id"));
            Assert.That(scope.Links, Has.One.EqualTo("id2"));
            Assert.That(scope.Activity.Tags, Has.One.EqualTo(new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.ServerKind)), "The activities tag should be server.");
        }
Ejemplo n.º 11
0
        public void Intercept(IInvocation invocation)
        {
            var methodName = invocation.Method.Name;

            if (methodName.EndsWith("Async"))
            {
                Type declaringType = invocation.Method.DeclaringType;
                var  ns            = declaringType.Namespace;
                var  expectedName  = declaringType.Name + "." + methodName.Substring(0, methodName.Length - 5);
                using ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure."), asyncLocal: true);
                invocation.Proceed();

                bool expectFailure = false;
                bool skipChecks    = false;

                bool strict = !invocation.Method.GetCustomAttributes(true).Any(a => a.GetType().FullName == "Azure.Core.ForwardsClientCallsAttribute");
                if (invocation.Method.ReturnType.Name.Contains("Pageable") ||
                    invocation.Method.ReturnType.Name.Contains("IAsyncEnumerable"))
                {
                    return;
                }

                try
                {
                    object returnValue = invocation.ReturnValue;
                    if (returnValue is Task t)
                    {
                        t.GetAwaiter().GetResult();
                    }
                    else
                    {
                        // Await ValueTask
                        Type       returnType       = returnValue.GetType();
                        MethodInfo getAwaiterMethod = returnType.GetMethod("GetAwaiter", BindingFlags.Instance | BindingFlags.Public);
                        MethodInfo getResultMethod  = getAwaiterMethod.ReturnType.GetMethod("GetResult", BindingFlags.Instance | BindingFlags.Public);

                        getResultMethod.Invoke(
                            getAwaiterMethod.Invoke(returnValue, Array.Empty <object>()),
                            Array.Empty <object>());
                    }
                }
                catch (Exception ex)
                {
                    expectFailure = true;

                    if (ex is ArgumentException)
                    {
                        // Don't expect scope for argument validation failures
                        skipChecks = true;
                    }
                }
                finally
                {
                    // Remove subscribers before enumerating events.
                    diagnosticListener.Dispose();
                    if (!skipChecks)
                    {
                        if (strict)
                        {
                            ClientDiagnosticListener.ProducedDiagnosticScope e = diagnosticListener.Scopes.FirstOrDefault(e => e.Name == expectedName);

                            if (e == default)
                            {
                                throw new InvalidOperationException($"Expected diagnostic scope not created {expectedName} {Environment.NewLine}    created scopes {string.Join(", ", diagnosticListener.Scopes)} {Environment.NewLine}    You may have forgotten to set your operationId to {expectedName} in {methodName} or applied the Azure.Core.ForwardsClientCallsAttribute to {methodName}.");
                            }

                            if (!e.Activity.Tags.Any(tag => tag.Key == "az.namespace"))
                            {
                                throw new InvalidOperationException($"All diagnostic scopes should have 'az.namespace' attribute, make sure the assembly containing **ClientOptions type is marked with the AzureResourceProviderNamespace attribute specifying the appropriate provider. This attribute should be included in AssemblyInfo, and can be included by pulling in AzureResourceProviderNamespaceAttribute.cs using the AzureCoreSharedSources alias.");
                            }

                            if (expectFailure && !e.IsFailed)
                            {
                                throw new InvalidOperationException($"Expected scope {expectedName} to be marked as failed but it succeeded");
                            }
                        }
                        else
                        {
                            if (!diagnosticListener.Scopes.Any())
                            {
                                throw new InvalidOperationException($"Expected some diagnostic scopes to be created, found none");
                            }
                        }
                    }
                }
            }
            else
            {
                invocation.Proceed();
            }
        }
 public void Setup()
 {
     _listener = new ClientDiagnosticListener(EntityScopeFactory.DiagnosticNamespace);
 }
        public async Task EventHubProducerCreatesDiagnosticScopeOnBatchSend()
        {
            using var testListener = new ClientDiagnosticListener(EventDataInstrumentation.DiagnosticNamespace);
            var activity = new Activity("SomeActivity").Start();

            var eventCount         = 0;
            var eventHubName       = "SomeName";
            var endpoint           = "endpoint";
            var batchEvent         = default(EventData);
            var fakeConnection     = new MockConnection(endpoint, eventHubName);
            var batchTransportMock = new Mock <TransportEventBatch>();

            batchTransportMock
            .Setup(m => m.TryAdd(It.IsAny <EventData>()))
            .Callback <EventData>(addedEvent => batchEvent = addedEvent)
            .Returns(() =>
            {
                eventCount++;
                return(eventCount <= 1);
            });

            batchTransportMock
            .Setup(m => m.Count)
            .Returns(1);

            var transportMock = new Mock <TransportProducer>();

            transportMock
            .Setup(m => m.SendAsync(It.IsAny <IEnumerable <EventData> >(), It.IsAny <SendEventOptions>(), It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask);

            transportMock
            .Setup(m => m.CreateBatchAsync(It.IsAny <CreateBatchOptions>(), It.IsAny <CancellationToken>()))
            .Returns(new ValueTask <TransportEventBatch>(Task.FromResult(batchTransportMock.Object)));

            var producer = new EventHubProducerClient(fakeConnection, transportMock.Object);

            var eventData = new EventData(ReadOnlyMemory <byte> .Empty);
            var batch     = await producer.CreateBatchAsync();

            Assert.That(batch.TryAdd(eventData), Is.True);

            await producer.SendAsync(batch);

            activity.Stop();

            ClientDiagnosticListener.ProducedDiagnosticScope sendScope = testListener.AssertScope(DiagnosticProperty.ProducerActivityName,
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.ClientKind),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.ServiceContextAttribute, DiagnosticProperty.EventHubsServiceContext),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                  new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint));

            ClientDiagnosticListener.ProducedDiagnosticScope messageScope = testListener.AssertScope(DiagnosticProperty.EventActivityName,
                                                                                                     new KeyValuePair <string, string>(DiagnosticProperty.EventHubAttribute, eventHubName),
                                                                                                     new KeyValuePair <string, string>(DiagnosticProperty.EndpointAttribute, endpoint));

            Assert.That(batchEvent.Properties[DiagnosticProperty.DiagnosticIdAttribute], Is.EqualTo(messageScope.Activity.Id), "The diagnostics identifier should match.");
            Assert.That(messageScope.Activity, Is.Not.SameAs(sendScope.Activity), "The activities should not be the same instance.");
            Assert.That(sendScope.Activity.ParentId, Is.EqualTo(activity.Id), "The send scope's parent identifier should match the activity in the active scope.");
            Assert.That(messageScope.Activity.ParentId, Is.EqualTo(activity.Id), "The message scope's parent identifier should match the activity in the active scope.");
        }
        public async Task PartitionPumpCreatesScopeForEventProcessing()
        {
            using ClientDiagnosticListener listener = new ClientDiagnosticListener(DiagnosticSourceName);
            var  processorCalledSource = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var  consumerMock          = new Mock <TransportConsumer>();
            bool returnedItems         = false;

            consumerMock.Setup(c => c.ReceiveAsync(It.IsAny <int>(), It.IsAny <TimeSpan?>(), It.IsAny <CancellationToken>()))
            .Returns(() =>
            {
                if (returnedItems)
                {
                    throw new InvalidOperationException("Something bad happened");
                }

                returnedItems = true;
                return(Task.FromResult(
                           (IEnumerable <EventData>) new[]
                {
                    new EventData(Array.Empty <byte>())
                    {
                        Properties =
                        {
                            { "Diagnostic-Id", "id" }
                        }
                    },
                    new EventData(Array.Empty <byte>())
                    {
                        Properties =
                        {
                            { "Diagnostic-Id", "id2" }
                        }
                    }
                }));
            });

            var clientMock = new Mock <EventHubConnection>();

            clientMock.Setup(c => c.CreateTransportConsumer("cg", "pid", It.IsAny <EventPosition>(), It.IsAny <EventHubConsumerClientOptions>())).Returns(consumerMock.Object);

            var eventProcessorMock = new Mock <EventProcessorClient>();

            eventProcessorMock.Object.ProcessEventAsync = processorEvent =>
            {
                processorCalledSource.SetResult(null);
                return(Task.CompletedTask);
            };

            var manager = new PartitionPump(eventProcessorMock.Object, clientMock.Object, "cg", new PartitionContext("pid"), EventPosition.Earliest, new EventProcessorClientOptions());

            await manager.StartAsync();

            await processorCalledSource.Task;
            await manager.StopAsync(null);

            ClientDiagnosticListener.ProducedDiagnosticScope scope = listener.Scopes.Single();
            Assert.That(scope.Name, Is.EqualTo(DiagnosticProperty.EventProcessorProcessingActivityName));
            Assert.That(scope.Links, Has.One.EqualTo("id"));
            Assert.That(scope.Links, Has.One.EqualTo("id2"));
            Assert.That(scope.Activity.Tags, Has.One.EqualTo(new KeyValuePair <string, string>(DiagnosticProperty.KindAttribute, DiagnosticProperty.ServerKind)), "The activities tag should be server.");
        }
        public async Task SetsTraceParentExtension(bool inclTraceparent, bool inclTracestate)
        {
            MockTransport mockTransport = CreateMockTransport();

            var options = new EventGridPublisherClientOptions
            {
                Transport = mockTransport
            };
            EventGridPublisherClient client =
                new EventGridPublisherClient(
                    new Uri("http://localHost"),
                    new AzureKeyCredential("fakeKey"),
                    options);

            using ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure."), asyncLocal: true);

            var activity = new Activity($"{nameof(EventGridPublisherClient)}.{nameof(EventGridPublisherClient.SendEvents)}");

            activity.SetW3CFormat();
            activity.Start();
            activity.TraceStateString = "tracestatevalue";
            List <CloudEvent> eventsList = new List <CloudEvent>();

            for (int i = 0; i < 10; i++)
            {
                CloudEvent cloudEvent = new CloudEvent(
                    "record",
                    "Microsoft.MockPublisher.TestEvent",
                    JsonDocument.Parse("{\"property1\": \"abc\",  \"property2\": 123}").RootElement)
                {
                    Id      = "id",
                    Subject = $"Subject-{i}",
                    Time    = DateTimeOffset.UtcNow
                };
                if (inclTraceparent && i % 2 == 0)
                {
                    cloudEvent.ExtensionAttributes.Add("traceparent", "traceparentValue");
                }
                if (inclTracestate && i % 2 == 0)
                {
                    cloudEvent.ExtensionAttributes.Add("tracestate", "param:value");
                }
                eventsList.Add(cloudEvent);
            }
            await client.SendEventsAsync(eventsList);

            // stop activity after extracting the events from the request as this is where the cloudEvents would actually
            // be serialized
            activity.Stop();

            IEnumerator <CloudEvent> cloudEnum = eventsList.GetEnumerator();

            for (int i = 0; i < 10; i++)
            {
                cloudEnum.MoveNext();
                IDictionary <string, object> cloudEventAttr = cloudEnum.Current.ExtensionAttributes;
                if (inclTraceparent && inclTracestate && i % 2 == 0)
                {
                    Assert.AreEqual(
                        "traceparentValue",
                        cloudEventAttr[TraceParentHeaderName]);

                    Assert.AreEqual(
                        "param:value",
                        cloudEventAttr[TraceStateHeaderName]);
                }
                else if (inclTraceparent && i % 2 == 0)
                {
                    Assert.AreEqual(
                        "traceparentValue",
                        cloudEventAttr[TraceParentHeaderName]);
                }
                else if (inclTracestate && i % 2 == 0)
                {
                    Assert.AreEqual(
                        "param:value",
                        cloudEventAttr[TraceStateHeaderName]);
                }
                else
                {
                    Assert.IsTrue(mockTransport.SingleRequest.Headers.TryGetValue(TraceParentHeaderName, out string requestHeader));

                    Assert.AreEqual(
                        requestHeader,
                        cloudEventAttr[TraceParentHeaderName]);
                }
            }
        }
        public async Task SessionProcessorActivities()
        {
            ClientDiagnosticListener.ProducedLink[] messageActivities = null;
            int  messageProcessedCt = 0;
            bool callbackExecuted   = false;

            _listener = new ClientDiagnosticListener(
                EntityScopeFactory.DiagnosticNamespace,
                scopeStartCallback: scope =>
            {
                if (scope.Name == DiagnosticProperty.ProcessSessionMessageActivityName)
                {
                    Assert.IsNotNull(messageActivities);
                    Assert.AreEqual(
                        messageActivities[messageProcessedCt],
                        scope.Links.Single());
                    callbackExecuted = true;
                }
            });
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: true))
            {
                var client = new ServiceBusClient(TestEnvironment.ServiceBusConnectionString);
                ServiceBusSender sender = client.CreateSender(scope.QueueName);
                var messageCt           = 2;
                var msgs = ServiceBusTestUtilities.GetMessages(messageCt, "sessionId");
                await sender.SendMessagesAsync(msgs);

                Activity[] sendActivities = AssertSendActivities(false, sender, msgs);
                messageActivities = sendActivities.Select(a => new ClientDiagnosticListener.ProducedLink(a.ParentId, a.TraceStateString)).ToArray();

                ServiceBusSessionProcessor processor = client.CreateSessionProcessor(scope.QueueName,
                                                                                     new ServiceBusSessionProcessorOptions
                {
                    AutoCompleteMessages  = false,
                    SessionIdleTimeout    = TimeSpan.FromSeconds(10),
                    MaxConcurrentSessions = 1
                });
                TaskCompletionSource <bool> tcs = new TaskCompletionSource <bool>();
                processor.ProcessMessageAsync += args =>
                {
                    if (++messageProcessedCt == messageCt)
                    {
                        tcs.SetResult(true);
                    }
                    return(Task.CompletedTask);
                };
                processor.ProcessErrorAsync += ServiceBusTestUtilities.ExceptionHandler;
                await processor.StartProcessingAsync();

                await tcs.Task;
                await processor.StopProcessingAsync();

                for (int i = 0; i < messageCt; i++)
                {
                    _listener.AssertAndRemoveScope(DiagnosticProperty.ReceiveActivityName);
                    var processScope = _listener.AssertAndRemoveScope(DiagnosticProperty.ProcessSessionMessageActivityName);
                    AssertCommonTags(processScope.Activity, processor.EntityPath, processor.FullyQualifiedNamespace);
                }
                Assert.IsTrue(callbackExecuted);
            }
        }
        public async Task RunPartitionProcessingAsyncCreatesScopeForEventProcessing()
        {
            var mockStorage   = new MockCheckPointStorage();
            var mockConsumer  = new Mock <EventHubConsumerClient>("cg", Mock.Of <EventHubConnection>(), default);
            var mockProcessor = new Mock <EventProcessorClient>(mockStorage, "cg", "ns", "eh", Mock.Of <Func <EventHubConnection> >(), default)
            {
                CallBase = true
            };

            using ClientDiagnosticListener listener = new ClientDiagnosticListener(DiagnosticSourceName);
            var completionSource  = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var processEventCalls = 0;

            mockConsumer
            .Setup(consumer => consumer.ReadEventsFromPartitionAsync(
                       It.IsAny <string>(),
                       It.IsAny <EventPosition>(),
                       It.IsAny <ReadEventOptions>(),
                       It.IsAny <CancellationToken>()))
            .Returns <string, EventPosition, ReadEventOptions, CancellationToken>((partitionId, position, options, token) =>
            {
                async IAsyncEnumerable <PartitionEvent> mockPartitionEventEnumerable()
                {
                    var context = new MockPartitionContext(partitionId);

                    yield return(new PartitionEvent(context, new EventData(Array.Empty <byte>())
                    {
                        Properties = { { "Diagnostic-Id", "id" } }
                    }));

                    yield return(new PartitionEvent(context, new EventData(Array.Empty <byte>())
                    {
                        Properties = { { "Diagnostic-Id", "id2" } }
                    }));

                    while (!completionSource.Task.IsCompleted && !token.IsCancellationRequested)
                    {
                        await Task.Delay(TimeSpan.FromSeconds(1));
                        yield return(new PartitionEvent());
                    }

                    yield break;
                };

                return(mockPartitionEventEnumerable());
            });

            mockProcessor
            .Setup(processor => processor.CreateConsumer(
                       It.IsAny <string>(),
                       It.IsAny <EventHubConnection>(),
                       It.IsAny <EventHubConsumerClientOptions>()))
            .Returns(mockConsumer.Object);

            mockProcessor.Object.ProcessEventAsync += eventArgs =>
            {
                if (++processEventCalls == 2)
                {
                    completionSource.SetResult(null);
                }

                return(Task.CompletedTask);
            };

            // RunPartitionProcessingAsync does not invoke the error handler, but we are setting it here in case
            // this fact changes in the future.

            mockProcessor.Object.ProcessErrorAsync += eventArgs => Task.CompletedTask;

            // Start processing and wait for the consumer to be invoked.  Set a cancellation for backup to ensure
            // that the test completes deterministically.

            using var cancellationSource = new CancellationTokenSource();
            cancellationSource.CancelAfter(TimeSpan.FromSeconds(15));

            using var partitionProcessingTask = Task.Run(() => mockProcessor.Object.RunPartitionProcessingAsync("pid", default, cancellationSource.Token));
Ejemplo n.º 18
0
        public async Task SetsTraceParentExtensionRetries(bool inclTraceparent, bool inclTracestate)
        {
            int requestCt     = 0;
            var mockTransport = new MockTransport((request) =>
            {
                var stream = new MemoryStream();
                request.Content.WriteTo(stream, CancellationToken.None);
                if (requestCt++ == 0)
                {
                    return(new MockResponse(500));
                }
                else
                {
                    return(new MockResponse(200));
                }
            });

            var options = new EventGridPublisherClientOptions
            {
                Transport = mockTransport
            };
            EventGridPublisherClient client =
                new EventGridPublisherClient(
                    new Uri("http://localHost"),
                    new AzureKeyCredential("fakeKey"),
                    options);

            using ClientDiagnosticListener diagnosticListener = new ClientDiagnosticListener(s => s.StartsWith("Azure."), asyncLocal: true);

            // simulating some other activity already being started before doing operations with the client
            var activity = new Activity("ParentEvent");

            activity.SetW3CFormat();
            activity.Start();
            activity.TraceStateString = "tracestatevalue";
            List <CloudEvent> eventsList = new List <CloudEvent>();

            for (int i = 0; i < 10; i++)
            {
                CloudEvent cloudEvent = new CloudEvent(
                    "record",
                    "Microsoft.MockPublisher.TestEvent",
                    JsonDocument.Parse("{\"property1\": \"abc\",  \"property2\": 123}").RootElement)
                {
                    Id      = "id",
                    Subject = $"Subject-{i}",
                    Time    = DateTimeOffset.UtcNow
                };
                if (inclTraceparent && i % 2 == 0)
                {
                    cloudEvent.ExtensionAttributes.Add("traceparent", "traceparentValue");
                }
                if (inclTracestate && i % 2 == 0)
                {
                    cloudEvent.ExtensionAttributes.Add("tracestate", "param:value");
                }
                eventsList.Add(cloudEvent);
            }
            await client.SendEventsAsync(eventsList);

            // stop activity after extracting the events from the request as this is where the cloudEvents would actually
            // be serialized
            activity.Stop();

            IEnumerator <CloudEvent> cloudEnum = eventsList.GetEnumerator();

            for (int i = 0; i < 10; i++)
            {
                cloudEnum.MoveNext();
                IDictionary <string, object> cloudEventAttr = cloudEnum.Current.ExtensionAttributes;
                if (inclTraceparent && inclTracestate && i % 2 == 0)
                {
                    Assert.AreEqual(
                        "traceparentValue",
                        cloudEventAttr[TraceParentHeaderName]);

                    Assert.AreEqual(
                        "param:value",
                        cloudEventAttr[TraceStateHeaderName]);
                }
                else if (inclTraceparent && i % 2 == 0)
                {
                    Assert.AreEqual(
                        "traceparentValue",
                        cloudEventAttr[TraceParentHeaderName]);
                }
                else if (inclTracestate && i % 2 == 0)
                {
                    Assert.AreEqual(
                        "param:value",
                        cloudEventAttr[TraceStateHeaderName]);
                }
                else
                {
                    Assert.IsTrue(mockTransport.Requests[1].Headers.TryGetValue(TraceParentHeaderName, out string traceParent));
                    Assert.AreEqual(
                        traceParent,
                        cloudEventAttr[TraceParentHeaderName]);

                    Assert.IsTrue(mockTransport.Requests[1].Headers.TryGetValue(TraceStateHeaderName, out string traceState));
                    Assert.AreEqual(
                        traceState,
                        cloudEventAttr[TraceStateHeaderName]);
                }
            }
        }