Skip to content
Open
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
16 changes: 16 additions & 0 deletions packages/core/src/metrics/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,19 @@ export function getStatusCodeGroup(statusCode: number) {
}
}
}

/**
* Make URL start with slash and have maximum depth.
*/
export const normalizeUrlWithTrimming = (url: string, maxDepth = 0) => {
if (maxDepth < 0) {
throw new Error('maxDepth must be bigger than 0')
}

if (maxDepth === 0) {
return url
}

const withStartingSlashUrl = url.startsWith('/') ? url : `/${url}`
return withStartingSlashUrl.split('/', maxDepth + 1).join('/')
}
6 changes: 4 additions & 2 deletions packages/core/src/next/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import path from 'node:path'

import {glob} from 'glob'

import {normalizeUrlWithTrimming} from '../metrics/util'

interface RouteInfo {
page: string
regex: string
Expand Down Expand Up @@ -40,7 +42,7 @@ export function getNextRoutesManifest() {
* Creates a function that normalizes Next.js URLs to route patterns for metrics
* @returns Function that takes a URL and returns the normalized route pattern
*/
export function createNextRoutesUrlGroup() {
export function createNextRoutesUrlGroup(maxNormalizedUrlDepth: number) {
const {basePath, routes} = getNextRoutesManifest()

return function getUrlGroup(originalUrl: string) {
Expand Down Expand Up @@ -69,6 +71,6 @@ export function createNextRoutesUrlGroup() {
}
}

return withoutBasePathUrl
return normalizeUrlWithTrimming(withoutBasePathUrl, maxNormalizedUrlDepth)
}
}
2 changes: 2 additions & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ export interface CommonPrometheusExporterOptions {
metricsPath?: string
/** Whether to collect default Node.js metrics */
collectDefaultMetrics?: boolean
/** URL depth limit for path normalization */
maxNormalizedUrlDepth?: number
}
9 changes: 8 additions & 1 deletion packages/hono/src/exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export async function createHonoPrometheusExporter({
bypass,
normalizePath,
formatStatusCode,
maxNormalizedUrlDepth,
}: HonoPrometheusExporterOptions) {
// Disabled: return noop
if (!enabled) {
Expand Down Expand Up @@ -65,7 +66,13 @@ export async function createHonoPrometheusExporter({

registerGaugeUp()

const middleware = getHonoMetricsMiddleware({nextjs, bypass, normalizePath, formatStatusCode})
const middleware = getHonoMetricsMiddleware({
nextjs,
bypass,
normalizePath,
formatStatusCode,
maxNormalizedUrlDepth,
})

// PM2 mode: aggregated metrics from all workers
// Standalone mode: single process metrics
Expand Down
15 changes: 12 additions & 3 deletions packages/hono/src/middleware/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getStatusCodeGroup,
isBypassPath,
startTraceHistogram,
trimUrl,
} from '@naverpay/prometheus-core'

import type {HonoPrometheusExporterOptions} from '../types'
Expand All @@ -20,12 +21,20 @@ export function getHonoMetricsMiddleware({
bypass,
normalizePath,
formatStatusCode,
}: Pick<HonoPrometheusExporterOptions, 'nextjs' | 'bypass' | 'normalizePath' | 'formatStatusCode'>): MiddlewareHandler {
const normalizeNextRoutesPath = nextjs ? createNextRoutesUrlGroup() : undefined
maxNormalizedUrlDepth,
}: Pick<
HonoPrometheusExporterOptions,
'nextjs' | 'bypass' | 'normalizePath' | 'formatStatusCode' | 'maxNormalizedUrlDepth'
>): MiddlewareHandler {
const normalizeNextRoutesPath = nextjs ? createNextRoutesUrlGroup(maxNormalizedUrlDepth) : undefined

const extendedNormalizePath = (context: Context) => {
const url = new URL(context.req.url)
return normalizeNextRoutesPath?.(url.href) || normalizePath?.(context) || url.pathname
return (
normalizeNextRoutesPath?.(url.href) ||
normalizePath?.(context) ||
trimUrl(url.pathname, maxNormalizedUrlDepth)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 이름을 normalizeUrlWithTrimming 이걸로 바꾸신것 같은데 반영이 안되었습니다.

)
}

return async (context, next) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/koa/src/exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export async function createKoaPrometheusExporter({
bypass,
normalizePath,
formatStatusCode,
maxNormalizedUrlDepth,
}: KoaPrometheusExporterOptions) {
// Disabled: return noop
if (!enabled) {
Expand Down Expand Up @@ -65,7 +66,7 @@ export async function createKoaPrometheusExporter({

registerGaugeUp()

const middleware = getKoaMetricsMiddleware({nextjs, bypass, normalizePath, formatStatusCode})
const middleware = getKoaMetricsMiddleware({nextjs, bypass, normalizePath, formatStatusCode, maxNormalizedUrlDepth})

// PM2 mode: aggregated metrics from all workers
// Standalone mode: single process metrics
Expand Down
11 changes: 8 additions & 3 deletions packages/koa/src/middleware/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getStatusCodeGroup,
isBypassPath,
startTraceHistogram,
trimUrl,
} from '@naverpay/prometheus-core'
import onFinished from 'on-finished'

Expand All @@ -21,11 +22,15 @@ export function getKoaMetricsMiddleware({
bypass,
normalizePath,
formatStatusCode,
}: Pick<KoaPrometheusExporterOptions, 'nextjs' | 'bypass' | 'normalizePath' | 'formatStatusCode'>): Middleware {
const normalizeNextRoutesPath = nextjs ? createNextRoutesUrlGroup() : undefined
maxNormalizedUrlDepth,
}: Pick<
KoaPrometheusExporterOptions,
'nextjs' | 'bypass' | 'normalizePath' | 'formatStatusCode' | 'maxNormalizedUrlDepth'
>): Middleware {
const normalizeNextRoutesPath = nextjs ? createNextRoutesUrlGroup(maxNormalizedUrlDepth) : undefined

const extendedNormalizePath = (context: Context) => {
return normalizeNextRoutesPath?.(context.url) || normalizePath?.(context) || context.path
return normalizeNextRoutesPath?.(context.url) || normalizePath?.(context) || trimUrl(context.path)
}

return async (context, next) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/next/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export async function createNextServerWithMetrics({
bypass,
normalizePath,
formatStatusCode,
maxNormalizedUrlDepth,
}: NextjsPrometheusExporterOptions) {
const app = next(nextOptions)
await app.prepare()
Expand All @@ -73,7 +74,7 @@ export async function createNextServerWithMetrics({
registerGaugeUp()
}

const normalizeNextRoutesPath = createNextRoutesUrlGroup()
const normalizeNextRoutesPath = createNextRoutesUrlGroup(maxNormalizedUrlDepth)

const server = http.createServer(async (request, response) => {
if (!pm2) {
Expand Down