@redthreadlabs/tracelog 1.4.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/LICENSE +26 -0
- package/README.md +126 -0
- package/index.d.ts +464 -0
- package/index.js +11 -0
- package/lib/InflightEventSet.js +53 -0
- package/lib/activation-method.js +97 -0
- package/lib/agent.js +1226 -0
- package/lib/apm-client/apm-client.js +107 -0
- package/lib/apm-client/channel-writer.js +334 -0
- package/lib/apm-client/jsonl-file-client.js +241 -0
- package/lib/apm-client/ndjson.js +20 -0
- package/lib/apm-client/noop-apm-client.js +79 -0
- package/lib/apm-client/s3-uploader.js +308 -0
- package/lib/apm-client/truncate.js +507 -0
- package/lib/async-hooks-polyfill.js +58 -0
- package/lib/cloud-metadata/aws.js +175 -0
- package/lib/cloud-metadata/azure.js +123 -0
- package/lib/cloud-metadata/callback-coordination.js +159 -0
- package/lib/cloud-metadata/gcp.js +133 -0
- package/lib/cloud-metadata/index.js +175 -0
- package/lib/config/config.js +431 -0
- package/lib/config/normalizers.js +649 -0
- package/lib/config/schema.js +946 -0
- package/lib/constants.js +35 -0
- package/lib/errors.js +303 -0
- package/lib/filters/sanitize-field-names.js +69 -0
- package/lib/http-request.js +249 -0
- package/lib/instrumentation/context.js +56 -0
- package/lib/instrumentation/dropped-spans-stats.js +112 -0
- package/lib/instrumentation/elasticsearch-shared.js +63 -0
- package/lib/instrumentation/express-utils.js +91 -0
- package/lib/instrumentation/generic-span.js +322 -0
- package/lib/instrumentation/http-shared.js +424 -0
- package/lib/instrumentation/ids.js +39 -0
- package/lib/instrumentation/index.js +1078 -0
- package/lib/instrumentation/modules/@apollo/server.js +39 -0
- package/lib/instrumentation/modules/@aws-sdk/client-dynamodb.js +143 -0
- package/lib/instrumentation/modules/@aws-sdk/client-s3.js +230 -0
- package/lib/instrumentation/modules/@aws-sdk/client-sns.js +197 -0
- package/lib/instrumentation/modules/@aws-sdk/client-sqs.js +336 -0
- package/lib/instrumentation/modules/@elastic/elasticsearch.js +343 -0
- package/lib/instrumentation/modules/@hapi/hapi.js +221 -0
- package/lib/instrumentation/modules/@redis/client/dist/lib/client/commands-queue.js +178 -0
- package/lib/instrumentation/modules/@redis/client/dist/lib/client/index.js +49 -0
- package/lib/instrumentation/modules/@smithy/smithy-client.js +198 -0
- package/lib/instrumentation/modules/apollo-server-core.js +49 -0
- package/lib/instrumentation/modules/aws-sdk/dynamodb.js +155 -0
- package/lib/instrumentation/modules/aws-sdk/s3.js +184 -0
- package/lib/instrumentation/modules/aws-sdk/sns.js +232 -0
- package/lib/instrumentation/modules/aws-sdk/sqs.js +361 -0
- package/lib/instrumentation/modules/aws-sdk.js +76 -0
- package/lib/instrumentation/modules/bluebird.js +93 -0
- package/lib/instrumentation/modules/cassandra-driver.js +280 -0
- package/lib/instrumentation/modules/elasticsearch.js +200 -0
- package/lib/instrumentation/modules/express-graphql.js +66 -0
- package/lib/instrumentation/modules/express-queue.js +28 -0
- package/lib/instrumentation/modules/express.js +162 -0
- package/lib/instrumentation/modules/fastify.js +179 -0
- package/lib/instrumentation/modules/finalhandler.js +41 -0
- package/lib/instrumentation/modules/generic-pool.js +85 -0
- package/lib/instrumentation/modules/graphql.js +256 -0
- package/lib/instrumentation/modules/handlebars.js +33 -0
- package/lib/instrumentation/modules/http.js +112 -0
- package/lib/instrumentation/modules/http2.js +320 -0
- package/lib/instrumentation/modules/https.js +68 -0
- package/lib/instrumentation/modules/ioredis.js +94 -0
- package/lib/instrumentation/modules/jade.js +29 -0
- package/lib/instrumentation/modules/kafkajs.js +476 -0
- package/lib/instrumentation/modules/knex.js +91 -0
- package/lib/instrumentation/modules/koa-router.js +74 -0
- package/lib/instrumentation/modules/koa.js +15 -0
- package/lib/instrumentation/modules/memcached.js +100 -0
- package/lib/instrumentation/modules/mimic-response.js +45 -0
- package/lib/instrumentation/modules/mongodb/lib/cmap/connection_pool.js +40 -0
- package/lib/instrumentation/modules/mongodb-core.js +206 -0
- package/lib/instrumentation/modules/mongodb.js +259 -0
- package/lib/instrumentation/modules/mysql.js +200 -0
- package/lib/instrumentation/modules/mysql2.js +140 -0
- package/lib/instrumentation/modules/pg.js +148 -0
- package/lib/instrumentation/modules/pug.js +29 -0
- package/lib/instrumentation/modules/redis.js +176 -0
- package/lib/instrumentation/modules/restify.js +52 -0
- package/lib/instrumentation/modules/tedious.js +159 -0
- package/lib/instrumentation/modules/undici.js +270 -0
- package/lib/instrumentation/modules/ws.js +59 -0
- package/lib/instrumentation/noop-transaction.js +81 -0
- package/lib/instrumentation/run-context/AbstractRunContextManager.js +215 -0
- package/lib/instrumentation/run-context/AsyncHooksRunContextManager.js +106 -0
- package/lib/instrumentation/run-context/AsyncLocalStorageRunContextManager.js +73 -0
- package/lib/instrumentation/run-context/BasicRunContextManager.js +82 -0
- package/lib/instrumentation/run-context/RunContext.js +151 -0
- package/lib/instrumentation/run-context/index.js +23 -0
- package/lib/instrumentation/shimmer.js +123 -0
- package/lib/instrumentation/span-compression.js +239 -0
- package/lib/instrumentation/span.js +621 -0
- package/lib/instrumentation/template-shared.js +43 -0
- package/lib/instrumentation/timer.js +84 -0
- package/lib/instrumentation/transaction.js +571 -0
- package/lib/load-source-map.js +100 -0
- package/lib/logging.js +212 -0
- package/lib/metrics/index.js +92 -0
- package/lib/metrics/platforms/generic/index.js +40 -0
- package/lib/metrics/platforms/generic/process-cpu.js +22 -0
- package/lib/metrics/platforms/generic/process-top.js +157 -0
- package/lib/metrics/platforms/generic/stats.js +34 -0
- package/lib/metrics/platforms/generic/system-cpu.js +51 -0
- package/lib/metrics/platforms/linux/index.js +19 -0
- package/lib/metrics/platforms/linux/stats.js +213 -0
- package/lib/metrics/queue.js +90 -0
- package/lib/metrics/registry.js +52 -0
- package/lib/metrics/reporter.js +119 -0
- package/lib/metrics/runtime.js +77 -0
- package/lib/middleware/connect.js +16 -0
- package/lib/parsers.js +225 -0
- package/lib/propwrap.js +147 -0
- package/lib/stacktraces.js +537 -0
- package/lib/symbols.js +15 -0
- package/lib/tracecontext/index.js +115 -0
- package/lib/tracecontext/traceparent.js +185 -0
- package/lib/tracecontext/tracestate.js +388 -0
- package/lib/wildcard-matcher.js +52 -0
- package/loader.mjs +7 -0
- package/package.json +98 -0
- package/start.d.ts +8 -0
- package/start.js +29 -0
- package/types/aws-lambda.d.ts +98 -0
- package/types/connect.d.ts +23 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2012, Matt Robenolt
|
|
4
|
+
Copyright (c) 2013-2014, Thomas Watson Steen and Elasticsearch B.V.
|
|
5
|
+
Copyright (c) 2015-2023, Elasticsearch B.V.
|
|
6
|
+
|
|
7
|
+
Redistribution and use in source and binary forms, with or without
|
|
8
|
+
modification, are permitted provided that the following conditions are met:
|
|
9
|
+
|
|
10
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
11
|
+
list of conditions and the following disclaimer.
|
|
12
|
+
|
|
13
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
14
|
+
this list of conditions and the following disclaimer in the documentation
|
|
15
|
+
and/or other materials provided with the distribution.
|
|
16
|
+
|
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
18
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
19
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
20
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
21
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
22
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
23
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
24
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
25
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Tracelog
|
|
2
|
+
|
|
3
|
+
Node.js APM instrumentation that writes traces to local JSONL files, with automatic rotation and optional S3 upload.
|
|
4
|
+
|
|
5
|
+
Forked from [elastic-apm-node](https://github.com/elastic/apm-agent-nodejs) v4.15.0. All 43 auto-instrumentation modules are preserved (Express, Fastify, Koa, PostgreSQL, MongoDB, Redis, AWS SDK, etc.), but instead of shipping data to an Elastic APM server, everything is written to timestamped `.jsonl` files on disk with time-based and size-based rotation.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npm install tracelog
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Start tracelog at the very top of your application, before importing anything else:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
require('tracelog').start({
|
|
19
|
+
serviceName: 'my-api',
|
|
20
|
+
serviceVersion: '1.0.0',
|
|
21
|
+
logDir: '/var/log/myapp',
|
|
22
|
+
s3Bucket: 'my-traces',
|
|
23
|
+
s3Region: 'us-east-1',
|
|
24
|
+
s3KeyTemplate: '{serviceName}/{environment}/{date}/{hostname}-{pid}-{timestamp}.jsonl',
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or use the auto-start entry point with environment variables:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
TRACELOG_SERVICE_NAME=my-api \
|
|
32
|
+
node -r tracelog/start app.js
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
That's it. Tracelog will automatically instrument your HTTP servers, database clients, and other modules, writing transaction, span, error, and metric data to the JSONL file. If `s3Bucket` is set, completed (rotated) files are gzipped and uploaded to S3, then deleted locally.
|
|
36
|
+
|
|
37
|
+
## Custom events
|
|
38
|
+
|
|
39
|
+
Tracelog adds a custom **event** type that has no equivalent in Elastic APM or OpenTelemetry. Events are free-form records for anything that isn't a trace, error, or metric — user analytics, audit logs, client-side telemetry from mobile or browser apps, or structured log lines.
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
// Single event
|
|
43
|
+
apm.captureEvent('page_view', {
|
|
44
|
+
message: 'User viewed dashboard',
|
|
45
|
+
level: 'info',
|
|
46
|
+
user: { id: 'u-abc123', username: 'jane_doe' },
|
|
47
|
+
client: { name: 'duiduidui-ios', version: '2.4.1' },
|
|
48
|
+
params: { page: '/dashboard', referrer: '/home' },
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Events support standardized fields for user identity (`user`), client environment (`client`), severity (`level`), timing (`duration`), and an open-ended `params` object for anything else. Only `type` is required.
|
|
53
|
+
|
|
54
|
+
For server endpoints that receive batches of events from client devices, use `captureEvents`:
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
// Batch — e.g. from a mobile app uploading queued events
|
|
58
|
+
app.post('/events', (req, res) => {
|
|
59
|
+
apm.captureEvents(req.body.events, () => res.sendStatus(202));
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Each event in the batch is individually filtered (via `addEventFilter`) and written as a separate JSONL line. See **[SCHEMA.md](SCHEMA.md)** for the full event schema.
|
|
64
|
+
|
|
65
|
+
## Output format
|
|
66
|
+
|
|
67
|
+
Each line is a self-contained JSON object with one top-level key identifying the event type. There are six event types: `metadata`, `transaction`, `span`, `error`, `metricset`, and `event`. Files start with a metadata line:
|
|
68
|
+
|
|
69
|
+
```jsonl
|
|
70
|
+
{"metadata":{"service":{"name":"my-api","version":"1.0.0"},"process":{"pid":1234},"system":{"hostname":"ip-10-0-1-42"},"cloud":{"provider":"aws","instance":{"id":"i-0abc123"},"availability_zone":"us-east-1a"}}}
|
|
71
|
+
{"transaction":{"id":"abc123","trace_id":"def456","name":"GET /users","type":"request","duration":42.5,"result":"HTTP 2xx","sampled":true,"outcome":"success","span_count":{"started":1}}}
|
|
72
|
+
{"span":{"id":"ghi789","transaction_id":"abc123","trace_id":"def456","parent_id":"abc123","name":"SELECT * FROM users","type":"db","subtype":"postgresql","duration":12.3,"sync":true,"outcome":"success"}}
|
|
73
|
+
{"error":{"id":"err001","timestamp":1709740800000000,"exception":{"message":"Something broke","type":"TypeError","handled":false,"stacktrace":[...]}}}
|
|
74
|
+
{"metricset":{"timestamp":1709740800000000,"samples":{"system.process.cpu.total.norm.pct":{"value":0.023},"nodejs.memory.heap.used.bytes":{"value":52428800}}}}
|
|
75
|
+
{"event":{"type":"page_view","timestamp":1719484200000,"message":"User viewed dashboard","level":"info","user":{"id":"u-abc123","username":"jane_doe"},"client":{"name":"duiduidui-ios","version":"2.4.1","os":{"name":"iOS","version":"18.2"},"device":{"model":"iPhone 16 Pro","type":"phone"}},"params":{"page":"/dashboard"}}}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
For the complete schema of every field in each event type, see **[SCHEMA.md](SCHEMA.md)**.
|
|
79
|
+
|
|
80
|
+
## Configuration
|
|
81
|
+
|
|
82
|
+
All options can be set via `require('tracelog').start({...})`, via environment variables, or in a `tracelog.config.js` file.
|
|
83
|
+
|
|
84
|
+
| Option | Env Var | Default | Description |
|
|
85
|
+
|--------|---------|---------|-------------|
|
|
86
|
+
| `serviceName` | `TRACELOG_SERVICE_NAME` | from package.json | Name of your service |
|
|
87
|
+
| `serviceVersion` | `TRACELOG_SERVICE_VERSION` | from package.json | Version of your service |
|
|
88
|
+
| `environment` | `TRACELOG_ENVIRONMENT` | `NODE_ENV` or `development` | Deployment environment |
|
|
89
|
+
| `logDir` | `TRACELOG_LOG_DIR` | `.` (cwd) | Directory for JSONL output files |
|
|
90
|
+
| `logFilePrefix` | `TRACELOG_LOG_FILE_PREFIX` | `tracelog` | Filename prefix (files are named `{prefix}-{date}.jsonl`) |
|
|
91
|
+
| `logMaxFileSize` | — | `104857600` (100MB) | Rotate when file exceeds this size in bytes |
|
|
92
|
+
| `logRotationSchedule` | `TRACELOG_LOG_ROTATION_SCHEDULE` | `daily` | Time-based rotation: `daily` or `hourly` |
|
|
93
|
+
| `s3Bucket` | `TRACELOG_S3_BUCKET` | — | S3 bucket for log upload (disabled if not set) |
|
|
94
|
+
| `active` | `TRACELOG_ACTIVE` | `true` | Enable/disable the agent entirely |
|
|
95
|
+
| `logLevel` | `TRACELOG_LOG_LEVEL` | `info` | Agent log level |
|
|
96
|
+
|
|
97
|
+
For the complete list of all configuration options (instrumentation, sampling, error capture, stack traces, span compression, metrics, S3 upload, cloud, and more), see **[CONFIG.md](CONFIG.md)**.
|
|
98
|
+
|
|
99
|
+
## Filtering
|
|
100
|
+
|
|
101
|
+
Filter functions let you modify or drop events before they are written. Return the (possibly modified) object to keep it, or return a falsy value to drop it.
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
const apm = require('tracelog').start({ serviceName: 'my-api' });
|
|
105
|
+
|
|
106
|
+
// Drop all debug-level custom events
|
|
107
|
+
apm.addEventFilter((event) => {
|
|
108
|
+
return event.level === 'debug' ? false : event;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Redact user emails from custom events
|
|
112
|
+
apm.addEventFilter((event) => {
|
|
113
|
+
if (event.user) event.user.email = '[REDACTED]';
|
|
114
|
+
return event;
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Available filter methods: `addFilter(fn)` (adds to all types), `addTransactionFilter(fn)`, `addSpanFilter(fn)`, `addErrorFilter(fn)`, `addEventFilter(fn)`, `addMetadataFilter(fn)`.
|
|
119
|
+
|
|
120
|
+
## Auto-instrumented modules
|
|
121
|
+
|
|
122
|
+
Express, Fastify, Koa, Hapi, Connect, Restify, HTTP/HTTPS, fetch/undici, PostgreSQL, MySQL, MongoDB, Redis, Elasticsearch, Cassandra, Memcached, AWS SDK (v2 & v3), GraphQL, Apollo Server, Kafka, WebSockets, generic-pool, Knex, Tedious (MSSQL), Handlebars, Pug, and more.
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
[BSD-2-Clause](LICENSE) — forked from Elastic APM Node.js Agent.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and other contributors where applicable.
|
|
3
|
+
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
4
|
+
* compliance with the BSD 2-Clause License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/// <reference types="node" />
|
|
8
|
+
|
|
9
|
+
// Note: We avoid import of any external `@types/...` to avoid TypeScript users
|
|
10
|
+
// needing to manually install them. The only exception is the prerequisite to
|
|
11
|
+
// `npm install -D @types/node`.
|
|
12
|
+
import type { IncomingMessage, ServerResponse } from 'http';
|
|
13
|
+
import { Connect } from './types/connect';
|
|
14
|
+
import { AwsLambda } from './types/aws-lambda';
|
|
15
|
+
|
|
16
|
+
declare namespace apm {
|
|
17
|
+
// Agent API
|
|
18
|
+
// https://www.elastic.co/guide/en/apm/agent/nodejs/current/agent-api.html
|
|
19
|
+
export interface Agent {
|
|
20
|
+
// Configuration
|
|
21
|
+
start (options?: AgentConfigOptions): Agent;
|
|
22
|
+
isStarted (): boolean;
|
|
23
|
+
getServiceName (): string | undefined;
|
|
24
|
+
getServiceVersion (): string | undefined;
|
|
25
|
+
getServiceEnvironment (): string;
|
|
26
|
+
getServiceNodeName (): string | undefined;
|
|
27
|
+
setFramework (options: {
|
|
28
|
+
name?: string;
|
|
29
|
+
version?: string;
|
|
30
|
+
overwrite?: boolean;
|
|
31
|
+
}): void;
|
|
32
|
+
addPatch (modules: string | Array<string>, handler: string | PatchHandler): void;
|
|
33
|
+
removePatch (modules: string | Array<string>, handler: string | PatchHandler): void;
|
|
34
|
+
clearPatches (modules: string | Array<string>): void;
|
|
35
|
+
|
|
36
|
+
// Data collection hooks
|
|
37
|
+
middleware: { connect (): Connect.ErrorHandleFunction };
|
|
38
|
+
lambda (handler: AwsLambda.Handler): AwsLambda.Handler;
|
|
39
|
+
lambda (type: string, handler: AwsLambda.Handler): AwsLambda.Handler;
|
|
40
|
+
handleUncaughtExceptions (
|
|
41
|
+
fn?: (err: Error) => void
|
|
42
|
+
): void;
|
|
43
|
+
|
|
44
|
+
// Write methods (primary API)
|
|
45
|
+
writeError (err: Error | string | ParameterizedMessageObject, callback?: CaptureErrorCallback): void;
|
|
46
|
+
writeError (err: Error | string | ParameterizedMessageObject, options?: CaptureErrorOptions, callback?: CaptureErrorCallback): void;
|
|
47
|
+
writeEvent (type: string, options?: CaptureEventOptions, callback?: Function): void;
|
|
48
|
+
writeEvents (events: CaptureEventData[], callback?: Function): void;
|
|
49
|
+
writeTransaction (transaction: object): void;
|
|
50
|
+
writeSpan (span: object): void;
|
|
51
|
+
|
|
52
|
+
// Backward compat aliases
|
|
53
|
+
captureError (err: Error | string | ParameterizedMessageObject, callback?: CaptureErrorCallback): void;
|
|
54
|
+
captureError (err: Error | string | ParameterizedMessageObject, options?: CaptureErrorOptions, callback?: CaptureErrorCallback): void;
|
|
55
|
+
captureEvent (type: string, options?: CaptureEventOptions, callback?: Function): void;
|
|
56
|
+
captureEvents (events: CaptureEventData[], callback?: Function): void;
|
|
57
|
+
writeClientTransaction (transaction: object): void;
|
|
58
|
+
writeClientSpan (span: object): void;
|
|
59
|
+
|
|
60
|
+
// Channels — route records to separate JSONL files
|
|
61
|
+
getChannel (name: string): Channel;
|
|
62
|
+
|
|
63
|
+
// Distributed Tracing
|
|
64
|
+
currentTraceparent: string | null;
|
|
65
|
+
currentTraceIds: {
|
|
66
|
+
'trace.id'?: string;
|
|
67
|
+
'transaction.id'?: string;
|
|
68
|
+
'span.id'?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Transactions
|
|
72
|
+
startTransaction(
|
|
73
|
+
name?: string | null,
|
|
74
|
+
options?: TransactionOptions
|
|
75
|
+
): Transaction;
|
|
76
|
+
startTransaction(
|
|
77
|
+
name: string | null,
|
|
78
|
+
type: string | null,
|
|
79
|
+
options?: TransactionOptions
|
|
80
|
+
): Transaction;
|
|
81
|
+
setTransactionName (name: string): void;
|
|
82
|
+
endTransaction (result?: string | number, endTime?: number): void;
|
|
83
|
+
currentTransaction: Transaction | null;
|
|
84
|
+
|
|
85
|
+
// Spans
|
|
86
|
+
startSpan(
|
|
87
|
+
name?: string | null,
|
|
88
|
+
options?: SpanOptions
|
|
89
|
+
): Span | null;
|
|
90
|
+
startSpan(
|
|
91
|
+
name: string | null,
|
|
92
|
+
type: string | null,
|
|
93
|
+
options?: SpanOptions
|
|
94
|
+
): Span | null;
|
|
95
|
+
startSpan(
|
|
96
|
+
name: string | null,
|
|
97
|
+
type: string | null,
|
|
98
|
+
subtype: string | null,
|
|
99
|
+
options?: SpanOptions
|
|
100
|
+
): Span | null;
|
|
101
|
+
startSpan(
|
|
102
|
+
name: string | null,
|
|
103
|
+
type: string | null,
|
|
104
|
+
subtype: string | null,
|
|
105
|
+
action: string | null,
|
|
106
|
+
options?: SpanOptions
|
|
107
|
+
): Span | null;
|
|
108
|
+
currentSpan: Span | null;
|
|
109
|
+
|
|
110
|
+
// Context
|
|
111
|
+
setGlobalLabel (name: string, value: LabelValue): void;
|
|
112
|
+
setLabel (name: string, value: LabelValue, stringify?: boolean): boolean;
|
|
113
|
+
addLabels (labels: Labels, stringify?: boolean): boolean;
|
|
114
|
+
setUserContext (user: UserObject): void;
|
|
115
|
+
setCustomContext (custom: object): void;
|
|
116
|
+
|
|
117
|
+
// Transport
|
|
118
|
+
addFilter (fn: FilterFn): void;
|
|
119
|
+
addErrorFilter (fn: FilterFn): void;
|
|
120
|
+
addSpanFilter (fn: FilterFn): void;
|
|
121
|
+
addTransactionFilter (fn: FilterFn): void;
|
|
122
|
+
addEventFilter (fn: FilterFn): void;
|
|
123
|
+
addMetadataFilter (fn: FilterFn): void;
|
|
124
|
+
flush (): Promise<void>;
|
|
125
|
+
flush (callback?: Function): void;
|
|
126
|
+
destroy (): Promise<void>;
|
|
127
|
+
|
|
128
|
+
// Utils
|
|
129
|
+
logger: Logger;
|
|
130
|
+
|
|
131
|
+
// Custom metrics
|
|
132
|
+
registerMetric(name: string, callback: Function): void;
|
|
133
|
+
registerMetric(name: string, labels: Labels, callback: Function): void;
|
|
134
|
+
|
|
135
|
+
setTransactionOutcome(outcome: Outcome): void;
|
|
136
|
+
setSpanOutcome(outcome: Outcome): void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
type Outcome = 'unknown' | 'success' | 'failure';
|
|
140
|
+
|
|
141
|
+
// Transaction API
|
|
142
|
+
// https://www.elastic.co/guide/en/apm/agent/nodejs/current/transaction-api.html
|
|
143
|
+
export interface Transaction {
|
|
144
|
+
// The following properties and methods are currently not documented as their API isn't considered official:
|
|
145
|
+
// - timestamp, ended, id, traceId, parentId, sampled, duration()
|
|
146
|
+
// - setUserContext(), setCustomContext(), toJSON(), setDefaultName(), setDefaultNameFromRequest()
|
|
147
|
+
|
|
148
|
+
name: string;
|
|
149
|
+
type: string | null;
|
|
150
|
+
traceparent: string;
|
|
151
|
+
outcome: Outcome;
|
|
152
|
+
result: string | number;
|
|
153
|
+
ids: {
|
|
154
|
+
'trace.id': string;
|
|
155
|
+
'transaction.id': string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
setType (type?: string | null): void;
|
|
159
|
+
setLabel (name: string, value: LabelValue, stringify?: boolean): boolean;
|
|
160
|
+
addLabels (labels: Labels, stringify?: boolean): boolean;
|
|
161
|
+
setOutcome(outcome: Outcome): void;
|
|
162
|
+
addLink (link: Link): void;
|
|
163
|
+
addLinks (links: Link[]): void;
|
|
164
|
+
|
|
165
|
+
startSpan(
|
|
166
|
+
name?: string | null,
|
|
167
|
+
options?: SpanOptions
|
|
168
|
+
): Span | null;
|
|
169
|
+
startSpan(
|
|
170
|
+
name: string | null,
|
|
171
|
+
type: string | null,
|
|
172
|
+
options?: SpanOptions
|
|
173
|
+
): Span | null;
|
|
174
|
+
startSpan(
|
|
175
|
+
name: string | null,
|
|
176
|
+
type: string | null,
|
|
177
|
+
subtype: string | null,
|
|
178
|
+
options?: SpanOptions
|
|
179
|
+
): Span | null;
|
|
180
|
+
startSpan(
|
|
181
|
+
name: string | null,
|
|
182
|
+
type: string | null,
|
|
183
|
+
subtype: string | null,
|
|
184
|
+
action: string | null,
|
|
185
|
+
options?: SpanOptions
|
|
186
|
+
): Span | null;
|
|
187
|
+
ensureParentId (): string;
|
|
188
|
+
end (result?: string | number | null, endTime?: number): void;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Span API
|
|
192
|
+
// https://www.elastic.co/guide/en/apm/agent/nodejs/current/span-api.html
|
|
193
|
+
export interface Span {
|
|
194
|
+
// The following properties and methods are currently not documented as their API isn't considered official:
|
|
195
|
+
// - timestamp, ended, id, traceId, parentId, sampled, duration()
|
|
196
|
+
// - customStackTrace(), setDbContext()
|
|
197
|
+
|
|
198
|
+
transaction: Transaction;
|
|
199
|
+
name: string;
|
|
200
|
+
type: string | null;
|
|
201
|
+
subtype: string | null;
|
|
202
|
+
action: string | null;
|
|
203
|
+
traceparent: string;
|
|
204
|
+
outcome: Outcome;
|
|
205
|
+
ids: {
|
|
206
|
+
'trace.id': string;
|
|
207
|
+
'span.id': string;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
setType (type?: string | null, subtype?: string | null, action?: string | null): void;
|
|
211
|
+
setLabel (name: string, value: LabelValue, stringify?: boolean): boolean;
|
|
212
|
+
addLabels (labels: Labels, stringify?: boolean): boolean;
|
|
213
|
+
setOutcome(outcome: Outcome): void;
|
|
214
|
+
setServiceTarget(type?: string | null, name?: string | null): void;
|
|
215
|
+
addLink (link: Link): void;
|
|
216
|
+
addLinks (links: Link[]): void;
|
|
217
|
+
end (endTime?: number): void;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// https://www.elastic.co/guide/en/apm/agent/nodejs/current/configuration.html
|
|
221
|
+
export interface AgentConfigOptions {
|
|
222
|
+
abortedErrorThreshold?: string; // Also support `number`, but as we're removing this functionality soon, there's no need to advertise it
|
|
223
|
+
active?: boolean;
|
|
224
|
+
addPatch?: KeyValueConfig;
|
|
225
|
+
apiKey?: string;
|
|
226
|
+
apiRequestSize?: string; // Also support `number`, but as we're removing this functionality soon, there's no need to advertise it
|
|
227
|
+
apiRequestTime?: string; // Also support `number`, but as we're removing this functionality soon, there's no need to advertise it
|
|
228
|
+
breakdownMetrics?: boolean;
|
|
229
|
+
captureBody?: CaptureBody;
|
|
230
|
+
captureErrorLogStackTraces?: CaptureErrorLogStackTraces;
|
|
231
|
+
captureExceptions?: boolean;
|
|
232
|
+
captureHeaders?: boolean;
|
|
233
|
+
/**
|
|
234
|
+
* @deprecated Use `spanStackTraceMinDuration`.
|
|
235
|
+
*/
|
|
236
|
+
captureSpanStackTraces?: boolean;
|
|
237
|
+
centralConfig?: boolean;
|
|
238
|
+
cloudProvider?: string;
|
|
239
|
+
configFile?: string;
|
|
240
|
+
containerId?: string;
|
|
241
|
+
contextManager?: string;
|
|
242
|
+
contextPropagationOnly?: boolean;
|
|
243
|
+
disableInstrumentations?: string | string[];
|
|
244
|
+
disableSend?: boolean;
|
|
245
|
+
elasticsearchCaptureBodyUrls?: Array<string>;
|
|
246
|
+
environment?: string;
|
|
247
|
+
/**
|
|
248
|
+
* @deprecated Use `longFieldMaxLength`
|
|
249
|
+
*/
|
|
250
|
+
errorMessageMaxLength?: string;
|
|
251
|
+
errorOnAbortedRequests?: boolean;
|
|
252
|
+
exitSpanMinDuration?: string;
|
|
253
|
+
frameworkName?: string;
|
|
254
|
+
frameworkVersion?: string;
|
|
255
|
+
globalLabels?: KeyValueConfig;
|
|
256
|
+
hostname?: string;
|
|
257
|
+
ignoreMessageQueues?: Array<string>;
|
|
258
|
+
ignoreUrls?: Array<string | RegExp>;
|
|
259
|
+
ignoreUserAgents?: Array<string | RegExp>;
|
|
260
|
+
instrument?: boolean;
|
|
261
|
+
instrumentIncomingHTTPRequests?: boolean;
|
|
262
|
+
kubernetesNamespace?: string;
|
|
263
|
+
kubernetesNodeName?: string;
|
|
264
|
+
kubernetesPodName?: string;
|
|
265
|
+
kubernetesPodUID?: string;
|
|
266
|
+
logLevel?: LogLevel;
|
|
267
|
+
logger?: Logger; // Notably this Logger interface matches the Pino Logger.
|
|
268
|
+
longFieldMaxLength?: number;
|
|
269
|
+
maxQueueSize?: number;
|
|
270
|
+
metricsInterval?: string; // Also support `number`, but as we're removing this functionality soon, there's no need to advertise it
|
|
271
|
+
metricsLimit?: number;
|
|
272
|
+
opentelemetryBridgeEnabled?: boolean;
|
|
273
|
+
payloadLogFile?: string;
|
|
274
|
+
sanitizeFieldNames?: Array<string>;
|
|
275
|
+
secretToken?: string;
|
|
276
|
+
serverCaCertFile?: string;
|
|
277
|
+
serverTimeout?: string; // Also support `number`, but as we're removing this functionality soon, there's no need to advertise it
|
|
278
|
+
serverUrl?: string;
|
|
279
|
+
serviceName?: string;
|
|
280
|
+
serviceNodeName?: string;
|
|
281
|
+
serviceVersion?: string;
|
|
282
|
+
sourceLinesErrorAppFrames?: number;
|
|
283
|
+
sourceLinesErrorLibraryFrames?: number;
|
|
284
|
+
sourceLinesSpanAppFrames?: number;
|
|
285
|
+
sourceLinesSpanLibraryFrames?: number;
|
|
286
|
+
spanCompressionEnabled?: boolean;
|
|
287
|
+
spanCompressionExactMatchMaxDuration?: string;
|
|
288
|
+
spanCompressionSameKindMaxDuration?: string;
|
|
289
|
+
/**
|
|
290
|
+
* @deprecated Use `spanStackTraceMinDuration`.
|
|
291
|
+
*/
|
|
292
|
+
spanFramesMinDuration?: string;
|
|
293
|
+
spanStackTraceMinDuration?: string;
|
|
294
|
+
stackTraceLimit?: number;
|
|
295
|
+
traceContinuationStrategy?: TraceContinuationStrategy;
|
|
296
|
+
transactionIgnoreUrls?: Array<string>;
|
|
297
|
+
transactionMaxSpans?: number;
|
|
298
|
+
transactionSampleRate?: number;
|
|
299
|
+
useElasticTraceparentHeader?: boolean;
|
|
300
|
+
usePathAsTransactionName?: boolean;
|
|
301
|
+
verifyServerCert?: boolean;
|
|
302
|
+
|
|
303
|
+
// Tracelog: output & rotation
|
|
304
|
+
logDir?: string;
|
|
305
|
+
logFilePrefix?: string;
|
|
306
|
+
logMaxFileSize?: number;
|
|
307
|
+
logFlushIntervalMs?: number;
|
|
308
|
+
logRotationSchedule?: 'daily' | 'hourly' | string;
|
|
309
|
+
maxLocalRetentionDays?: number;
|
|
310
|
+
maxBufferSize?: number;
|
|
311
|
+
|
|
312
|
+
// Tracelog: S3 upload
|
|
313
|
+
s3Bucket?: string;
|
|
314
|
+
s3Region?: string;
|
|
315
|
+
s3KeyTemplate?: string;
|
|
316
|
+
s3UploadIntervalMs?: number;
|
|
317
|
+
s3GzipCompleted?: boolean;
|
|
318
|
+
s3GzipCurrent?: boolean;
|
|
319
|
+
s3AccessKeyId?: string;
|
|
320
|
+
s3SecretAccessKey?: string;
|
|
321
|
+
s3SessionToken?: string;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
interface Channel {
|
|
325
|
+
writeEvent (type: string, options?: CaptureEventOptions, callback?: Function): void;
|
|
326
|
+
writeEvents (events: CaptureEventData[], callback?: Function): void;
|
|
327
|
+
writeError (err: Error | string | ParameterizedMessageObject, options?: CaptureErrorOptions, callback?: CaptureErrorCallback): void;
|
|
328
|
+
writeTransaction (transaction: object): void;
|
|
329
|
+
writeSpan (span: object): void;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
interface CaptureEventOptions {
|
|
333
|
+
message?: string;
|
|
334
|
+
level?: 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
335
|
+
timestamp?: number;
|
|
336
|
+
duration?: number;
|
|
337
|
+
error?: Error | any;
|
|
338
|
+
user?: EventUserInfo;
|
|
339
|
+
client?: EventClientInfo;
|
|
340
|
+
params?: { [key: string]: any };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
interface CaptureEventData extends CaptureEventOptions {
|
|
344
|
+
type: string;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
interface EventUserInfo {
|
|
348
|
+
id?: string;
|
|
349
|
+
email?: string;
|
|
350
|
+
username?: string;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
interface EventClientInfo {
|
|
354
|
+
name?: string;
|
|
355
|
+
version?: string;
|
|
356
|
+
os?: { name?: string; version?: string };
|
|
357
|
+
device?: { model?: string; type?: string };
|
|
358
|
+
runtime?: { name?: string; version?: string };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
interface CaptureErrorOptions {
|
|
362
|
+
request?: IncomingMessage;
|
|
363
|
+
response?: ServerResponse;
|
|
364
|
+
timestamp?: number;
|
|
365
|
+
handled?: boolean;
|
|
366
|
+
user?: UserObject;
|
|
367
|
+
labels?: Labels;
|
|
368
|
+
tags?: Labels;
|
|
369
|
+
custom?: object;
|
|
370
|
+
message?: string;
|
|
371
|
+
captureAttributes?: boolean;
|
|
372
|
+
skipOutcome?: boolean;
|
|
373
|
+
/**
|
|
374
|
+
* A Transaction or Span instance to make the parent of this error. If not
|
|
375
|
+
* given (undefined), then the current span or transaction will be used. If
|
|
376
|
+
* `null` is given, then no span or transaction will be used.
|
|
377
|
+
*/
|
|
378
|
+
parent?: Transaction | Span | null;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
interface Labels {
|
|
382
|
+
[key: string]: LabelValue;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
interface UserObject {
|
|
386
|
+
id?: string | number;
|
|
387
|
+
username?: string;
|
|
388
|
+
email?: string;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
interface ParameterizedMessageObject {
|
|
392
|
+
message: string;
|
|
393
|
+
params: Array<any>;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
interface Logger {
|
|
397
|
+
// Defining overloaded methods rather than a separate `interface LogFn`
|
|
398
|
+
// as @types/pino does, because the IDE completion shows these as *methods*
|
|
399
|
+
// rather than as properties, which is slightly nicer.
|
|
400
|
+
fatal (msg: string, ...args: any[]): void;
|
|
401
|
+
fatal (obj: {}, msg?: string, ...args: any[]): void;
|
|
402
|
+
error (msg: string, ...args: any[]): void;
|
|
403
|
+
error (obj: {}, msg?: string, ...args: any[]): void;
|
|
404
|
+
warn (msg: string, ...args: any[]): void;
|
|
405
|
+
warn (obj: {}, msg?: string, ...args: any[]): void;
|
|
406
|
+
info (msg: string, ...args: any[]): void;
|
|
407
|
+
info (obj: {}, msg?: string, ...args: any[]): void;
|
|
408
|
+
debug (msg: string, ...args: any[]): void;
|
|
409
|
+
debug (obj: {}, msg?: string, ...args: any[]): void;
|
|
410
|
+
trace (msg: string, ...args: any[]): void;
|
|
411
|
+
trace (obj: {}, msg?: string, ...args: any[]): void;
|
|
412
|
+
// Allow a passed in Logger that has other properties, as a Pino logger
|
|
413
|
+
// does. Discussion:
|
|
414
|
+
// https://github.com/elastic/apm-agent-nodejs/pull/926/files#r266239656
|
|
415
|
+
[propName: string]: any;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Link and `links` are intended to be compatible with OTel's
|
|
419
|
+
// equivalent APIs in "opentelemetry-js-api/src/trace/link.ts". Currently
|
|
420
|
+
// span link attributes are not supported.
|
|
421
|
+
export interface Link {
|
|
422
|
+
/** A W3C trace-context 'traceparent' string, Transaction, Span, or OTel SpanContext. */
|
|
423
|
+
context: Transaction | Span | {traceId: string, spanId: string} | string;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export interface TransactionOptions {
|
|
427
|
+
startTime?: number;
|
|
428
|
+
// `childOf` is a W3C trace-context 'traceparent' string. Passing a
|
|
429
|
+
// Transaction or Span is deprecated.
|
|
430
|
+
childOf?: Transaction | Span | string;
|
|
431
|
+
tracestate?: string; // A W3C trace-context 'tracestate' string.
|
|
432
|
+
links?: Link[];
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export interface SpanOptions {
|
|
436
|
+
startTime?: number;
|
|
437
|
+
childOf?: Transaction | Span | string;
|
|
438
|
+
exitSpan?: boolean;
|
|
439
|
+
links?: Link[];
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
type CaptureBody = 'off' | 'errors' | 'transactions' | 'all';
|
|
443
|
+
type CaptureErrorLogStackTraces = 'never' | 'messages' | 'always';
|
|
444
|
+
type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'warning' | 'error' | 'fatal' | 'critical' | 'off';
|
|
445
|
+
type TraceContinuationStrategy = 'continue' | 'restart' | 'restart_external';
|
|
446
|
+
|
|
447
|
+
type CaptureErrorCallback = (err: Error | null, id: string) => void;
|
|
448
|
+
type FilterFn = (payload: Payload) => Payload | boolean | void;
|
|
449
|
+
type LabelValue = string | number | boolean | null | undefined;
|
|
450
|
+
type KeyValueConfig = string | Labels | Array<Array<LabelValue>>
|
|
451
|
+
|
|
452
|
+
type Payload = { [propName: string]: any }
|
|
453
|
+
|
|
454
|
+
type PatchHandler = (exports: any, agent: Agent, options: PatchOptions) => any;
|
|
455
|
+
|
|
456
|
+
interface PatchOptions {
|
|
457
|
+
name: string;
|
|
458
|
+
version: string | undefined;
|
|
459
|
+
enabled: boolean;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
declare const apm: apm.Agent;
|
|
464
|
+
export = apm;
|
package/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and other contributors where applicable.
|
|
3
|
+
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
4
|
+
* compliance with the BSD 2-Clause License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
var Agent = require('./lib/agent');
|
|
10
|
+
|
|
11
|
+
module.exports = new Agent();
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and other contributors where applicable.
|
|
3
|
+
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
4
|
+
* compliance with the BSD 2-Clause License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
// A `Set` object used to track inflight APM events: ended spans and errors
|
|
10
|
+
// that are currently being processed, but have not yet been sent to the Agent
|
|
11
|
+
// transport.
|
|
12
|
+
//
|
|
13
|
+
// `setDrainHandler` allows setting a function to be called when the inflight
|
|
14
|
+
// events have drained. Agent#flush() uses this to ensure that a flush waits
|
|
15
|
+
// for inflight events to be processed, so they are sent to APM Server before
|
|
16
|
+
// calling back.
|
|
17
|
+
class InflightEventSet extends Set {
|
|
18
|
+
// Set a `fn` to be called *once* when the set size next goes to zero.
|
|
19
|
+
// If the optional `timeoutMs` is given, then `fn(err)` will be called if
|
|
20
|
+
// the set hasn't yet drained.
|
|
21
|
+
setDrainHandler(fn, timeoutMs) {
|
|
22
|
+
this._drainHandler = fn;
|
|
23
|
+
if (timeoutMs) {
|
|
24
|
+
this._drainTimeout = setTimeout(() => {
|
|
25
|
+
this._drain(new Error('inflight event set drain timeout'));
|
|
26
|
+
}, timeoutMs).unref();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Call the drain handler, if there is one.
|
|
31
|
+
_drain(err) {
|
|
32
|
+
if (this._drainHandler) {
|
|
33
|
+
if (this._drainTimeout) {
|
|
34
|
+
clearTimeout(this._drainTimeout);
|
|
35
|
+
this._drainTimeout = null;
|
|
36
|
+
}
|
|
37
|
+
this._drainHandler(err);
|
|
38
|
+
// Remove the handler so it is only called once.
|
|
39
|
+
this._drainHandler = null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
delete(key) {
|
|
44
|
+
super.delete(key);
|
|
45
|
+
if (this.size === 0) {
|
|
46
|
+
this._drain();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = {
|
|
52
|
+
InflightEventSet,
|
|
53
|
+
};
|