public async Task SendAsync_SentryTraceHeaderAlreadySet_NotOverwritten() { // Arrange var hub = Substitute.For <IHub>(); hub.GetTraceHeader().ReturnsForAnyArgs( SentryTraceHeader.Parse("75302ac48a024bde9a3b3734a82e36c8-1000000000000000-0") ); using var innerHandler = new RecordingHttpMessageHandler(new FakeHttpMessageHandler()); using var sentryHandler = new SentryHttpMessageHandler(innerHandler, hub); using var client = new HttpClient(sentryHandler); client.DefaultRequestHeaders.Add("sentry-trace", "foobar"); // Act await client.GetAsync("https://example.com/"); using var request = innerHandler.GetRequests().Single(); // Assert request.Headers.Should().Contain(h => h.Key == "sentry-trace" && string.Concat(h.Value) == "foobar" ); }
public async Task TeamsSendToGeneralChannelAsync() { // Arrange var inboundActivity = new Activity { Type = ActivityTypes.Message, Conversation = new ConversationAccount { Id = "originalId" }, ChannelData = new TeamsChannelData { Team = new TeamInfo { Id = "team123" } }, }; var turnContext = new TurnContext(new SimpleAdapter((Activity[] arg) => { }), inboundActivity); var baseUri = new Uri("http://no-where"); var credentials = new MicrosoftAppCredentials(string.Empty, string.Empty); var messageHandler = new RecordingHttpMessageHandler(); turnContext.TurnState.Add <IConnectorClient>(new ConnectorClient(baseUri, credentials, new HttpClient(messageHandler))); // Act var(conversationReference, activityId) = await turnContext.TeamsSendToGeneralChannelAsync(MessageFactory.Text("hi")); // Assert Assert.AreEqual("ConversationId", conversationReference.Conversation.Id); Assert.AreEqual("ActivityId", activityId); }
public async Task SendEnvelopeAsync_AttachmentTooLarge_DropsItem() { // Arrange using var httpHandler = new RecordingHttpMessageHandler( new FakeHttpMessageHandler() ); var logger = new InMemoryDiagnosticLogger(); var httpTransport = new HttpTransport( new SentryOptions { Dsn = DsnSamples.ValidDsnWithSecret, MaxAttachmentSize = 1, DiagnosticLogger = logger, Debug = true }, new HttpClient(httpHandler) ); var attachmentNormal = new Attachment( AttachmentType.Default, new StreamAttachmentContent(new MemoryStream(new byte[] { 1 })), "test1.txt", null ); var attachmentTooBig = new Attachment( AttachmentType.Default, new StreamAttachmentContent(new MemoryStream(new byte[] { 1, 2, 3, 4, 5 })), "test2.txt", null ); using var envelope = Envelope.FromEvent( new SentryEvent(), new[] { attachmentNormal, attachmentTooBig } ); // Act await httpTransport.SendEnvelopeAsync(envelope); var lastRequest = httpHandler.GetRequests().Last(); var actualEnvelopeSerialized = await lastRequest.Content.ReadAsStringAsync(); // Assert // (the envelope should have only one item) logger.Entries.Should().Contain(e => e.Message == "Attachment '{0}' dropped because it's too large ({1} bytes)." && e.Args[0].ToString() == "test2.txt" && e.Args[1].ToString() == "5" ); actualEnvelopeSerialized.Should().NotContain("test2.txt"); }
public async Task SendEnvelopeAsync_AttachmentFail_DropsItem() { // Arrange using var httpHandler = new RecordingHttpMessageHandler( new FakeHttpMessageHandler()); var logger = new InMemoryDiagnosticLogger(); var httpTransport = new HttpTransport( new SentryOptions { Dsn = DsnSamples.ValidDsnWithSecret, MaxAttachmentSize = 1, DiagnosticLogger = logger, Debug = true }, new HttpClient(httpHandler)); var attachment = new Attachment( AttachmentType.Default, new FileAttachmentContent("test1.txt"), "test1.txt", null); using var envelope = Envelope.FromEvent( new SentryEvent(), logger, new[] { attachment }); // Act await httpTransport.SendEnvelopeAsync(envelope); var lastRequest = httpHandler.GetRequests().Last(); var actualEnvelopeSerialized = await lastRequest.Content.ReadAsStringAsync(); // Assert // (the envelope should have only one item) logger.Entries.Should().Contain(e => e.Message == "Failed to add attachment: {0}." && (string)e.Args[0] == "test1.txt"); actualEnvelopeSerialized.Should().NotContain("test2.txt"); }
public async Task SendEnvelopeAsync_ItemRateLimit_DoesNotAffectNextSessionWithDifferentId() { // Arrange using var httpHandler = new RecordingHttpMessageHandler( new FakeHttpMessageHandler( () => SentryResponses.GetRateLimitResponse("1:session") ) ); var httpTransport = new HttpTransport( new SentryOptions { Dsn = DsnSamples.ValidDsnWithSecret }, new HttpClient(httpHandler) ); var session = new Session("foo", "bar", "baz"); // First request always goes through await httpTransport.SendEnvelopeAsync(Envelope.FromEvent(new SentryEvent())); // Send session update with init=true await httpTransport.SendEnvelopeAsync(Envelope.FromEvent(new SentryEvent(), null, session.CreateUpdate(true, DateTimeOffset.Now))); // Pretend the rate limit has already passed foreach (var(category, _) in httpTransport.CategoryLimitResets) { httpTransport.CategoryLimitResets[category] = DateTimeOffset.Now - TimeSpan.FromDays(1); } // Act // Send an update for different session with init=false (should NOT get promoted) var nextSession = new Session("foo2", "bar2", "baz2"); await httpTransport.SendEnvelopeAsync(Envelope.FromEvent(new SentryEvent(), null, nextSession.CreateUpdate(false, DateTimeOffset.Now))); var lastRequest = httpHandler.GetRequests().Last(); var actualEnvelopeSerialized = await lastRequest.Content.ReadAsStringAsync(); // Assert actualEnvelopeSerialized.Should().NotContain("\"init\":true"); }
public RecordingHandlerBuilderFilter(RecordingHttpMessageHandler handler) => _handler = handler;
public async Task SendEnvelopeAsync_ItemRateLimit_DropsItem() { // Arrange using var httpHandler = new RecordingHttpMessageHandler( new FakeHttpMessageHandler( () => SentryResponses.GetRateLimitResponse("1234:event, 897:transaction") )); var httpTransport = new HttpTransport( new SentryOptions { Dsn = DsnSamples.ValidDsnWithSecret }, new HttpClient(httpHandler)); // First request always goes through await httpTransport.SendEnvelopeAsync(Envelope.FromEvent(new SentryEvent())); var envelope = new Envelope( new Dictionary <string, object>(), new[] { // Should be dropped new EnvelopeItem( new Dictionary <string, object> { ["type"] = "event" }, new EmptySerializable()), new EnvelopeItem( new Dictionary <string, object> { ["type"] = "event" }, new EmptySerializable()), new EnvelopeItem( new Dictionary <string, object> { ["type"] = "transaction" }, new EmptySerializable()), // Should stay new EnvelopeItem( new Dictionary <string, object> { ["type"] = "other" }, new EmptySerializable()) }); var expectedEnvelope = new Envelope( new Dictionary <string, object>(), new[] { new EnvelopeItem( new Dictionary <string, object> { ["type"] = "other" }, new EmptySerializable()) }); var expectedEnvelopeSerialized = await expectedEnvelope.SerializeToStringAsync(); // Act await httpTransport.SendEnvelopeAsync(envelope); var lastRequest = httpHandler.GetRequests().Last(); var actualEnvelopeSerialized = await lastRequest.Content.ReadAsStringAsync(); // Assert actualEnvelopeSerialized.Should().BeEquivalentTo(expectedEnvelopeSerialized); }
public async Task ScenarioWithInspectionMiddlwareOpenAttach() { // Arrange // any bot state should be returned as trace messages per turn var storage = new MemoryStorage(); var inspectionState = new InspectionState(storage); var userState = new UserState(storage); var conversationState = new ConversationState(storage); // set up the middleware with an http client that will just record the traffic - we are expecting the trace activities here var recordingHttpClient = new RecordingHttpMessageHandler(); var inspectionMiddleware = new TestInspectionMiddleware( inspectionState, userState, conversationState, new HttpClient(recordingHttpClient)); // Act // (1) send the /INSPECT open command from the emulator to the middleware var openActivity = MessageFactory.Text("/INSPECT open"); var inspectionAdapter = new TestAdapter(Channels.Test, true); await inspectionAdapter.ProcessActivityAsync(openActivity, async (turnContext, cancellationToken) => { await inspectionMiddleware.ProcessCommandAsync(turnContext); }); var inspectionOpenResultActivity = inspectionAdapter.ActiveQueue.Dequeue(); // (2) send the resulting /INSPECT attach command from the channel to the middleware var applicationAdapter = new TestAdapter(Channels.Test, true); applicationAdapter.Use(inspectionMiddleware); var attachCommand = inspectionOpenResultActivity.Value.ToString(); await applicationAdapter.ProcessActivityAsync(MessageFactory.Text(attachCommand), async (turnContext, cancellationToken) => { // nothing happens - just attach the inspector await Task.CompletedTask; }); var attachResponse = applicationAdapter.ActiveQueue.Dequeue(); // (3) send an application messaage from the channel, it should get the reply and then so should the emulator http endpioint await applicationAdapter.ProcessActivityAsync(MessageFactory.Text("hi"), async (turnContext, cancellationToken) => { await turnContext.SendActivityAsync(MessageFactory.Text($"echo: {turnContext.Activity.Text}")); (await userState.CreateProperty <Scratch>("x").GetAsync(turnContext, () => new Scratch())).Property = "hello"; (await conversationState.CreateProperty <Scratch>("y").GetAsync(turnContext, () => new Scratch())).Property = "world"; await userState.SaveChangesAsync(turnContext); await conversationState.SaveChangesAsync(turnContext); }); // Assert var outboundActivity = applicationAdapter.ActiveQueue.Dequeue(); Assert.AreEqual("echo: hi", outboundActivity.Text); Assert.AreEqual(3, recordingHttpClient.Requests.Count); var inboundTrace = JObject.Parse(recordingHttpClient.Requests[0]); Assert.AreEqual("trace", inboundTrace["type"].ToString()); Assert.AreEqual("ReceivedActivity", inboundTrace["name"].ToString()); Assert.AreEqual("message", inboundTrace["value"]["type"].ToString()); Assert.AreEqual("hi", inboundTrace["value"]["text"].ToString()); var outboundTrace = JObject.Parse(recordingHttpClient.Requests[1]); Assert.AreEqual("trace", outboundTrace["type"].ToString()); Assert.AreEqual("SentActivity", outboundTrace["name"].ToString()); Assert.AreEqual("message", outboundTrace["value"]["type"].ToString()); Assert.AreEqual("echo: hi", outboundTrace["value"]["text"].ToString()); var stateTrace = JObject.Parse(recordingHttpClient.Requests[2]); Assert.AreEqual("trace", stateTrace["type"].ToString()); Assert.AreEqual("BotState", stateTrace["name"].ToString()); Assert.AreEqual("hello", stateTrace["value"]["userState"]["x"]["Property"].ToString()); Assert.AreEqual("world", stateTrace["value"]["conversationState"]["y"]["Property"].ToString()); }
public async Task ScenarioWithInspectionMiddlwareOpenAttachAndTracePassThrough() { // Arrange // any bot state should be returned as trace messages per turn var storage = new MemoryStorage(); var inspectionState = new InspectionState(storage); // set up the middleware with an http client that will just record the traffic - we are expecting the trace activities here var recordingHttpClient = new RecordingHttpMessageHandler(); var inspectionMiddleware = new TestInspectionMiddleware( inspectionState, null, null, new HttpClient(recordingHttpClient)); // Act // (1) send the /INSPECT open command from the emulator to the middleware var openActivity = MessageFactory.Text("/INSPECT open"); var inspectionAdapter = new TestAdapter(Channels.Test, true); await inspectionAdapter.ProcessActivityAsync(openActivity, async (turnContext, cancellationToken) => { await inspectionMiddleware.ProcessCommandAsync(turnContext); }); var inspectionOpenResultActivity = inspectionAdapter.ActiveQueue.Dequeue(); // (2) send the resulting /INSPECT attach command from the channel to the middleware var applicationAdapter = new TestAdapter(Channels.Test, true); applicationAdapter.Use(inspectionMiddleware); var attachCommand = inspectionOpenResultActivity.Value.ToString(); await applicationAdapter.ProcessActivityAsync(MessageFactory.Text(attachCommand), async (turnContext, cancellationToken) => { // nothing happens - just attach the inspector await Task.CompletedTask; }); var attachResponse = applicationAdapter.ActiveQueue.Dequeue(); // (3) send an application messaage from the channel, it should get the reply and then so should the emulator http endpioint await applicationAdapter.ProcessActivityAsync(MessageFactory.Text("hi"), async (turnContext, cancellationToken) => { var activity = (Activity)Activity.CreateTraceActivity("CustomTrace"); await turnContext.SendActivityAsync(activity); }); // Assert var outboundActivity = applicationAdapter.ActiveQueue.Dequeue(); Assert.AreEqual("CustomTrace", outboundActivity.Name); Assert.AreEqual(2, recordingHttpClient.Requests.Count); var inboundTrace = JObject.Parse(recordingHttpClient.Requests[0]); Assert.AreEqual("trace", inboundTrace["type"].ToString()); Assert.AreEqual("ReceivedActivity", inboundTrace["name"].ToString()); Assert.AreEqual("message", inboundTrace["value"]["type"].ToString()); Assert.AreEqual("hi", inboundTrace["value"]["text"].ToString()); var outboundTrace = JObject.Parse(recordingHttpClient.Requests[1]); Assert.AreEqual("trace", outboundTrace["type"].ToString()); Assert.AreEqual("CustomTrace", outboundTrace["name"].ToString()); }