@redthreadlabs/tracelog 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +16 -0
- package/lib/agent.js +21 -1
- package/lib/apm-client/apm-client.js +1 -1
- package/lib/apm-client/channel-writer.js +1 -1
- package/lib/apm-client/jsonl-file-client.js +1 -1
- package/lib/apm-client/s3-uploader.js +1 -1
- package/lib/config/config.js +2 -0
- package/lib/config/normalizers.js +41 -0
- package/lib/config/schema.js +11 -0
- package/lib/instrumentation/index.js +17 -2
- package/lib/metrics/reporter.js +13 -1
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -293,6 +293,15 @@ declare namespace apm {
|
|
|
293
293
|
spanStackTraceMinDuration?: string;
|
|
294
294
|
stackTraceLimit?: number;
|
|
295
295
|
traceContinuationStrategy?: TraceContinuationStrategy;
|
|
296
|
+
/**
|
|
297
|
+
* Route auto-instrumented transactions (and their spans and breakdown
|
|
298
|
+
* metricsets) to a named channel when the transaction name matches a
|
|
299
|
+
* wildcard pattern. First matching rule wins; unmatched records go to
|
|
300
|
+
* the default channel.
|
|
301
|
+
*
|
|
302
|
+
* Example: `[{ pattern: '* unknown route*', channel: 'unknown-route' }]`
|
|
303
|
+
*/
|
|
304
|
+
transactionChannels?: Array<TransactionChannelRule>;
|
|
296
305
|
transactionIgnoreUrls?: Array<string>;
|
|
297
306
|
transactionMaxSpans?: number;
|
|
298
307
|
transactionSampleRate?: number;
|
|
@@ -329,6 +338,13 @@ declare namespace apm {
|
|
|
329
338
|
writeSpan (span: object): void;
|
|
330
339
|
}
|
|
331
340
|
|
|
341
|
+
interface TransactionChannelRule {
|
|
342
|
+
/** Wildcard pattern matched against the transaction name. */
|
|
343
|
+
pattern: string;
|
|
344
|
+
/** Channel to route matching transactions, spans, and breakdown metricsets to. */
|
|
345
|
+
channel: string;
|
|
346
|
+
}
|
|
347
|
+
|
|
332
348
|
interface CaptureEventOptions {
|
|
333
349
|
message?: string;
|
|
334
350
|
level?: 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
package/lib/agent.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright Red Thread Labs LLC. and Elasticsearch B.V. and other contributors where applicable.
|
|
3
3
|
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
4
4
|
* compliance with the BSD 2-Clause License.
|
|
5
5
|
*/
|
|
@@ -831,6 +831,26 @@ Agent.prototype.writeEvents = function (events, cb) {
|
|
|
831
831
|
// the default channel ('server'). Named channels are created lazily via
|
|
832
832
|
// getChannel(name) and write to separate files (e.g. tracelog-client-*.jsonl).
|
|
833
833
|
|
|
834
|
+
/**
|
|
835
|
+
* Resolve the channel that records for the named transaction should be
|
|
836
|
+
* routed to, per the `transactionChannels` config rules (first matching
|
|
837
|
+
* rule wins). Returns null when no rule matches, i.e. the record belongs
|
|
838
|
+
* on the default channel. Used for auto-instrumented transactions, their
|
|
839
|
+
* spans, and their breakdown metricsets.
|
|
840
|
+
*/
|
|
841
|
+
Agent.prototype._channelForTransactionName = function (name) {
|
|
842
|
+
const rules = this._conf && this._conf.transactionChannelRules;
|
|
843
|
+
if (!rules || rules.length === 0 || typeof name !== 'string') {
|
|
844
|
+
return null;
|
|
845
|
+
}
|
|
846
|
+
for (let i = 0; i < rules.length; i++) {
|
|
847
|
+
if (rules[i].re.test(name)) {
|
|
848
|
+
return rules[i].channel;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
return null;
|
|
852
|
+
};
|
|
853
|
+
|
|
834
854
|
/**
|
|
835
855
|
* Get a named channel. Returns an object with writeEvent, writeEvents,
|
|
836
856
|
* writeError, writeTransaction, and writeSpan methods that route to the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Copyright Elasticsearch B.V. and other contributors where applicable.
|
|
3
|
-
* Copyright
|
|
3
|
+
* Copyright Red Thread Labs LLC. All rights reserved.
|
|
4
4
|
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
5
5
|
* compliance with the BSD 2-Clause License.
|
|
6
6
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Copyright Elasticsearch B.V. and other contributors where applicable.
|
|
3
|
-
* Copyright
|
|
3
|
+
* Copyright Red Thread Labs LLC. All rights reserved.
|
|
4
4
|
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
5
5
|
* compliance with the BSD 2-Clause License.
|
|
6
6
|
*/
|
package/lib/config/config.js
CHANGED
|
@@ -48,6 +48,7 @@ const {
|
|
|
48
48
|
normalizeSanitizeFieldNames,
|
|
49
49
|
normalizeCloudProvider,
|
|
50
50
|
normalizeCustomMetricsHistogramBoundaries,
|
|
51
|
+
normalizeTransactionChannels,
|
|
51
52
|
normalizeTransactionSampleRate,
|
|
52
53
|
normalizeTraceContinuationStrategy,
|
|
53
54
|
normalizeContextManager,
|
|
@@ -396,6 +397,7 @@ function normalize(opts, logger) {
|
|
|
396
397
|
normalizeDurationOptions(opts, DURATION_OPTS, defaults, logger);
|
|
397
398
|
normalizeBools(opts, BOOL_OPTS, defaults, logger);
|
|
398
399
|
normalizeIgnoreOptions(opts);
|
|
400
|
+
normalizeTransactionChannels(opts, [], defaults, logger);
|
|
399
401
|
normalizeElasticsearchCaptureBodyUrls(opts);
|
|
400
402
|
normalizeDisableMetrics(opts);
|
|
401
403
|
normalizeSanitizeFieldNames(opts);
|
|
@@ -427,6 +427,46 @@ function normalizeIgnoreOptions(opts, fields, defaults, logger) {
|
|
|
427
427
|
}
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Normalizes transactionChannels rules into compiled wildcard matchers.
|
|
432
|
+
*
|
|
433
|
+
* Input is an array of { pattern, channel } objects, where `pattern` is a
|
|
434
|
+
* wildcard expression matched against the transaction name (e.g.
|
|
435
|
+
* '* unknown route*') and `channel` is the name of the channel to route
|
|
436
|
+
* matching transactions (and their spans and breakdown metricsets) to.
|
|
437
|
+
* Compiles to opts.transactionChannelRules: [{ re, channel }]. Invalid
|
|
438
|
+
* rules are dropped with a warning.
|
|
439
|
+
*
|
|
440
|
+
* @param {Record<String, unknown>} opts the configuration options to normalize
|
|
441
|
+
* @param {String[]} fields the list of fields to normalize (unused)
|
|
442
|
+
* @param {Record<String, unknown>} defaults the configuration defaults (unused)
|
|
443
|
+
* @param {import('../logging.js').Logger} logger
|
|
444
|
+
*/
|
|
445
|
+
function normalizeTransactionChannels(opts, fields, defaults, logger) {
|
|
446
|
+
if (opts.transactionChannels) {
|
|
447
|
+
opts.transactionChannelRules = [];
|
|
448
|
+
const wildcard = new WildcardMatcher();
|
|
449
|
+
for (const rule of opts.transactionChannels) {
|
|
450
|
+
if (
|
|
451
|
+
!rule ||
|
|
452
|
+
typeof rule.pattern !== 'string' ||
|
|
453
|
+
typeof rule.channel !== 'string' ||
|
|
454
|
+
!rule.channel
|
|
455
|
+
) {
|
|
456
|
+
logger.warn(
|
|
457
|
+
'invalid transactionChannels rule (expected { pattern, channel } strings): %j',
|
|
458
|
+
rule,
|
|
459
|
+
);
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
opts.transactionChannelRules.push({
|
|
463
|
+
re: wildcard.compile(rule.pattern),
|
|
464
|
+
channel: rule.channel,
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
430
470
|
/**
|
|
431
471
|
* Normalizes the wildcard matchers of sanitizeFieldNames and thansforms the into RegExps
|
|
432
472
|
*
|
|
@@ -640,6 +680,7 @@ module.exports = {
|
|
|
640
680
|
normalizeKeyValuePairs,
|
|
641
681
|
normalizeNumbers,
|
|
642
682
|
normalizeSanitizeFieldNames,
|
|
683
|
+
normalizeTransactionChannels,
|
|
643
684
|
normalizeTransactionSampleRate,
|
|
644
685
|
secondsFromDuration,
|
|
645
686
|
normalizeTraceContinuationStrategy,
|
package/lib/config/schema.js
CHANGED
|
@@ -361,6 +361,17 @@ const CONFIG_SCHEMA = [
|
|
|
361
361
|
centralConfigName: 'trace_continuation_strategy',
|
|
362
362
|
crossAgentName: 'trace_continuation_strategy',
|
|
363
363
|
},
|
|
364
|
+
{
|
|
365
|
+
name: 'transactionChannels',
|
|
366
|
+
configType: 'transactionChannelArray',
|
|
367
|
+
defaultValue: [],
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: 'transactionChannelRules',
|
|
371
|
+
configType: 'wildcardChannelRuleArray',
|
|
372
|
+
defaultValue: [],
|
|
373
|
+
deps: ['transactionChannels'],
|
|
374
|
+
},
|
|
364
375
|
{
|
|
365
376
|
name: 'transactionIgnoreUrls',
|
|
366
377
|
configType: 'stringArray',
|
|
@@ -717,7 +717,12 @@ Instrumentation.prototype.addEndedTransaction = function (transaction) {
|
|
|
717
717
|
trans: transaction.id,
|
|
718
718
|
trace: transaction.traceId,
|
|
719
719
|
});
|
|
720
|
-
agent.
|
|
720
|
+
const channel = agent._channelForTransactionName(payload.name);
|
|
721
|
+
if (channel && typeof agent._apmClient.sendToChannel === 'function') {
|
|
722
|
+
agent._apmClient.sendToChannel(channel, 'transaction', payload);
|
|
723
|
+
} else {
|
|
724
|
+
agent._apmClient.sendTransaction(payload);
|
|
725
|
+
}
|
|
721
726
|
};
|
|
722
727
|
|
|
723
728
|
Instrumentation.prototype.addEndedSpan = function (span) {
|
|
@@ -841,7 +846,17 @@ Instrumentation.prototype._encodeAndSendSpan = function (span) {
|
|
|
841
846
|
type: span.type,
|
|
842
847
|
});
|
|
843
848
|
if (agent._apmClient) {
|
|
844
|
-
|
|
849
|
+
// Spans follow their transaction's channel. The transaction name
|
|
850
|
+
// may not be final until the transaction ends, so this routing is
|
|
851
|
+
// best-effort for spans that end before the route is resolved.
|
|
852
|
+
const channel = agent._channelForTransactionName(
|
|
853
|
+
span.transaction && span.transaction.name,
|
|
854
|
+
);
|
|
855
|
+
if (channel && typeof agent._apmClient.sendToChannel === 'function') {
|
|
856
|
+
agent._apmClient.sendToChannel(channel, 'span', payload);
|
|
857
|
+
} else {
|
|
858
|
+
agent._apmClient.sendSpan(payload);
|
|
859
|
+
}
|
|
845
860
|
}
|
|
846
861
|
}
|
|
847
862
|
}
|
package/lib/metrics/reporter.js
CHANGED
|
@@ -67,7 +67,19 @@ class MetricsReporter extends Reporter {
|
|
|
67
67
|
|
|
68
68
|
if (this._agent._apmClient) {
|
|
69
69
|
for (const metric of seen.values()) {
|
|
70
|
-
|
|
70
|
+
// Breakdown metricsets carry the name of the transaction they
|
|
71
|
+
// were aggregated for; route them to that transaction's channel.
|
|
72
|
+
const channel = this._agent._channelForTransactionName(
|
|
73
|
+
metric.transaction && metric.transaction.name,
|
|
74
|
+
);
|
|
75
|
+
if (
|
|
76
|
+
channel &&
|
|
77
|
+
typeof this._agent._apmClient.sendToChannel === 'function'
|
|
78
|
+
) {
|
|
79
|
+
this._agent._apmClient.sendToChannel(channel, 'metricset', metric);
|
|
80
|
+
} else {
|
|
81
|
+
this._agent._apmClient.sendMetricSet(metric);
|
|
82
|
+
}
|
|
71
83
|
}
|
|
72
84
|
}
|
|
73
85
|
});
|