Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Deno.serve({ port, hostname: '0.0.0.0' }, async (req: Request) => {
}

// node-redis: SET then GET — exercises two commands inside a single
// transaction so we can assert the parent has two db.redis children.
// transaction so we can assert the parent has two db.query children.
if (url.pathname === '/redis-set-get') {
const key = url.searchParams.get('key') ?? 'cache:key';
const value = url.searchParams.get('value') ?? 'hello';
Expand Down Expand Up @@ -89,7 +89,7 @@ Deno.serve({ port, hostname: '0.0.0.0' }, async (req: Request) => {

// ioredis: MULTI — ioredis has no separate batch channel; per-command
// payloads carry `batchMode`/`batchSize` instead, so we still expect one
// db.redis span per command.
// db.query span per command.
if (url.pathname === '/ioredis-multi') {
const result = await ioredis.multi().set('iomulti:a', '1').set('iomulti:b', '2').get('iomulti:a').exec();
return Response.json({ result });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { expect, test } from '@playwright/test';
import { waitForTransaction } from '@sentry-internal/test-utils';

test('ioredis GET emits an http.server transaction containing a db.redis child span', async ({ baseURL }) => {
test('ioredis GET emits an http.server transaction containing a db.query child span', async ({ baseURL }) => {
// Each incoming request gets a Sentry http.server transaction (via the
// default denoServeIntegration); the ioredis command runs inside it, so the
// child span attaches to that transaction.
const transactionPromise = waitForTransaction('deno-redis', event => {
return (
event?.contexts?.trace?.op === 'http.server' &&
(event.request?.url ?? '').includes('/ioredis-get') &&
(event.spans?.some(span => span.op === 'db.redis') ?? false)
(event.spans?.some(span => span.op === 'db.query') ?? false)
);
});

Expand All @@ -18,20 +18,20 @@ test('ioredis GET emits an http.server transaction containing a db.redis child s
await res.json();

const transaction = await transactionPromise;
const redisSpan = transaction.spans!.find(span => span.op === 'db.redis');
const redisSpan = transaction.spans!.find(span => span.op === 'db.query');
expect(redisSpan).toBeDefined();
// ioredis publishes lowercase command names; node-redis publishes uppercase.
expect(redisSpan!.description).toBe('redis-get');
expect(redisSpan!.data?.['db.system.name']).toBe('redis');
expect(redisSpan!.data?.['db.query.text']).toBe('get iocache:user:42');
});

test('ioredis SET then GET emit two db.redis child spans on the same transaction', async ({ baseURL }) => {
test('ioredis SET then GET emit two db.query child spans on the same transaction', async ({ baseURL }) => {
const transactionPromise = waitForTransaction('deno-redis', event => {
return (
event?.contexts?.trace?.op === 'http.server' &&
(event.request?.url ?? '').includes('/ioredis-set-get') &&
(event.spans?.filter(span => span.op === 'db.redis').length ?? 0) >= 2
(event.spans?.filter(span => span.op === 'db.query').length ?? 0) >= 2
);
});

Expand All @@ -40,14 +40,14 @@ test('ioredis SET then GET emit two db.redis child spans on the same transaction
await res.json();

const transaction = await transactionPromise;
const redisSpans = transaction.spans!.filter(span => span.op === 'db.redis');
const redisSpans = transaction.spans!.filter(span => span.op === 'db.query');
expect(redisSpans.length).toBeGreaterThanOrEqual(2);
const ops = redisSpans.map(s => s.description);
expect(ops).toContain('redis-set');
expect(ops).toContain('redis-get');
});

test('ioredis MULTI emits one db.redis span per command (no batch channel)', async ({ baseURL }) => {
test('ioredis MULTI emits one db.query span per command (no batch channel)', async ({ baseURL }) => {
// ioredis does not publish to a batch channel — each command in the
// transaction publishes individually with batchMode/batchSize set on its
// own payload. So the transaction should contain multiple `redis-<cmd>`
Expand All @@ -56,7 +56,7 @@ test('ioredis MULTI emits one db.redis span per command (no batch channel)', asy
return (
event?.contexts?.trace?.op === 'http.server' &&
(event.request?.url ?? '').includes('/ioredis-multi') &&
(event.spans?.filter(span => span.op === 'db.redis').length ?? 0) >= 3
(event.spans?.filter(span => span.op === 'db.query').length ?? 0) >= 3
);
});

Expand All @@ -65,7 +65,7 @@ test('ioredis MULTI emits one db.redis span per command (no batch channel)', asy
await res.json();

const transaction = await transactionPromise;
const redisSpans = transaction.spans!.filter(span => span.op === 'db.redis');
const redisSpans = transaction.spans!.filter(span => span.op === 'db.query');
expect(redisSpans.length).toBeGreaterThanOrEqual(3);
const descriptions = redisSpans.map(s => s.description);
expect(descriptions).toContain('redis-set');
Expand All @@ -75,12 +75,12 @@ test('ioredis MULTI emits one db.redis span per command (no batch channel)', asy
expect(batchSpan).toBeUndefined();
});

test('ioredis PIPELINE emits one db.redis span per command', async ({ baseURL }) => {
test('ioredis PIPELINE emits one db.query span per command', async ({ baseURL }) => {
const transactionPromise = waitForTransaction('deno-redis', event => {
return (
event?.contexts?.trace?.op === 'http.server' &&
(event.request?.url ?? '').includes('/ioredis-pipeline') &&
(event.spans?.filter(span => span.op === 'db.redis').length ?? 0) >= 3
(event.spans?.filter(span => span.op === 'db.query').length ?? 0) >= 3
);
});

Expand All @@ -89,6 +89,6 @@ test('ioredis PIPELINE emits one db.redis span per command', async ({ baseURL })
await res.json();

const transaction = await transactionPromise;
const redisSpans = transaction.spans!.filter(span => span.op === 'db.redis');
const redisSpans = transaction.spans!.filter(span => span.op === 'db.query');
expect(redisSpans.length).toBeGreaterThanOrEqual(3);
});
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { expect, test } from '@playwright/test';
import { waitForTransaction } from '@sentry-internal/test-utils';

test('GET command emits an http.server transaction containing a db.redis child span', async ({ baseURL }) => {
test('GET command emits an http.server transaction containing a db.query child span', async ({ baseURL }) => {
// Each incoming request gets a Sentry http.server transaction (via the
// default denoServeIntegration); the redis command runs inside it, so the
// child span attaches to that transaction.
const transactionPromise = waitForTransaction('deno-redis', event => {
return (
event?.contexts?.trace?.op === 'http.server' &&
(event.request?.url ?? '').includes('/redis-get') &&
(event.spans?.some(span => span.op === 'db.redis') ?? false)
(event.spans?.some(span => span.op === 'db.query') ?? false)
);
});

Expand All @@ -18,7 +18,7 @@ test('GET command emits an http.server transaction containing a db.redis child s
await res.json();

const transaction = await transactionPromise;
const redisSpan = transaction.spans!.find(span => span.op === 'db.redis');
const redisSpan = transaction.spans!.find(span => span.op === 'db.query');
expect(redisSpan).toBeDefined();
expect(redisSpan!.description).toBe('redis-GET');
expect(redisSpan!.data?.['db.system.name']).toBe('redis');
Expand All @@ -27,12 +27,12 @@ test('GET command emits an http.server transaction containing a db.redis child s
expect(redisSpan!.data?.['server.port']).toBe(6379);
});

test('SET then GET emit two db.redis child spans on the same transaction', async ({ baseURL }) => {
test('SET then GET emit two db.query child spans on the same transaction', async ({ baseURL }) => {
const transactionPromise = waitForTransaction('deno-redis', event => {
return (
event?.contexts?.trace?.op === 'http.server' &&
(event.request?.url ?? '').includes('/redis-set-get') &&
(event.spans?.filter(span => span.op === 'db.redis').length ?? 0) >= 2
(event.spans?.filter(span => span.op === 'db.query').length ?? 0) >= 2
);
});

Expand All @@ -41,7 +41,7 @@ test('SET then GET emit two db.redis child spans on the same transaction', async
await res.json();

const transaction = await transactionPromise;
const redisSpans = transaction.spans!.filter(span => span.op === 'db.redis');
const redisSpans = transaction.spans!.filter(span => span.op === 'db.query');
expect(redisSpans.length).toBeGreaterThanOrEqual(2);
const ops = redisSpans.map(s => s.description);
expect(ops).toContain('redis-SET');
Expand All @@ -64,7 +64,7 @@ test('MULTI batch emits a PIPELINE/MULTI batch span', async ({ baseURL }) => {
const transaction = await transactionPromise;
const batchSpan = transaction.spans!.find(span => span.description === 'MULTI' || span.description === 'PIPELINE');
expect(batchSpan).toBeDefined();
expect(batchSpan!.op).toBe('db.redis');
expect(batchSpan!.op).toBe('db.query');
expect(batchSpan!.data?.['db.system.name']).toBe('redis');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { waitForTransaction } from '@sentry-internal/test-utils';
import { APP_NAME } from '../constants';

test.describe('server - redis db spans (instrumentation API)', () => {
test('OTel db.redis spans nest under the native instrumentation-API http.server transaction', async ({ page }) => {
test('OTel db.query spans nest under the native instrumentation-API http.server transaction', async ({ page }) => {
const txPromise = waitForTransaction(APP_NAME, async transactionEvent => {
return (
transactionEvent.transaction === 'GET /performance/redis' &&
(transactionEvent.spans?.some(span => span.op === 'db.redis') ?? false)
(transactionEvent.spans?.some(span => span.op === 'db.query') ?? false)
);
});

Expand All @@ -24,7 +24,7 @@ test.describe('server - redis db spans (instrumentation API)', () => {
const rootSpanId = transaction.contexts?.trace?.span_id;
const spanIds = new Set([rootSpanId, ...(transaction.spans ?? []).map(span => span.span_id)]);

const redisSpans = transaction.spans!.filter(span => span.op === 'db.redis');
const redisSpans = transaction.spans!.filter(span => span.op === 'db.query');

// loader runs SET then GET => at least two redis command spans
expect(redisSpans.length).toBeGreaterThanOrEqual(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { waitForTransaction } from '@sentry-internal/test-utils';
import { APP_NAME } from '../constants';

test.describe('server - redis db spans', () => {
test('server loader emits db.redis child spans on the http.server transaction', async ({ page }) => {
test('server loader emits db.query child spans on the http.server transaction', async ({ page }) => {
const txPromise = waitForTransaction(APP_NAME, async transactionEvent => {
return (
transactionEvent.transaction === 'GET /performance/redis' &&
(transactionEvent.spans?.some(span => span.op === 'db.redis') ?? false)
(transactionEvent.spans?.some(span => span.op === 'db.query') ?? false)
);
});

Expand All @@ -21,7 +21,7 @@ test.describe('server - redis db spans', () => {
const rootSpanId = transaction.contexts?.trace?.span_id;
const spanIds = new Set([rootSpanId, ...(transaction.spans ?? []).map(span => span.span_id)]);

const redisSpans = transaction.spans!.filter(span => span.op === 'db.redis');
const redisSpans = transaction.spans!.filter(span => span.op === 'db.query');

// loader runs SET then GET => at least two redis command spans
expect(redisSpans.length).toBeGreaterThanOrEqual(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { waitForTransaction } from '@sentry-internal/test-utils';
import { APP_NAME } from '../constants';

test.describe('server - redis db spans', () => {
test('server loader emits db.redis child spans on the http.server transaction', async ({ page }) => {
test('server loader emits db.query child spans on the http.server transaction', async ({ page }) => {
const txPromise = waitForTransaction(APP_NAME, async transactionEvent => {
return (
transactionEvent.transaction === 'GET /performance/redis' &&
(transactionEvent.spans?.some(span => span.op === 'db.redis') ?? false)
(transactionEvent.spans?.some(span => span.op === 'db.query') ?? false)
);
});

Expand All @@ -21,7 +21,7 @@ test.describe('server - redis db spans', () => {
const rootSpanId = transaction.contexts?.trace?.span_id;
const spanIds = new Set([rootSpanId, ...(transaction.spans ?? []).map(span => span.span_id)]);

const redisSpans = transaction.spans!.filter(span => span.op === 'db.redis');
const redisSpans = transaction.spans!.filter(span => span.op === 'db.query');

// loader runs SET then GET => at least two redis command spans
expect(redisSpans.length).toBeGreaterThanOrEqual(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ describeWithDockerCompose(
transaction: 'Test Span IORedis 5.11 DC',
spans: expect.arrayContaining([
expect.objectContaining({
op: 'db.redis',
op: 'db.query',
origin: 'auto.db.redis.diagnostic_channel',
data: expect.objectContaining({
'sentry.op': 'db.redis',
'sentry.op': 'db.query',
'sentry.origin': 'auto.db.redis.diagnostic_channel',
'db.system.name': 'redis',
'db.query.text': 'set dc-test-key ?',
Expand Down Expand Up @@ -45,10 +45,10 @@ describeWithDockerCompose(
}),
}),
expect.objectContaining({
op: 'db.redis',
op: 'db.query',
origin: 'auto.db.redis.diagnostic_channel',
data: expect.objectContaining({
'sentry.op': 'db.redis',
'sentry.op': 'db.query',
'sentry.origin': 'auto.db.redis.diagnostic_channel',
'db.system.name': 'redis',
'db.query.text': 'get dc-test-key',
Expand Down Expand Up @@ -78,10 +78,10 @@ describeWithDockerCompose(
}),
}),
expect.objectContaining({
op: 'db.redis',
op: 'db.query',
origin: 'auto.db.redis.diagnostic_channel',
data: expect.objectContaining({
'sentry.op': 'db.redis',
'sentry.op': 'db.query',
'sentry.origin': 'auto.db.redis.diagnostic_channel',
'db.system.name': 'redis',
'db.query.text': 'mget ? ? ?',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory
? [
expect.objectContaining({
description: 'MULTI',
op: 'db.redis',
op: 'db.query',
origin: redisOrigin,
data: expect.objectContaining({
'sentry.origin': redisOrigin,
Expand Down Expand Up @@ -286,7 +286,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory
// a failing command produces a span with an error status
expect.objectContaining({
description: 'INCR redis-test-key',
op: 'db',
op: isOrchestrionEnabled() ? 'db.query' : 'db',
status: 'internal_error',
origin: redisOrigin,
data: expect.objectContaining({
Expand Down Expand Up @@ -321,7 +321,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory
? [
expect.objectContaining({
description: 'MULTI',
op: 'db.redis',
op: 'db.query',
origin: redisOrigin,
data: expect.objectContaining({
'sentry.origin': redisOrigin,
Expand Down Expand Up @@ -439,7 +439,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory
// a failing command produces a span with an error status
expect.objectContaining({
description: 'INCR redis-5-test-key',
op: 'db',
op: isOrchestrionEnabled() ? 'db.query' : 'db',
status: 'internal_error',
origin: redisOrigin,
data: expect.objectContaining({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ describeWithDockerCompose(
transaction: 'Test Span Redis 5 DC',
spans: expect.arrayContaining([
expect.objectContaining({
op: 'db.redis',
op: 'db.query',
origin: 'auto.db.redis.diagnostic_channel',
data: expect.objectContaining({
'sentry.op': 'db.redis',
'sentry.op': 'db.query',
'sentry.origin': 'auto.db.redis.diagnostic_channel',
'db.system.name': 'redis',
'db.query.text': 'SET dc-test-key ?',
Expand Down Expand Up @@ -47,10 +47,10 @@ describeWithDockerCompose(
}),
}),
expect.objectContaining({
op: 'db.redis',
op: 'db.query',
origin: 'auto.db.redis.diagnostic_channel',
data: expect.objectContaining({
'sentry.op': 'db.redis',
'sentry.op': 'db.query',
'sentry.origin': 'auto.db.redis.diagnostic_channel',
'db.system.name': 'redis',
'db.query.text': 'GET dc-test-key',
Expand Down Expand Up @@ -82,12 +82,12 @@ describeWithDockerCompose(
}),
}),
// MGET: node-redis sanitizes args for diagnostics_channel (keys become '?'),
// so cache detection cannot match prefixes — remains a plain db.redis span.
// so cache detection cannot match prefixes — remains a plain db.query span.
expect.objectContaining({
op: 'db.redis',
op: 'db.query',
origin: 'auto.db.redis.diagnostic_channel',
data: expect.objectContaining({
'sentry.op': 'db.redis',
'sentry.op': 'db.query',
'sentry.origin': 'auto.db.redis.diagnostic_channel',
'db.system.name': 'redis',
'db.query.text': 'MGET ? ? ?',
Expand Down
Loading
Loading