diff --git a/static/app/components/seer/markdown/embeds/components/log/log.spec.tsx b/static/app/components/seer/markdown/embeds/components/log/log.spec.tsx
index 4c269d22a92c..38702ebdec16 100644
--- a/static/app/components/seer/markdown/embeds/components/log/log.spec.tsx
+++ b/static/app/components/seer/markdown/embeds/components/log/log.spec.tsx
@@ -128,6 +128,23 @@ describe('Seer log embed', () => {
);
});
+ it('renders an ANSI-colored message without escape codes', async () => {
+ mockLogDetails([
+ {
+ name: OurLogKnownFieldKey.MESSAGE,
+ type: 'str',
+ value: '\x1B[31mPayment\x1B[0m provider timed out',
+ },
+ ...ATTRIBUTES.slice(1),
+ ]);
+
+ renderLog();
+
+ const colored = await screen.findByText('Payment');
+ expect(colored.style.color).toContain('color-mix(in srgb,');
+ expect(colored.parentElement).toHaveTextContent(/^Payment provider timed out$/);
+ });
+
it('renders on a page that never initialized page filters', async () => {
// Seer renders from the organization layout, so it appears on plenty of
// pages that mount no PageFiltersContainer -- the stories page among them.
diff --git a/static/app/components/seer/markdown/embeds/components/log/logBlock.tsx b/static/app/components/seer/markdown/embeds/components/log/logBlock.tsx
index abc820a50d94..24efe6186ba9 100644
--- a/static/app/components/seer/markdown/embeds/components/log/logBlock.tsx
+++ b/static/app/components/seer/markdown/embeds/components/log/logBlock.tsx
@@ -5,6 +5,7 @@ import {useQuery} from '@tanstack/react-query';
import {Flex, Stack} from '@sentry/scraps/layout';
import {Text} from '@sentry/scraps/text';
+import {AnsiText} from 'sentry/components/ansiText';
import {LoadingIndicator} from 'sentry/components/loadingIndicator';
import {ALL_ACCESS_PROJECTS} from 'sentry/components/pageFilters/constants';
import {LogAttributesView} from 'sentry/components/seer/markdown/embeds/components/log/logAttributesView';
@@ -336,7 +337,7 @@ export default function LogBlock(props: LogData) {
- {String(message ?? '')}
+ {String(message ?? '')}