Skip to content

Commit

Permalink
fix: instrumentation & rename redis
Browse files Browse the repository at this point in the history
  • Loading branch information
FelixNgFender committed Mar 18, 2024
1 parent 9f6ab2d commit 5fca200
Show file tree
Hide file tree
Showing 8 changed files with 583 additions and 117 deletions.
8 changes: 7 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ const nextConfig = {
experimental: {
instrumentationHook: true,
},
webpack: (config) => {
webpack: (
config,
{ isServer },
) => {
config.externals.push('@node-rs/argon2', '@node-rs/bcrypt');
if (isServer) {
config.ignoreWarnings = [{ module: /opentelemetry/ }];
}
return config;
},
logging: {
Expand Down
620 changes: 529 additions & 91 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
"@marsidev/react-turnstile": "^0.5.3",
"@next/bundle-analyzer": "^14.1.3",
"@next/third-parties": "^14.1.3",
"@opentelemetry/exporter-jaeger": "^1.22.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.49.1",
"@opentelemetry/resources": "^1.22.0",
"@opentelemetry/sdk-node": "^0.49.1",
"@opentelemetry/sdk-trace-node": "^1.22.0",
"@opentelemetry/semantic-conventions": "^1.22.0",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
Expand All @@ -52,7 +58,6 @@
"@react-email/render": "^0.0.12",
"@tanstack/react-query": "^5.17.19",
"@tanstack/react-table": "^8.11.6",
"@vercel/otel": "^1.6.0",
"arctic": "^1.1.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
Expand Down
4 changes: 2 additions & 2 deletions src/app/api/healthcheck/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cache, db, fileStorage } from '@/infra';
import { redis, db, fileStorage } from '@/infra';
import { withErrorHandling } from '@/lib/error';
import { HttpResponse } from '@/lib/response';
import { sql } from 'drizzle-orm';
Expand All @@ -9,7 +9,7 @@ export const GET = withErrorHandling(async () => {
const start = performance.now();
await db.execute(sql`SELECT 1`);
const databaseLatency = (performance.now() - start).toFixed(2);
await cache.ping();
await redis.ping();
const cacheLatency = (
performance.now() -
start -
Expand Down
2 changes: 1 addition & 1 deletion src/infra/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './database';
export * from './cache';
export * from './redis';
export * from './file-storage';
export * from './replicate';
18 changes: 9 additions & 9 deletions src/infra/cache.ts → src/infra/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,31 @@ import { type RedisClientType, createClient } from 'redis';
import 'server-only';

declare global {
var cache: RedisClientType | undefined;
var redis: RedisClientType | undefined;
}

let cache: RedisClientType;
let redis: RedisClientType;

if (env.NODE_ENV === 'production') {
cache = createClient({ url: env.REDIS_URL, disableOfflineQueue: true });
redis = createClient({ url: env.REDIS_URL, disableOfflineQueue: true });
} else {
if (!global.cache) {
global.cache = createClient({
if (!global.redis) {
global.redis = createClient({
url: env.REDIS_URL,
disableOfflineQueue: true,
});
}

cache = global.cache;
redis = global.redis;
}

if (process.env.NEXT_PHASE !== PHASE_PRODUCTION_BUILD && !cache.isOpen) {
cache
if (process.env.NEXT_PHASE !== PHASE_PRODUCTION_BUILD && !redis.isOpen) {
redis
.on('error', async (err) => {
await errorHandler.handleError(err);
})
.on('ready', () => logger.info('Redis Client Ready'))
.connect();
}

export { cache };
export { redis };
27 changes: 22 additions & 5 deletions src/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { registerOTel } from '@vercel/otel';

export const register = async () => {
if (process.env.NEXT_RUNTIME === 'nodejs') {
if (parseInt(process.versions.node.split('.')[0] ?? '') <= 18) {
Expand All @@ -14,10 +12,29 @@ export const register = async () => {
const { errorHandler } = await import('@/lib/error');
const { logger } = await import('@/lib/logger');
const { env } = await import('@/config/env');
const { cache } = await import('@/infra');
const { redis } = await import('@/infra');

if (env.ENABLE_INSTRUMENTATION) {
registerOTel({ serviceName: 'web' });
const { OTLPTraceExporter } = await import(
'@opentelemetry/exporter-trace-otlp-http'
);
const { Resource } = await import('@opentelemetry/resources');
const { NodeSDK } = await import('@opentelemetry/sdk-node');
const { SimpleSpanProcessor } = await import(
'@opentelemetry/sdk-trace-node'
);
const { SEMRESATTRS_SERVICE_NAME } = await import(
'@opentelemetry/semantic-conventions'
);

const sdk = new NodeSDK({
resource: new Resource({
[SEMRESATTRS_SERVICE_NAME]: 'web',
}),
spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter()),
});

sdk.start();
}

/**
Expand All @@ -27,7 +44,7 @@ export const register = async () => {
const cleanup = async (exitCode: number) => {
// await queryClient.end();
// Redis and Minio clients are already closed by the time this function is called.
await cache.quit();
await redis.quit();
logger.info('Gracefully shutting down...');
process.exit(exitCode);
};
Expand Down
14 changes: 7 additions & 7 deletions src/lib/rate-limit.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cache } from '@/infra';
import { redis } from '@/infra';
import { headers } from 'next/headers';
import { RateLimiterRedis, RateLimiterRes } from 'rate-limiter-flexible';
import 'server-only';
Expand All @@ -15,47 +15,47 @@ function getIPAdress() {
}

const signInRateLimiter = new RateLimiterRedis({
storeClient: cache,
storeClient: redis,
useRedisPackage: true,
keyPrefix: 'rate-limiter:sign-in',
points: 5,
duration: 5 * 60,
});

const signUpRateLimiter = new RateLimiterRedis({
storeClient: cache,
storeClient: redis,
useRedisPackage: true,
keyPrefix: 'rate-limiter:sign-up',
points: 3,
duration: 1 * 60 * 60 * 24,
});

const passwordResetRateLimiter = new RateLimiterRedis({
storeClient: cache,
storeClient: redis,
useRedisPackage: true,
keyPrefix: 'rate-limiter:password-reset',
points: 3,
duration: 1 * 60 * 60,
});

const verifyCodeRateLimiter = new RateLimiterRedis({
storeClient: cache,
storeClient: redis,
useRedisPackage: true,
keyPrefix: 'rate-limiter:verify-code',
points: 5,
duration: 1 * 60 * 60,
});

const resendCodeRateLimiter = new RateLimiterRedis({
storeClient: cache,
storeClient: redis,
useRedisPackage: true,
keyPrefix: 'rate-limiter:resend-code',
points: 5,
duration: 1 * 60 * 60,
});

const trackProcessingRateLimiter = new RateLimiterRedis({
storeClient: cache,
storeClient: redis,
useRedisPackage: true,
keyPrefix: 'rate-limiter:track-processing',
points: 10,
Expand Down

0 comments on commit 5fca200

Please sign in to comment.