Skip to content

Commit

Permalink
Add support for Jaeger trace target (#28129)
Browse files Browse the repository at this point in the history
Adds support for Jaeger next to Zipkin as a trace target.

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes
  • Loading branch information
timneutkens committed Aug 15, 2021
1 parent ebe3d93 commit 76cc01f
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/next/telemetry/trace/report/index.ts
@@ -1,6 +1,7 @@
import { TARGET, SpanId } from '../shared'
import reportToConsole from './to-console'
import reportToZipkin from './to-zipkin'
import reportToJaeger from './to-jaeger'
import reportToTelemetry from './to-telemetry'

type Reporter = (
Expand Down Expand Up @@ -28,6 +29,8 @@ if (target === TARGET.CONSOLE) {
report = reportToConsole
} else if (target === TARGET.ZIPKIN) {
report = reportToZipkin
} else if (target === TARGET.JAEGER) {
report = reportToJaeger
} else {
report = reportToTelemetry
}
90 changes: 90 additions & 0 deletions packages/next/telemetry/trace/report/to-jaeger.ts
@@ -0,0 +1,90 @@
import retry from 'next/dist/compiled/async-retry'
import { randomBytes } from 'crypto'
import fetch from 'node-fetch'
import * as Log from '../../../build/output/log'

let traceId = process.env.TRACE_ID
let batch: ReturnType<typeof batcher> | undefined

const localEndpoint = {
serviceName: 'nextjs',
ipv4: '127.0.0.1',
port: 9411,
}
// Jaeger supports Zipkin's reporting API
const zipkinUrl = `http://${localEndpoint.ipv4}:${localEndpoint.port}`
const jaegerWebUiUrl = `http://${localEndpoint.ipv4}:16686`
const zipkinAPI = `${zipkinUrl}/api/v2/spans`

type Event = {
traceId: string
parentId?: string
name: string
id: string
timestamp: number
duration: number
localEndpoint: typeof localEndpoint
tags?: Object
}

// Batch events as zipkin allows for multiple events to be sent in one go
function batcher(reportEvents: (evts: Event[]) => void) {
const events: Event[] = []
let timeout: ReturnType<typeof setTimeout> | undefined
return (event: Event) => {
events.push(event)
// setTimeout is used instead of setInterval to ensure events sending does not block exiting the program
if (!timeout) {
timeout = setTimeout(() => {
reportEvents(events.slice())
events.length = 0
timeout = undefined
}, 1500)
}
}
}

const reportToLocalHost = (
name: string,
duration: number,
timestamp: number,
id: string,
parentId?: string,
attrs?: Object
) => {
if (!traceId) {
traceId = process.env.TRACE_ID = randomBytes(8).toString('hex')
Log.info(
`Jaeger trace will be available on ${jaegerWebUiUrl}/trace/${traceId}`
)
}

if (!batch) {
batch = batcher((events) => {
// Ensure ECONNRESET error is retried 3 times before erroring out
retry(
() =>
// Send events to zipkin
fetch(zipkinAPI, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(events),
}),
{ minTimeout: 500, retries: 3, factor: 1 }
).catch(console.log)
})
}

batch({
traceId,
parentId,
name,
id,
timestamp,
duration,
localEndpoint,
tags: attrs,
})
}

export default reportToLocalHost
1 change: 1 addition & 0 deletions packages/next/telemetry/trace/shared.ts
Expand Up @@ -3,6 +3,7 @@
export enum TARGET {
CONSOLE = 'CONSOLE',
ZIPKIN = 'ZIPKIN',
JAEGER = 'JAEGER',
TELEMETRY = 'TELEMETRY',
}

Expand Down

0 comments on commit 76cc01f

Please sign in to comment.