Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.8k
ref(node): Streamline redis instrumentation#21582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import * as Sentry from '@sentry/node'; | ||
| import { loggingTransport } from '@sentry-internal/node-integration-tests'; | ||
| Sentry.init({ | ||
| dsn: 'https://public@dsn.ingest.sentry.io/1337', | ||
| release: '1.0', | ||
| tracesSampleRate: 1.0, | ||
| transport: loggingTransport, | ||
| integrations: [Sentry.redisIntegration({ cachePrefixes: ['redis-5-cache:'] })], | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import * as Sentry from '@sentry/node'; | ||
| import { createClient } from 'redis-5'; | ||
| async function run() { | ||
| const redisClient = await createClient().connect(); | ||
| await Sentry.startSpan( | ||
| { | ||
| name: 'Test Span Redis 5', | ||
| op: 'test-span-redis-5', | ||
| }, | ||
| async () => { | ||
| try { | ||
| await redisClient.set('redis-5-test-key', 'test-value'); | ||
| await redisClient.set('redis-5-cache:test-key', 'test-value'); | ||
| await redisClient.set('redis-5-cache:test-key-set-EX', 'test-value', { EX: 10 }); | ||
| await redisClient.setEx('redis-5-cache:test-key-setex', 10, 'test-value'); | ||
| await redisClient.get('redis-5-test-key'); | ||
| await redisClient.get('redis-5-cache:test-key'); | ||
| await redisClient.get('redis-5-cache:unavailable-data'); | ||
| await redisClient.mGet(['redis-5-test-key', 'redis-5-cache:test-key', 'redis-5-cache:unavailable-data']); | ||
| // MULTI/EXEC produces one span per queued command, all ended together on exec | ||
| await redisClient.multi().set('redis-5-multi-key', 'multi-value').get('redis-5-multi-key').exec(); | ||
| // a failing command should produce a span with an error status | ||
| // (INCR on a non-integer string value rejects) | ||
| await redisClient.incr('redis-5-test-key').catch(() => {}); | ||
| } finally { | ||
| await redisClient.disconnect(); | ||
| } | ||
| }, | ||
| ); | ||
| } | ||
| run(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -232,6 +232,39 @@ describe('redis cache auto instrumentation', () => { | ||
| 'cache.key': ['redis-test-key', 'redis-cache:test-key', 'redis-cache:unavailable-data'], | ||
| }), | ||
| }), | ||
| // MULTI/EXEC: one span per queued command | ||
| expect.objectContaining({ | ||
| description: 'SET redis-multi-key [1 other arguments]', | ||
| op: 'db', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.system': 'redis', | ||
| 'db.statement': 'SET redis-multi-key [1 other arguments]', | ||
| }), | ||
| }), | ||
| expect.objectContaining({ | ||
| description: 'GET redis-multi-key', | ||
| op: 'db', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.system': 'redis', | ||
| 'db.statement': 'GET redis-multi-key', | ||
| }), | ||
| }), | ||
| // a failing command produces a span with an error status | ||
| expect.objectContaining({ | ||
| description: 'INCR redis-test-key', | ||
| op: 'db', | ||
| status: 'internal_error', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.system': 'redis', | ||
| 'db.statement': 'INCR redis-test-key', | ||
| }), | ||
| }), | ||
logaretm marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ]), | ||
| }; | ||
| @@ -246,4 +279,136 @@ describe('redis cache auto instrumentation', () => { | ||
| }); | ||
| }); | ||
| }); | ||
| // node-redis 5.0-5.11 still flows through the vendored monkey-patch | ||
| // instrumentation (diagnostics_channel was only added in 5.12.0), so this | ||
| // exercises the `>=5.0.0 <5.12.0` branch of the vendored RedisInstrumentation. | ||
| describe('redis-5 cache keys', () => { | ||
| const EXPECTED_REDIS_CONNECT = { | ||
| transaction: 'redis-connect', | ||
| }; | ||
| const EXPECTED_TRANSACTION = { | ||
| transaction: 'Test Span Redis 5', | ||
| spans: expect.arrayContaining([ | ||
| // SET | ||
| expect.objectContaining({ | ||
| description: 'redis-5-cache:test-key', | ||
| op: 'cache.put', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.statement': 'SET redis-5-cache:test-key [1 other arguments]', | ||
| 'cache.key': ['redis-5-cache:test-key'], | ||
| 'cache.item_size': 2, | ||
| }), | ||
| }), | ||
| // SET (with EX) | ||
| expect.objectContaining({ | ||
| description: 'redis-5-cache:test-key-set-EX', | ||
| op: 'cache.put', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.statement': 'SET redis-5-cache:test-key-set-EX [3 other arguments]', | ||
| 'cache.key': ['redis-5-cache:test-key-set-EX'], | ||
| 'cache.item_size': 2, | ||
| }), | ||
| }), | ||
| // SETEX | ||
| expect.objectContaining({ | ||
| description: 'redis-5-cache:test-key-setex', | ||
| op: 'cache.put', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.statement': 'SETEX redis-5-cache:test-key-setex [2 other arguments]', | ||
| 'cache.key': ['redis-5-cache:test-key-setex'], | ||
| 'cache.item_size': 2, | ||
| }), | ||
| }), | ||
| // GET | ||
| expect.objectContaining({ | ||
| description: 'redis-5-cache:test-key', | ||
| op: 'cache.get', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.statement': 'GET redis-5-cache:test-key', | ||
| 'cache.hit': true, | ||
| 'cache.key': ['redis-5-cache:test-key'], | ||
| 'cache.item_size': 10, | ||
| }), | ||
| }), | ||
| // GET (unavailable - no cache hit) | ||
| expect.objectContaining({ | ||
| description: 'redis-5-cache:unavailable-data', | ||
| op: 'cache.get', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.statement': 'GET redis-5-cache:unavailable-data', | ||
| 'cache.hit': false, | ||
| 'cache.key': ['redis-5-cache:unavailable-data'], | ||
| }), | ||
| }), | ||
| // MGET | ||
| expect.objectContaining({ | ||
| description: 'redis-5-test-key, redis-5-cache:test-key, redis-5-cache:unavailable-data', | ||
| op: 'cache.get', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.statement': 'MGET [3 other arguments]', | ||
| 'cache.hit': true, | ||
| 'cache.key': ['redis-5-test-key', 'redis-5-cache:test-key', 'redis-5-cache:unavailable-data'], | ||
| }), | ||
| }), | ||
| // MULTI/EXEC: one span per queued command | ||
| expect.objectContaining({ | ||
| description: 'SET redis-5-multi-key [1 other arguments]', | ||
| op: 'db', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.system': 'redis', | ||
| 'db.statement': 'SET redis-5-multi-key [1 other arguments]', | ||
| }), | ||
| }), | ||
| expect.objectContaining({ | ||
| description: 'GET redis-5-multi-key', | ||
| op: 'db', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.system': 'redis', | ||
| 'db.statement': 'GET redis-5-multi-key', | ||
| }), | ||
| }), | ||
| // a failing command produces a span with an error status | ||
| expect.objectContaining({ | ||
| description: 'INCR redis-5-test-key', | ||
| op: 'db', | ||
| status: 'internal_error', | ||
| origin: 'auto.db.otel.redis', | ||
| data: expect.objectContaining({ | ||
| 'sentry.origin': 'auto.db.otel.redis', | ||
| 'db.system': 'redis', | ||
| 'db.statement': 'INCR redis-5-test-key', | ||
| }), | ||
| }), | ||
| ]), | ||
| }; | ||
| createEsmAndCjsTests(__dirname, 'scenario-redis-5.mjs', 'instrument-redis-5.mjs', (createTestRunner, test) => { | ||
| test('should create cache spans for prefixed keys (redis-5)', async () => { | ||
| await createTestRunner() | ||
| .withDockerCompose({ workingDirectory: [__dirname] }) | ||
| .expect({ transaction: EXPECTED_REDIS_CONNECT }) | ||
| .expect({ transaction: EXPECTED_TRANSACTION }) | ||
| .start() | ||
| .completed(); | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed after streamline