Skip to content

Commit bdbbda5

Browse files
committed
Add diagnostics-semconv to standardize some attributes and headers
1 parent 9841d3a commit bdbbda5

File tree

19 files changed

+154
-167
lines changed

19 files changed

+154
-167
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"@types/koa": "^2.11.0",
5151
"@types/koa-compose": "^3.2.3",
5252
"@vtex/diagnostics-nodejs": "0.1.0-beta.8",
53+
"@vtex/diagnostics-semconv": "0.1.0-beta.8",
5354
"@vtex/node-error-report": "^0.0.3",
5455
"@wry/equality": "^0.1.9",
5556
"agentkeepalive": "^4.0.2",

src/HttpClient/HttpClient.ts

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,9 @@ import { createHash } from 'crypto'
33
import { IncomingMessage } from 'http'
44
import compose from 'koa-compose'
55
import pLimit from 'p-limit'
6-
76
import {
8-
BINDING_HEADER,
7+
HeaderKeys,
98
BODY_HASH,
10-
FORWARDED_HOST_HEADER,
11-
LOCALE_HEADER,
12-
PRODUCT_HEADER,
13-
SEGMENT_HEADER,
14-
SESSION_HEADER,
15-
TENANT_HEADER,
169
} from '../constants'
1710
import { Logger } from '../service/logger'
1811
import { IOContext } from '../service/worker/runtime/typings'
@@ -89,14 +82,14 @@ export class HttpClient {
8982
...defaultHeaders,
9083
'Accept-Encoding': 'gzip',
9184
'User-Agent': userAgent,
92-
...host ? { [FORWARDED_HOST_HEADER]: host } : null,
93-
...tenant ? { [TENANT_HEADER]: formatTenantHeaderValue(tenant) } : null,
94-
...binding ? { [BINDING_HEADER]: formatBindingHeaderValue(binding) } : null,
95-
...locale ? { [LOCALE_HEADER]: locale } : null,
96-
...operationId ? { 'x-vtex-operation-id': operationId } : null,
97-
...product ? { [PRODUCT_HEADER]: product } : null,
98-
...segmentToken ? { [SEGMENT_HEADER]: segmentToken } : null,
99-
...sessionToken ? { [SESSION_HEADER]: sessionToken } : null,
85+
...host ? { [HeaderKeys.FORWARDED_HOST]: host } : null,
86+
...tenant ? { [HeaderKeys.TENANT]: formatTenantHeaderValue(tenant) } : null,
87+
...binding ? { [HeaderKeys.BINDING]: formatBindingHeaderValue(binding) } : null,
88+
...locale ? { [HeaderKeys.LOCALE]: locale } : null,
89+
...operationId ? { [HeaderKeys.OPERATION_ID]: operationId } : null,
90+
...product ? { [HeaderKeys.PRODUCT]: product } : null,
91+
...segmentToken ? { [HeaderKeys.SEGMENT]: segmentToken } : null,
92+
...sessionToken ? { [HeaderKeys.SESSION]: sessionToken } : null,
10093
}
10194

10295
if (authType && authToken) {
@@ -139,16 +132,16 @@ export class HttpClient {
139132
return typeof v !== 'object' || v === null || Array.isArray(v) ? v :
140133
Object.fromEntries(Object.entries(v).sort(([ka], [kb]) =>
141134
ka < kb ? -1 : ka > kb ? 1 : 0))
142-
}
143-
catch(error) {
135+
}
136+
catch(error) {
144137
// I don't believe this will ever happen, but just in case
145138
// Also, I didn't include error as I am unsure if it would have sensitive information
146139
this.logger.warn({message: 'Error while sorting object for cache key'})
147140
return v
148141
}
149142
}
150-
151-
143+
144+
152145
const bodyHash = createHash('md5').update(JSON.stringify(data, deterministicReplacer)).digest('hex')
153146
const cacheableConfig = this.getConfig(url, {
154147
...config,

src/HttpClient/middlewares/cache.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { AxiosRequestConfig, AxiosResponse } from 'axios'
22
import { Span } from 'opentracing'
33

44
import { CacheLayer } from '../../caches/CacheLayer'
5-
import { LOCALE_HEADER, SEGMENT_HEADER, SESSION_HEADER } from '../../constants'
5+
import { HeaderKeys } from '../../constants'
66
import { IOContext } from '../../service/worker/runtime/typings'
77
import { ErrorReport } from '../../tracing'
88
import { HttpLogEvents } from '../../tracing/LogEvents'
@@ -15,7 +15,7 @@ const cacheableStatusCodes = [200, 203, 204, 206, 300, 301, 404, 405, 410, 414,
1515

1616
export const cacheKey = (config: AxiosRequestConfig) => {
1717
const {baseURL = '', url = '', params, headers} = config
18-
const locale = headers[LOCALE_HEADER]
18+
const locale = headers[HeaderKeys.LOCALE]
1919

2020
const encodedBaseURL = baseURL.replace(/\//g, '\\')
2121
const encodedURL = url.replace(/\//g, '\\')
@@ -97,7 +97,7 @@ export const cacheMiddleware = ({ type, storage, asyncSet }: CacheOptions) => {
9797
const { rootSpan: span, tracer, logger } = ctx.tracing ?? {}
9898

9999
const key = cacheKey(ctx.config)
100-
const segmentToken = ctx.config.headers[SEGMENT_HEADER]
100+
const segmentToken = ctx.config.headers[HeaderKeys.SEGMENT]
101101
const keyWithSegment = key + segmentToken
102102

103103
span?.log({
@@ -201,11 +201,11 @@ export const cacheMiddleware = ({ type, storage, asyncSet }: CacheOptions) => {
201201
}
202202

203203
const shouldCache = maxAge || etag
204-
const varySession = ctx.response.headers.vary && ctx.response.headers.vary.includes(SESSION_HEADER)
204+
const varySession = ctx.response.headers.vary && ctx.response.headers.vary.includes(HeaderKeys.SESSION)
205205
if (shouldCache && !varySession) {
206206
const {responseType, responseEncoding: configResponseEncoding} = ctx.config
207207
const currentAge = revalidated ? 0 : age
208-
const varySegment = ctx.response.headers.vary && ctx.response.headers.vary.includes(SEGMENT_HEADER)
208+
const varySegment = ctx.response.headers.vary && ctx.response.headers.vary.includes(HeaderKeys.SEGMENT)
209209
const setKey = varySegment ? keyWithSegment : key
210210
const responseEncoding = configResponseEncoding || (responseType === 'arraybuffer' ? 'base64' : undefined)
211211
const cacheableData = type === CacheType.Disk && responseType === 'arraybuffer'

src/HttpClient/middlewares/request/setupAxios/interceptors/tracing/spanSetup.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
22
import buildFullPath from 'axios/lib/core/buildFullPath'
33
import { Span } from 'opentracing'
4-
import { ROUTER_CACHE_HEADER } from '../../../../../../constants'
4+
import { HeaderKeys } from '../../../../../../constants'
55
import { CustomHttpTags, OpentracingTags } from '../../../../../../tracing/Tags'
66
import { cloneAndSanitizeHeaders } from '../../../../../../tracing/utils'
77

@@ -11,7 +11,6 @@ export const injectRequestInfoOnSpan = (span: Span | undefined, http: AxiosInsta
1111
[OpentracingTags.HTTP_METHOD]: config.method,
1212
[OpentracingTags.HTTP_URL]: buildFullPath(config.baseURL, http.getUri(config)),
1313
})
14-
1514
span?.log({ 'request-headers': cloneAndSanitizeHeaders(config.headers) })
1615
}
1716

@@ -24,7 +23,8 @@ export const injectResponseInfoOnSpan = (span: Span | undefined, response: Axios
2423

2524
span?.log({ 'response-headers': cloneAndSanitizeHeaders(response.headers) })
2625
span?.setTag(OpentracingTags.HTTP_STATUS_CODE, response.status)
27-
if (response.headers[ROUTER_CACHE_HEADER]) {
28-
span?.setTag(CustomHttpTags.HTTP_ROUTER_CACHE_RESULT, response.headers[ROUTER_CACHE_HEADER])
26+
27+
if (response.headers[HeaderKeys.ROUTER_CACHE]) {
28+
span?.setTag(CustomHttpTags.HTTP_ROUTER_CACHE_RESULT, response.headers[HeaderKeys.ROUTER_CACHE])
2929
}
3030
}

src/clients/janus/Segment.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import parseCookie from 'cookie'
22
import { prop } from 'ramda'
3-
4-
import { PRODUCT_HEADER } from '../../constants'
3+
import { HeaderKeys } from '../../constants'
54
import { inflightUrlWithQuery, RequestTracingConfig } from '../../HttpClient'
65
import { JanusClient } from './JanusClient'
76

@@ -87,7 +86,7 @@ export class Segment extends JanusClient {
8786
forceMaxAge: SEGMENT_MAX_AGE_S,
8887
headers: {
8988
'Content-Type': 'application/json',
90-
[PRODUCT_HEADER]: product || '',
89+
[HeaderKeys.PRODUCT]: product || '',
9190
},
9291
inflightKey: inflightUrlWithQuery,
9392
metric,

src/constants.ts

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
import { versionToMajor } from './utils/app'
2+
import {
3+
ATTR_VTEX_OPERATION_ID,
4+
ATTR_VTEX_ACCOUNT_NAME,
5+
ATTR_VTEX_IO_WORKSPACE_NAME,
6+
ATTR_VTEX_IO_WORKSPACE_TYPE,
7+
ATTR_VTEX_IO_APP_ID,
8+
ATTR_VTEX_IO_APP_AUTHOR_TYPE
9+
} from '@vtex/diagnostics-semconv'
10+
211
// tslint:disable-next-line
312
const pkg = require('../package.json')
413

@@ -7,36 +16,57 @@ export const DEFAULT_WORKSPACE = 'master'
716
export const IS_IO = process.env.VTEX_IO
817
export const PID = process.pid
918

10-
export const CACHE_CONTROL_HEADER = 'cache-control'
11-
export const SEGMENT_HEADER = 'x-vtex-segment'
12-
export const SESSION_HEADER = 'x-vtex-session'
13-
export const PRODUCT_HEADER = 'x-vtex-product'
14-
export const LOCALE_HEADER = 'x-vtex-locale'
15-
export const FORWARDED_HOST_HEADER = 'x-forwarded-host'
16-
export const TENANT_HEADER = 'x-vtex-tenant'
17-
export const BINDING_HEADER = 'x-vtex-binding'
18-
export const META_HEADER = 'x-vtex-meta'
19-
export const META_HEADER_BUCKET = 'x-vtex-meta-bucket'
20-
export const ETAG_HEADER = 'etag'
21-
export const ACCOUNT_HEADER = 'x-vtex-account'
22-
export const CREDENTIAL_HEADER = 'x-vtex-credential'
23-
export const REQUEST_ID_HEADER = 'x-request-id'
24-
export const ROUTER_CACHE_HEADER = 'x-router-cache'
25-
export const OPERATION_ID_HEADER = 'x-vtex-operation-id'
26-
export const PLATFORM_HEADER = 'x-vtex-platform'
27-
export const WORKSPACE_IS_PRODUCTION_HEADER = 'x-vtex-workspace-is-production'
28-
export const WORKSPACE_HEADER = 'x-vtex-workspace'
29-
export const EVENT_KEY_HEADER = 'x-event-key'
30-
export const EVENT_SENDER_HEADER = 'x-event-sender'
31-
export const EVENT_SUBJECT_HEADER = 'x-event-subject'
32-
export const EVENT_HANDLER_ID_HEADER = 'x-event-handler-id'
33-
export const COLOSSUS_ROUTE_DECLARER_HEADER = 'x-colossus-route-declarer'
34-
export const COLOSSUS_ROUTE_ID_HEADER = 'x-colossus-route-id'
35-
export const COLOSSUS_PARAMS_HEADER = 'x-colossus-params'
36-
export const TRACE_ID_HEADER = 'x-trace-id'
37-
export const PROVIDER_HEADER = 'x-vtex-provider'
19+
export const HeaderKeys = {
20+
CACHE_CONTROL: 'cache-control',
21+
SEGMENT: 'x-vtex-segment',
22+
SESSION: 'x-vtex-session',
23+
PRODUCT: 'x-vtex-product',
24+
LOCALE: 'x-vtex-locale',
25+
FORWARDED_HOST: 'x-forwarded-host',
26+
FORWARDED_FOR: 'x-forwarded-for',
27+
TENANT: 'x-vtex-tenant',
28+
BINDING: 'x-vtex-binding',
29+
META: 'x-vtex-meta',
30+
META_BUCKET: 'x-vtex-meta-bucket',
31+
ETAG: 'etag',
32+
ACCOUNT: 'x-vtex-account',
33+
CREDENTIAL: 'x-vtex-credential',
34+
REQUEST_ID: 'x-request-id',
35+
ROUTER_CACHE: 'x-router-cache',
36+
OPERATION_ID: 'x-vtex-operation-id',
37+
PLATFORM: 'x-vtex-platform',
38+
WORKSPACE_IS_PRODUCTION: 'x-vtex-workspace-is-production',
39+
WORKSPACE: 'x-vtex-workspace',
40+
EVENT_KEY: 'x-event-key',
41+
EVENT_SENDER: 'x-event-sender',
42+
EVENT_SUBJECT: 'x-event-subject',
43+
EVENT_HANDLER_ID: 'x-event-handler-id',
44+
COLOSSUS_ROUTE_DECLARER: 'x-colossus-route-declarer',
45+
COLOSSUS_ROUTE_ID: 'x-colossus-route-id',
46+
COLOSSUS_PARAMS: 'x-colossus-params',
47+
TRACE_ID: 'x-trace-id',
48+
PROVIDER: 'x-vtex-provider',
49+
USER_AGENT: 'user-agent',
50+
VTEX_USER_AGENT: 'x-vtex-user-agent',
51+
VTEX_IO_CALLER: 'x-vtex-io-caller',
52+
VTEX_APP_SERVICE: 'x-vtex-app-service',
53+
VTEX_APP_KEY: 'x-vtex-app-key',
54+
VTEX_RETRY_COUNT: 'x-vtex-retry-count'
55+
}
56+
57+
export const AttributeKeys = {
58+
// VTEX Semantic Attributes
59+
VTEX_OPERATION_ID: ATTR_VTEX_OPERATION_ID,
60+
VTEX_ACCOUNT_NAME: ATTR_VTEX_ACCOUNT_NAME,
61+
62+
// VTEX IO Semantic Attributes
63+
VTEX_IO_WORKSPACE_NAME: ATTR_VTEX_IO_WORKSPACE_NAME,
64+
VTEX_IO_WORKSPACE_TYPE: ATTR_VTEX_IO_WORKSPACE_TYPE,
65+
VTEX_IO_APP_ID: ATTR_VTEX_IO_APP_ID,
66+
VTEX_IO_APP_AUTHOR_TYPE: ATTR_VTEX_IO_APP_AUTHOR_TYPE,
67+
}
3868

39-
export type VaryHeaders = typeof SEGMENT_HEADER | typeof SESSION_HEADER | typeof PRODUCT_HEADER | typeof LOCALE_HEADER
69+
export type VaryHeaders = typeof HeaderKeys.SEGMENT | typeof HeaderKeys.SESSION | typeof HeaderKeys.PRODUCT | typeof HeaderKeys.LOCALE
4070

4171
export const BODY_HASH = '__graphqlBodyHash'
4272

src/service/logger/logger.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { APP, LOG_CLIENT_INIT_TIMEOUT_MS } from '../../constants'
1+
import { APP, LOG_CLIENT_INIT_TIMEOUT_MS, AttributeKeys } from '../../constants'
22
import { cleanError } from '../../utils/error'
33
import { cleanLog } from '../../utils/log'
44
import { LogClient } from '@vtex/diagnostics-nodejs/dist/types';
@@ -82,13 +82,14 @@ export class Logger {
8282
const inflatedLog = {
8383
__VTEX_IO_LOG: true,
8484
level,
85-
app,
86-
account: this.account,
87-
workspace: this.workspace,
88-
production: this.production,
89-
data,
90-
operationId: this.operationId,
85+
[AttributeKeys.VTEX_IO_APP_ID]: app,
86+
[AttributeKeys.VTEX_ACCOUNT_NAME]: this.account,
87+
[AttributeKeys.VTEX_IO_WORKSPACE_NAME]: this.workspace,
88+
[AttributeKeys.VTEX_IO_WORKSPACE_TYPE]: this.production ? 'production' : 'development',
89+
[AttributeKeys.VTEX_IO_APP_AUTHOR_TYPE]: APP.IS_THIRD_PARTY() ? '3p' : '1p',
90+
[AttributeKeys.VTEX_OPERATION_ID]: this.operationId,
9191
requestId: this.requestId,
92+
data,
9293
... (this.tracingState?.isTraceSampled ? { traceId: this.tracingState.traceId } : null),
9394
}
9495

src/service/tracing/tracingMiddlewares.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FORMAT_HTTP_HEADERS, SpanContext, Tracer } from 'opentracing'
22
import { finished as onStreamFinished } from 'stream'
3-
import { ACCOUNT_HEADER, REQUEST_ID_HEADER, TRACE_ID_HEADER, WORKSPACE_HEADER } from '../../constants'
3+
import { HeaderKeys } from '../../constants'
44
import { ErrorReport, getTraceInfo } from '../../tracing'
55
import { RuntimeLogEvents } from '../../tracing/LogEvents'
66
import { RuntimeLogFields } from '../../tracing/LogFields'
@@ -52,14 +52,14 @@ export const addTracingMiddleware = (tracer: Tracer) => {
5252
[OpentracingTags.HTTP_METHOD]: ctx.request.method,
5353
[OpentracingTags.HTTP_STATUS_CODE]: ctx.response.status,
5454
[CustomHttpTags.HTTP_PATH]: ctx.request.path,
55-
[VTEXIncomingRequestTags.VTEX_REQUEST_ID]: ctx.get(REQUEST_ID_HEADER),
56-
[VTEXIncomingRequestTags.VTEX_WORKSPACE]: ctx.get(WORKSPACE_HEADER),
57-
[VTEXIncomingRequestTags.VTEX_ACCOUNT]: ctx.get(ACCOUNT_HEADER),
55+
[VTEXIncomingRequestTags.VTEX_REQUEST_ID]: ctx.get(HeaderKeys.REQUEST_ID),
56+
[VTEXIncomingRequestTags.VTEX_WORKSPACE]: ctx.get(HeaderKeys.WORKSPACE),
57+
[VTEXIncomingRequestTags.VTEX_ACCOUNT]: ctx.get(HeaderKeys.ACCOUNT),
5858
})
5959

6060
currentSpan?.log(cloneAndSanitizeHeaders(ctx.request.headers, 'req.headers.'))
6161
currentSpan?.log(cloneAndSanitizeHeaders(ctx.response.headers, 'res.headers.'))
62-
ctx.set(TRACE_ID_HEADER, traceInfo.traceId!)
62+
ctx.set(HeaderKeys.TRACE_ID, traceInfo.traceId!)
6363
}
6464

6565
const onResFinished = () => {

src/service/worker/runtime/builtIn/middlewares.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { collectDefaultMetrics, register } from 'prom-client'
2-
import { COLOSSUS_ROUTE_ID_HEADER } from '../../../../constants'
3-
2+
import { HeaderKeys } from '../../../../constants'
43
import { MetricsLogger } from '../../../logger/metricsLogger'
54
import { EventLoopLagMeasurer } from '../../../tracing/metrics/measurers/EventLoopLagMeasurer'
65
import { ServiceContext } from '../typings'
@@ -32,7 +31,7 @@ export const prometheusLoggerMiddleware = () => {
3231
return next()
3332
}
3433

35-
const routeId = ctx.get(COLOSSUS_ROUTE_ID_HEADER)
34+
const routeId = ctx.get(HeaderKeys.COLOSSUS_ROUTE_ID)
3635
if (routeId) {
3736
return next()
3837
}

src/service/worker/runtime/events/middlewares/context.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { IOClients } from '../../../../../clients/IOClients'
22
import {
3-
EVENT_HANDLER_ID_HEADER,
4-
EVENT_KEY_HEADER,
5-
EVENT_SENDER_HEADER,
6-
EVENT_SUBJECT_HEADER,
3+
HeaderKeys,
74
} from '../../../../../constants'
85
import { ParamsContext, RecorderState, ServiceContext } from '../../typings'
96
import { prepareHandlerCtx } from '../../utils/context'
@@ -13,12 +10,12 @@ export async function eventContextMiddleware <T extends IOClients, U extends Rec
1310
ctx.vtex = {
1411
...prepareHandlerCtx(header, ctx.tracing),
1512
eventInfo: {
16-
key: header[EVENT_KEY_HEADER],
17-
sender: header[EVENT_SENDER_HEADER],
18-
subject: header[EVENT_SUBJECT_HEADER],
13+
key: header[HeaderKeys.EVENT_KEY],
14+
sender: header[HeaderKeys.EVENT_SENDER],
15+
subject: header[HeaderKeys.EVENT_SUBJECT],
1916
},
2017
route: {
21-
id: header[EVENT_HANDLER_ID_HEADER],
18+
id: header[HeaderKeys.EVENT_HANDLER_ID],
2219
params: {},
2320
type: 'event',
2421
},

0 commit comments

Comments
 (0)