Skip to content

Commit 24d7b41

Browse files
committed
feat: Propagate requestId for trace logging
1 parent 0c27f8c commit 24d7b41

File tree

13 files changed

+202
-83
lines changed

13 files changed

+202
-83
lines changed

packages/cubejs-api-gateway/SubscriptionServer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class SubscriptionServer {
6868
context,
6969
isSubscription,
7070
res: this.resultFn(connectionId, message.messageId),
71+
requestId: message.requestId || `${connectionId}-${message.messageId}`,
7172
subscriptionState: async () => {
7273
const subscription = await this.subscriptionStore.getSubscription(connectionId, message.messageId);
7374
return subscription && subscription.state;

packages/cubejs-api-gateway/index.js

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ const jwt = require('jsonwebtoken');
22
const R = require('ramda');
33
const Joi = require('@hapi/joi');
44
const moment = require('moment');
5-
const dateParser = require('./dateParser');
5+
const uuid = require('uuid/v4');
66

7+
const dateParser = require('./dateParser');
78
const UserError = require('./UserError');
89
const CubejsHandlerError = require('./CubejsHandlerError');
910
const SubscriptionServer = require('./SubscriptionServer');
@@ -226,30 +227,34 @@ class ApiGateway {
226227
await this.load({
227228
query: req.query.query,
228229
context: this.contextByReq(req),
229-
res: this.resToResultFn(res)
230+
res: this.resToResultFn(res),
231+
requestId: this.requestIdByReq(req)
230232
});
231233
}));
232234

233235
app.get(`${this.basePath}/v1/subscribe`, this.checkAuthMiddleware, (async (req, res) => {
234236
await this.load({
235237
query: req.query.query,
236238
context: this.contextByReq(req),
237-
res: this.resToResultFn(res)
239+
res: this.resToResultFn(res),
240+
requestId: this.requestIdByReq(req)
238241
});
239242
}));
240243

241244
app.get(`${this.basePath}/v1/sql`, this.checkAuthMiddleware, (async (req, res) => {
242245
await this.sql({
243246
query: req.query.query,
244247
context: this.contextByReq(req),
245-
res: this.resToResultFn(res)
248+
res: this.resToResultFn(res),
249+
requestId: this.requestIdByReq(req)
246250
});
247251
}));
248252

249253
app.get(`${this.basePath}/v1/meta`, this.checkAuthMiddleware, (async (req, res) => {
250254
await this.meta({
251255
context: this.contextByReq(req),
252-
res: this.resToResultFn(res)
256+
res: this.resToResultFn(res),
257+
requestId: this.requestIdByReq(req)
253258
});
254259
}));
255260
}
@@ -262,20 +267,22 @@ class ApiGateway {
262267
return requestStarted && (new Date().getTime() - requestStarted.getTime());
263268
}
264269

265-
async meta({ context, res }) {
270+
async meta({ context, res, requestId }) {
266271
const requestStarted = new Date();
267272
try {
268273
const metaConfig = await this.getCompilerApi(context).metaConfig();
269274
const cubes = metaConfig.map(c => c.config);
270275
res({ cubes });
271276
} catch (e) {
272277
this.handleError({
273-
e, context, res, requestStarted
278+
e, context, res, requestStarted, requestId
274279
});
275280
}
276281
}
277282

278-
async sql({ query, context, res }) {
283+
async sql({
284+
query, context, res, requestId
285+
}) {
279286
const requestStarted = new Date();
280287
try {
281288
query = this.parseQueryParam(query);
@@ -289,18 +296,21 @@ class ApiGateway {
289296
});
290297
} catch (e) {
291298
this.handleError({
292-
e, context, query, res, requestStarted
299+
e, context, query, res, requestStarted, requestId
293300
});
294301
}
295302
}
296303

297-
async load({ query, context, res }) {
304+
async load({
305+
query, context, res, requestId
306+
}) {
298307
const requestStarted = new Date();
299308
try {
300309
query = this.parseQueryParam(query);
301310
this.log(context, {
302311
type: 'Load Request',
303-
query
312+
query,
313+
requestId
304314
});
305315
const normalizedQuery = await this.queryTransformer(normalizeQuery(query), context);
306316
const [compilerSqlResult, metaConfigResult] = await Promise.all([
@@ -320,15 +330,17 @@ class ApiGateway {
320330
query: sqlQuery.sql[0],
321331
values: sqlQuery.sql[1],
322332
continueWait: true,
323-
renewQuery: normalizedQuery.renewQuery
333+
renewQuery: normalizedQuery.renewQuery,
334+
requestId
324335
};
325336
const response = await this.getAdapterApi({
326337
...context, dataSource: sqlQuery.dataSource
327338
}).executeQuery(toExecute);
328339
this.log(context, {
329340
type: 'Load Request Success',
330341
query,
331-
duration: this.duration(requestStarted)
342+
duration: this.duration(requestStarted),
343+
requestId
332344
});
333345
const flattenAnnotation = {
334346
...annotation.measures,
@@ -347,13 +359,13 @@ class ApiGateway {
347359
});
348360
} catch (e) {
349361
this.handleError({
350-
e, context, query, res, requestStarted
362+
e, context, query, res, requestStarted, requestId
351363
});
352364
}
353365
}
354366

355367
async subscribe({
356-
query, context, res, subscribe, subscriptionState
368+
query, context, res, subscribe, subscriptionState, requestId
357369
}) {
358370
const requestStarted = new Date();
359371
try {
@@ -373,6 +385,7 @@ class ApiGateway {
373385
await this.load({
374386
query,
375387
context,
388+
requestId: `${requestId}-${uuid()}`,
376389
res: (message, opts) => {
377390
if (message.error) {
378391
error = { message, opts };
@@ -427,14 +440,19 @@ class ApiGateway {
427440
return { authInfo: req.authInfo };
428441
}
429442

443+
requestIdByReq(req) {
444+
return req.headers['x-request-id'] || req.headers.traceparent || uuid();
445+
}
446+
430447
handleError({
431-
e, context, query, res, requestStarted
448+
e, context, query, res, requestStarted, requestId
432449
}) {
433450
if (e instanceof CubejsHandlerError) {
434451
this.log(context, {
435452
type: e.type,
436453
query,
437454
error: e.message,
455+
requestId,
438456
duration: this.duration(requestStarted)
439457
});
440458
res({ error: e.message }, { status: e.status });
@@ -443,6 +461,7 @@ class ApiGateway {
443461
type: 'Continue wait',
444462
query,
445463
error: e.message,
464+
requestId,
446465
duration: this.duration(requestStarted)
447466
});
448467
res(e, { status: 200 });
@@ -451,6 +470,7 @@ class ApiGateway {
451470
type: 'Orchestrator error',
452471
query,
453472
error: e.error,
473+
requestId,
454474
duration: this.duration(requestStarted)
455475
});
456476
res(e, { status: 400 });
@@ -459,6 +479,7 @@ class ApiGateway {
459479
type: 'Internal Server Error',
460480
query,
461481
error: e.stack || e.toString(),
482+
requestId,
462483
duration: this.duration(requestStarted)
463484
});
464485
res({ error: e.toString() }, { status: 500 });

packages/cubejs-api-gateway/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"jsonwebtoken": "^8.3.0",
2222
"moment": "^2.24.0",
2323
"moment-timezone": "^0.5.27",
24-
"ramda": "^0.25.0"
24+
"ramda": "^0.25.0",
25+
"uuid": "^3.3.3"
2526
},
2627
"devDependencies": {
2728
"eslint": "^4.14.0",

packages/cubejs-api-gateway/yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4498,7 +4498,7 @@ utils-merge@1.0.1:
44984498
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
44994499
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
45004500

4501-
uuid@^3.3.2:
4501+
uuid@^3.3.2, uuid@^3.3.3:
45024502
version "3.3.3"
45034503
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
45044504
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==

packages/cubejs-query-orchestrator/orchestrator/LocalQueueDriver.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class LocalQueueDriverConnection {
6161

6262
addToQueue(keyScore, queryKey, time, queryHandler, query, priority, options) {
6363
const queryQueueObj = {
64-
queryHandler, query, queryKey, stageQueryKey: options.stageQueryKey, priority
64+
queryHandler, query, queryKey, stageQueryKey: options.stageQueryKey, priority, requestId: options.requestId
6565
};
6666
const key = this.redisHash(queryKey);
6767
if (!this.queryDef[key]) {

packages/cubejs-query-orchestrator/orchestrator/PreAggregations.js

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ class PreAggregationLoader {
165165
this.loadCache = loadCache;
166166
this.waitForRenew = options.waitForRenew;
167167
this.externalDriverFactory = preAggregations.externalDriverFactory;
168+
this.requestId = options.requestId;
168169
}
169170

170171
async loadPreAggregation() {
@@ -179,7 +180,11 @@ class PreAggregationLoader {
179180
if (versionEntryByStructureVersion) {
180181
this.loadPreAggregationWithKeys().catch(e => {
181182
if (!(e instanceof ContinueWaitError)) {
182-
this.logger('Error loading pre-aggregation', { error: (e.stack || e), preAggregation: this.preAggregation });
183+
this.logger('Error loading pre-aggregation', {
184+
error: (e.stack || e),
185+
preAggregation: this.preAggregation,
186+
requestId: this.requestId
187+
});
183188
}
184189
});
185190
return this.targetTableName(versionEntryByStructureVersion);
@@ -248,12 +253,18 @@ class PreAggregationLoader {
248253

249254
if (versionEntry) {
250255
if (versionEntry.structure_version !== newVersionEntry.structure_version) {
251-
this.logger('Invalidating pre-aggregation structure', { preAggregation: this.preAggregation });
256+
this.logger('Invalidating pre-aggregation structure', {
257+
preAggregation: this.preAggregation,
258+
requestId: this.requestId
259+
});
252260
await this.executeInQueue(invalidationKeys, 10, newVersionEntry);
253261
return mostRecentTargetTableName();
254262
} else if (versionEntry.content_version !== newVersionEntry.content_version) {
255263
if (this.waitForRenew) {
256-
this.logger('Waiting for pre-aggregation renew', { preAggregation: this.preAggregation });
264+
this.logger('Waiting for pre-aggregation renew', {
265+
preAggregation: this.preAggregation,
266+
requestId: this.requestId
267+
});
257268
await this.executeInQueue(invalidationKeys, 0, newVersionEntry);
258269
return mostRecentTargetTableName();
259270
} else {
@@ -268,7 +279,10 @@ class PreAggregationLoader {
268279
}
269280
}
270281
} else {
271-
this.logger('Creating pre-aggregation from scratch', { preAggregation: this.preAggregation });
282+
this.logger('Creating pre-aggregation from scratch', {
283+
preAggregation: this.preAggregation,
284+
requestId: this.requestId
285+
});
272286
await this.executeInQueue(invalidationKeys, 10, newVersionEntry);
273287
return mostRecentTargetTableName();
274288
}
@@ -283,7 +297,10 @@ class PreAggregationLoader {
283297
}
284298

285299
scheduleRefresh(invalidationKeys, newVersionEntry) {
286-
this.logger('Refreshing pre-aggregation content', { preAggregation: this.preAggregation });
300+
this.logger('Refreshing pre-aggregation content', {
301+
preAggregation: this.preAggregation,
302+
requestId: this.requestId
303+
});
287304
this.executeInQueue(invalidationKeys, 0, newVersionEntry)
288305
.then(() => {
289306
delete this.preAggregations.refreshErrors[newVersionEntry.table_name];
@@ -297,9 +314,11 @@ class PreAggregationLoader {
297314
this.preAggregations.refreshErrors[newVersionEntry.table_name][newVersionEntry.content_version].error = e;
298315
this.preAggregations.refreshErrors[newVersionEntry.table_name][newVersionEntry.content_version].counter += 1;
299316
}
300-
this.logger('Error refreshing pre-aggregation', { error: (e.stack || e), preAggregation: this.preAggregation })
317+
this.logger('Error refreshing pre-aggregation', {
318+
error: (e.stack || e), preAggregation: this.preAggregation, requestId: this.requestId
319+
});
301320
}
302-
})
321+
});
303322
}
304323

305324
executeInQueue(invalidationKeys, priority, newVersionEntry) {
@@ -309,7 +328,8 @@ class PreAggregationLoader {
309328
{
310329
preAggregation: this.preAggregation,
311330
preAggregationsTablesToTempTables: this.preAggregationsTablesToTempTables,
312-
newVersionEntry
331+
newVersionEntry,
332+
requestId: this.requestId
313333
},
314334
priority,
315335
{ stageQueryKey: PreAggregations.preAggregationQueryCacheKey(this.preAggregation) }
@@ -360,14 +380,20 @@ class PreAggregationLoader {
360380
throw new Error(`Can't load external pre-aggregation: source driver doesn't support downloadTable()`);
361381
}
362382
const table = this.targetTableName(newVersionEntry);
363-
this.logger('Downloading external pre-aggregation', { preAggregation: this.preAggregation });
383+
this.logger('Downloading external pre-aggregation', {
384+
preAggregation: this.preAggregation,
385+
requestId: this.requestId
386+
});
364387
const tableData = await client.downloadTable(table);
365388
const columns = await client.tableColumnTypes(table);
366389
const externalDriver = await this.externalDriverFactory();
367390
if (!externalDriver.uploadTable) {
368391
throw new Error(`Can't load external pre-aggregation: destination driver doesn't support uploadTable()`);
369392
}
370-
this.logger('Uploading external pre-aggregation', { preAggregation: this.preAggregation });
393+
this.logger('Uploading external pre-aggregation', {
394+
preAggregation: this.preAggregation,
395+
requestId: this.requestId
396+
});
371397
await externalDriver.uploadTable(table, columns, tableData);
372398
await this.loadCache.reset(this.preAggregation);
373399
await this.dropOrphanedTables(externalDriver, table);
@@ -389,7 +415,10 @@ class PreAggregationLoader {
389415
const toDrop = actualTables
390416
.map(t => `${this.preAggregation.preAggregationsSchema}.${t.table_name || t.TABLE_NAME}`)
391417
.filter(t => tablesToSave.indexOf(t) === -1);
392-
this.logger('Dropping orphaned tables', { tablesToDrop: JSON.stringify(toDrop) });
418+
this.logger('Dropping orphaned tables', {
419+
tablesToDrop: JSON.stringify(toDrop),
420+
requestId: this.requestId
421+
});
393422
await Promise.all(toDrop.map(table => client.dropTable(table)));
394423
}
395424
}
@@ -434,7 +463,7 @@ class PreAggregations {
434463
p,
435464
preAggregationsTablesToTempTables,
436465
loadCache,
437-
{ waitForRenew: queryBody.renewQuery }
466+
{ waitForRenew: queryBody.renewQuery, requestId: queryBody.requestId }
438467
);
439468
const preAggregationPromise = () => loader.loadPreAggregation().then(async targetTableName => {
440469
const usedPreAggregation = typeof targetTableName === 'string' ? { targetTableName } : targetTableName;
@@ -448,7 +477,9 @@ class PreAggregations {
448477
getQueue() {
449478
if (!this.queue) {
450479
this.queue = QueryCache.createQueue(`SQL_PRE_AGGREGATIONS_${this.redisPrefix}`, this.driverFactory, (client, q) => {
451-
const { preAggregation, preAggregationsTablesToTempTables, newVersionEntry } = q;
480+
const {
481+
preAggregation, preAggregationsTablesToTempTables, newVersionEntry, requestId
482+
} = q;
452483
const loader = new PreAggregationLoader(
453484
this.redisPrefix,
454485
this.driverFactory,
@@ -457,7 +488,8 @@ class PreAggregations {
457488
this,
458489
preAggregation,
459490
preAggregationsTablesToTempTables,
460-
new PreAggregationLoadCache(this.redisPrefix, this.driverFactory, this.queryCache, this)
491+
new PreAggregationLoadCache(this.redisPrefix, this.driverFactory, this.queryCache, this),
492+
{ requestId }
461493
);
462494
return loader.refresh(newVersionEntry)(client);
463495
}, {

0 commit comments

Comments
 (0)