newrelic 13.13.0 → 13.15.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/NEWS.md +66 -0
- package/THIRD_PARTY_NOTICES.md +11 -11
- package/lib/aggregators/base-aggregator.js +2 -0
- package/lib/aggregators/profiling-aggregator.js +6 -1
- package/lib/errors/index.js +81 -21
- package/lib/harvester.js +18 -3
- package/lib/instrumentation/@azure/functions.js +45 -1
- package/lib/instrumentation/aws-sdk/v3/bedrock.js +15 -12
- package/lib/{llm-events/aws-bedrock → instrumentation/aws-sdk/v3}/converse-stream-handler.js +12 -0
- package/lib/{llm-events/aws-bedrock → instrumentation/aws-sdk/v3}/stream-handler.js +13 -0
- package/lib/instrumentation/redis.js +1 -0
- package/lib/instrumentations.js +0 -5
- package/lib/llm-events/aws-bedrock/bedrock-command.js +1 -1
- package/lib/llm-events/aws-bedrock/bedrock-response.js +1 -1
- package/lib/llm-events/aws-bedrock/chat-completion-message.js +40 -64
- package/lib/llm-events/aws-bedrock/chat-completion-summary.js +37 -41
- package/lib/llm-events/aws-bedrock/embedding.js +31 -29
- package/lib/llm-events/aws-bedrock/index.js +4 -9
- package/lib/llm-events/chat-completion-summary.js +6 -1
- package/lib/llm-events/error-message.js +2 -2
- package/lib/llm-events/google-genai/chat-completion-message.js +24 -30
- package/lib/llm-events/google-genai/chat-completion-summary.js +33 -11
- package/lib/llm-events/google-genai/embedding.js +25 -12
- package/lib/llm-events/google-genai/get-usage-tokens.js +26 -0
- package/lib/llm-events/google-genai/index.js +4 -12
- package/lib/llm-events/langgraph/agent.js +13 -29
- package/lib/llm-events/openai/chat-completion-summary.js +4 -2
- package/lib/profiling/index.js +2 -1
- package/lib/spans/span-event.js +8 -8
- package/lib/subscriber-configs.js +3 -0
- package/lib/subscribers/ai-monitoring/chat.js +9 -7
- package/lib/subscribers/ai-monitoring/embedding.js +1 -1
- package/lib/subscribers/google-genai/config.js +20 -2
- package/lib/subscribers/google-genai/embed-content.js +11 -1
- package/lib/subscribers/google-genai/generate-content-stream.js +3 -0
- package/lib/subscribers/google-genai/generate-content.js +40 -10
- package/lib/subscribers/langgraph/graph-stream.js +3 -3
- package/lib/subscribers/nestjs/config.js +27 -0
- package/lib/subscribers/nestjs/instrumentation.js +39 -0
- package/lib/subscribers/node-redis-client/add-command.js +13 -0
- package/lib/subscribers/node-redis-client/config.js +63 -0
- package/lib/subscribers/node-redis-client/multi.js +13 -0
- package/lib/subscribers/node-redis-client/send-command.js +12 -0
- package/lib/subscribers/openai/chat.js +11 -1
- package/lib/subscribers/redis-client/add-command.js +46 -0
- package/lib/subscribers/redis-client/client-propagation.js +108 -0
- package/lib/subscribers/redis-client/config.js +83 -0
- package/lib/subscribers/redis-client/multi.js +17 -0
- package/lib/subscribers/redis-client/send-command.js +17 -0
- package/lib/transaction/trace/partial-trace.js +9 -6
- package/package.json +2 -2
- package/lib/instrumentation/@nestjs/core.js +0 -35
- package/lib/instrumentation/@node-redis/client.js +0 -114
- package/lib/instrumentation/@redis/client.js +0 -7
- package/lib/instrumentation/generic-pool.js +0 -33
- package/lib/instrumentation/superagent.js +0 -68
- package/lib/llm-events/aws-bedrock/event.js +0 -79
- package/lib/llm-events/event.js +0 -130
- package/lib/llm-events/google-genai/event.js +0 -36
- package/lib/llm-events/aws-bedrock/{utils.js → stringify-message.js} +5 -5
package/NEWS.md
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
+
### v13.15.0 (2026-03-09)
|
|
2
|
+
|
|
3
|
+
#### Features
|
|
4
|
+
|
|
5
|
+
* Added `time_to_first_token` for `LlmChatCompletionSummary` ([#3781](https://github.com/newrelic/node-newrelic/pull/3781)) ([737f374](https://github.com/newrelic/node-newrelic/commit/737f3740d43908be348a7795dd2c85e7a4e88cb8))
|
|
6
|
+
* Added `time_to_first_token` for AWS Bedrock ([#3804](https://github.com/newrelic/node-newrelic/pull/3804)) ([a993b00](https://github.com/newrelic/node-newrelic/commit/a993b00b4fa55fb2e7ba0b7748c4c21d8660b911))
|
|
7
|
+
* Added `time_to_first_token` for Google Gen AI ([#3785](https://github.com/newrelic/node-newrelic/pull/3785)) ([d90ee70](https://github.com/newrelic/node-newrelic/commit/d90ee709538e430395c0fb5863c344fe37009ce5))
|
|
8
|
+
* Added `time_to_first_token` for OpenAI ([#3782](https://github.com/newrelic/node-newrelic/pull/3782)) ([07cfd57](https://github.com/newrelic/node-newrelic/commit/07cfd570d5cc3dd77a5ae23e88587d47af3d195a))
|
|
9
|
+
|
|
10
|
+
#### Code refactoring
|
|
11
|
+
|
|
12
|
+
* Migrated `redis` 4+ instrumentation to subscribe to events emitted ([#3773](https://github.com/newrelic/node-newrelic/pull/3773)) ([add6827](https://github.com/newrelic/node-newrelic/commit/add68278d29f5f415134426d33986a59c089d71f))
|
|
13
|
+
|
|
14
|
+
#### Documentation
|
|
15
|
+
|
|
16
|
+
* Updated compatibility report ([#3800](https://github.com/newrelic/node-newrelic/pull/3800)) ([5228cdc](https://github.com/newrelic/node-newrelic/commit/5228cdc0508217fa139d8b4f8232391fd063a5fa)) ([#3795](https://github.com/newrelic/node-newrelic/pull/3795)) ([1d6fe52](https://github.com/newrelic/node-newrelic/commit/1d6fe522f0e707729a4a01f5c5e5599670136917)) ([#3791](https://github.com/newrelic/node-newrelic/pull/3791)) ([e79db5b](https://github.com/newrelic/node-newrelic/commit/e79db5bbac1500bfa49f8ac3e9dc64c409396d79)) ([#3777](https://github.com/newrelic/node-newrelic/pull/3777)) ([12fe4c6](https://github.com/newrelic/node-newrelic/commit/12fe4c6f2a7a3f08efd874ba949150c7805a8888))
|
|
17
|
+
|
|
18
|
+
#### Miscellaneous chores
|
|
19
|
+
|
|
20
|
+
* Added version comment for agent-metadata.yml ([#3779](https://github.com/newrelic/node-newrelic/pull/3779)) ([1267293](https://github.com/newrelic/node-newrelic/commit/1267293cc36c79106b7cdd84dedf2c18b8a010d9))
|
|
21
|
+
* Refactored nestjs instrumentation to subscriber type ([#3792](https://github.com/newrelic/node-newrelic/pull/3792)) ([f7feb25](https://github.com/newrelic/node-newrelic/commit/f7feb25a5c7349433e7de26a0f6aebb820c034f4))
|
|
22
|
+
* Removed `@langchain/core` peer dep from langchain openai and aws tests ([#3788](https://github.com/newrelic/node-newrelic/pull/3788)) ([e670bb1](https://github.com/newrelic/node-newrelic/commit/e670bb1f47720c61509157cf45cd200234505733))
|
|
23
|
+
* Removed unneccessary `generic-pool` context propagation ([#3786](https://github.com/newrelic/node-newrelic/pull/3786)) ([bdd35fb](https://github.com/newrelic/node-newrelic/commit/bdd35fbf6b57d374de84f716488498a40ece41fd))
|
|
24
|
+
* Removed unnecessary `superagent` context propagation ([#3798](https://github.com/newrelic/node-newrelic/pull/3798)) ([81650e1](https://github.com/newrelic/node-newrelic/commit/81650e18d7da3897f9c82098def2f34c05c78d9e))
|
|
25
|
+
* Updated `@apm-js-collab/tracing-hooks` to `0.4.0` ([#3787](https://github.com/newrelic/node-newrelic/pull/3787)) ([d85fb2b](https://github.com/newrelic/node-newrelic/commit/d85fb2b832bc7202e5acafa19ff59094c6e386ee))
|
|
26
|
+
* Updated version format in agent-metadata.yml ([#3778](https://github.com/newrelic/node-newrelic/pull/3778)) ([61759e9](https://github.com/newrelic/node-newrelic/commit/61759e9c4e9ad2796a6462b967e30bad35b3fbf7))
|
|
27
|
+
|
|
28
|
+
#### Tests
|
|
29
|
+
|
|
30
|
+
* Updated langchain vectorstore tests to use a custom vectorstore to simplify the testing process ([#3793](https://github.com/newrelic/node-newrelic/pull/3793)) ([0fd9b54](https://github.com/newrelic/node-newrelic/commit/0fd9b54c0b4782162dae769453169ad4b05d7918))
|
|
31
|
+
* Updated version range for langgraph tests ([#3794](https://github.com/newrelic/node-newrelic/pull/3794)) ([e02ce99](https://github.com/newrelic/node-newrelic/commit/e02ce99083d584d8b61a223c67c4509f3fa9f4ce))
|
|
32
|
+
|
|
33
|
+
### v13.14.0 (2026-02-24)
|
|
34
|
+
|
|
35
|
+
#### Features
|
|
36
|
+
|
|
37
|
+
* Added ability to delay the start of the Profiler and run for n milliseconds before shutting down. ([#3758](https://github.com/newrelic/node-newrelic/pull/3758)) ([8503d25](https://github.com/newrelic/node-newrelic/commit/8503d252dce31fa5ba0cbb4f146511155de48f88))
|
|
38
|
+
* Added functionality to ingest logs from Azure Functions App automatically ([#3772](https://github.com/newrelic/node-newrelic/pull/3772)) ([0c70ba2](https://github.com/newrelic/node-newrelic/commit/0c70ba20d2c03af03605ebc12baadbfd00c8733d))
|
|
39
|
+
* Added support for error causes ([#3769](https://github.com/newrelic/node-newrelic/pull/3769)) ([7c5aae3](https://github.com/newrelic/node-newrelic/commit/7c5aae3ac8b14e781a0740ffc57c2b2defc4300b))
|
|
40
|
+
|
|
41
|
+
#### Bug fixes
|
|
42
|
+
|
|
43
|
+
* Updated `@google/genai` subscriber to handle the new `embedContentInternal` method in 1.42.0 ([#3771](https://github.com/newrelic/node-newrelic/pull/3771)) ([e96c974](https://github.com/newrelic/node-newrelic/commit/e96c974a1aa8c15caebd66004c939c43f61cc0e2))
|
|
44
|
+
|
|
45
|
+
#### Code refactoring
|
|
46
|
+
|
|
47
|
+
* AWS Bedrock llm events refactor ([#3759](https://github.com/newrelic/node-newrelic/pull/3759)) ([7ff953d](https://github.com/newrelic/node-newrelic/commit/7ff953dbda4529591438811b8b58cfada3767f80))
|
|
48
|
+
* Google Gen AI LLM event refactor ([#3748](https://github.com/newrelic/node-newrelic/pull/3748)) ([f1e3a0e](https://github.com/newrelic/node-newrelic/commit/f1e3a0e57ea26370ce5021010ab6fe793dd5c594))
|
|
49
|
+
* LangGraph LlmAgent event, remove old LlmEvent base ([#3761](https://github.com/newrelic/node-newrelic/pull/3761)) ([39d1d9a](https://github.com/newrelic/node-newrelic/commit/39d1d9a59ca467d71d4a7db4cf437d743a24939b))
|
|
50
|
+
* Updated the reparenting logic for compact mode of partial traces to assign parent id to entry span ([#3768](https://github.com/newrelic/node-newrelic/pull/3768)) ([5196318](https://github.com/newrelic/node-newrelic/commit/5196318713cbeba113936a902ff4f092c33109cb))
|
|
51
|
+
|
|
52
|
+
#### Documentation
|
|
53
|
+
|
|
54
|
+
* Updated compatibility report ([#3774](https://github.com/newrelic/node-newrelic/pull/3774)) ([5d04bba](https://github.com/newrelic/node-newrelic/commit/5d04bba57ddb23b2aa1861cf46e393adae2c43ca))
|
|
55
|
+
|
|
56
|
+
#### Miscellaneous chores
|
|
57
|
+
|
|
58
|
+
* Added API key to enable support for GH action ([#3760](https://github.com/newrelic/node-newrelic/pull/3760)) ([a521e80](https://github.com/newrelic/node-newrelic/commit/a521e8065c525312d1170bfa725610d708b011e3))
|
|
59
|
+
* Added call to agent metadata workflow - step 1 ([#3750](https://github.com/newrelic/node-newrelic/pull/3750)) ([90eeaec](https://github.com/newrelic/node-newrelic/commit/90eeaec0e4de28c779ccab7a8f4b03448e8448bd))
|
|
60
|
+
* Added span id to all debug/trace level logs in `span.applyPartialTraceRules` ([#3766](https://github.com/newrelic/node-newrelic/pull/3766)) ([8c57230](https://github.com/newrelic/node-newrelic/commit/8c57230f3d580ace1cb5eb1611dc78f85bbe36f1))
|
|
61
|
+
* Renamed file and fix cache output ([#3757](https://github.com/newrelic/node-newrelic/pull/3757)) ([1ac00ea](https://github.com/newrelic/node-newrelic/commit/1ac00ea4718fb6e95502961d777e11c8ae71dde9))
|
|
62
|
+
* Set up metadata action to run with releases ([#3762](https://github.com/newrelic/node-newrelic/pull/3762)) ([66efb13](https://github.com/newrelic/node-newrelic/commit/66efb13b9bde33a28fb4256cb70bf313e10774bc))
|
|
63
|
+
* Updated `@langchain/core` version for langchain-openai tests ([#3763](https://github.com/newrelic/node-newrelic/pull/3763)) ([c27213e](https://github.com/newrelic/node-newrelic/commit/c27213e6ca3048463158fcfecb7e1cfcf87d4922))
|
|
64
|
+
|
|
1
65
|
### v13.13.0 (2026-02-17)
|
|
2
66
|
|
|
3
67
|
## Feature Release
|
|
@@ -8366,5 +8430,7 @@ Special thanks to Ryan Copley (@RyanCopley) for the contribution.
|
|
|
8366
8430
|
|
|
8367
8431
|
|
|
8368
8432
|
|
|
8433
|
+
|
|
8434
|
+
|
|
8369
8435
|
|
|
8370
8436
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -94,7 +94,7 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic
|
|
|
94
94
|
|
|
95
95
|
### @apm-js-collab/tracing-hooks
|
|
96
96
|
|
|
97
|
-
This product includes source derived from [@apm-js-collab/tracing-hooks](https://github.com/apm-js-collab/tracing-hooks) ([v0.
|
|
97
|
+
This product includes source derived from [@apm-js-collab/tracing-hooks](https://github.com/apm-js-collab/tracing-hooks) ([v0.4.0](https://github.com/apm-js-collab/tracing-hooks/tree/v0.4.0)), distributed under the [Apache-2.0 License](https://github.com/apm-js-collab/tracing-hooks/blob/v0.4.0/LICENSE):
|
|
98
98
|
|
|
99
99
|
```
|
|
100
100
|
|
|
@@ -722,7 +722,7 @@ This product includes source derived from [@grpc/proto-loader](https://github.co
|
|
|
722
722
|
|
|
723
723
|
### @newrelic/security-agent
|
|
724
724
|
|
|
725
|
-
This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v3.0.
|
|
725
|
+
This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v3.0.2](https://github.com/newrelic/csec-node-agent/tree/v3.0.2)), distributed under the [UNKNOWN License](https://github.com/newrelic/csec-node-agent/blob/v3.0.2/LICENSE):
|
|
726
726
|
|
|
727
727
|
```
|
|
728
728
|
## New Relic Software License v1.0
|
|
@@ -1186,7 +1186,7 @@ This product includes source derived from [@opentelemetry/api](https://github.co
|
|
|
1186
1186
|
|
|
1187
1187
|
### @opentelemetry/core
|
|
1188
1188
|
|
|
1189
|
-
This product includes source derived from [@opentelemetry/core](https://github.com/open-telemetry/opentelemetry-js) ([v2.5.
|
|
1189
|
+
This product includes source derived from [@opentelemetry/core](https://github.com/open-telemetry/opentelemetry-js) ([v2.5.1](https://github.com/open-telemetry/opentelemetry-js/tree/v2.5.1)), distributed under the [Apache-2.0 License](https://github.com/open-telemetry/opentelemetry-js/blob/v2.5.1/LICENSE):
|
|
1190
1190
|
|
|
1191
1191
|
```
|
|
1192
1192
|
Apache License
|
|
@@ -1604,7 +1604,7 @@ This product includes source derived from [@opentelemetry/exporter-metrics-otlp-
|
|
|
1604
1604
|
|
|
1605
1605
|
### @opentelemetry/resources
|
|
1606
1606
|
|
|
1607
|
-
This product includes source derived from [@opentelemetry/resources](https://github.com/open-telemetry/opentelemetry-js) ([v2.5.
|
|
1607
|
+
This product includes source derived from [@opentelemetry/resources](https://github.com/open-telemetry/opentelemetry-js) ([v2.5.1](https://github.com/open-telemetry/opentelemetry-js/tree/v2.5.1)), distributed under the [Apache-2.0 License](https://github.com/open-telemetry/opentelemetry-js/blob/v2.5.1/LICENSE):
|
|
1608
1608
|
|
|
1609
1609
|
```
|
|
1610
1610
|
Apache License
|
|
@@ -2022,7 +2022,7 @@ This product includes source derived from [@opentelemetry/sdk-logs](https://gith
|
|
|
2022
2022
|
|
|
2023
2023
|
### @opentelemetry/sdk-metrics
|
|
2024
2024
|
|
|
2025
|
-
This product includes source derived from [@opentelemetry/sdk-metrics](https://github.com/open-telemetry/opentelemetry-js) ([v2.5.
|
|
2025
|
+
This product includes source derived from [@opentelemetry/sdk-metrics](https://github.com/open-telemetry/opentelemetry-js) ([v2.5.1](https://github.com/open-telemetry/opentelemetry-js/tree/v2.5.1)), distributed under the [Apache-2.0 License](https://github.com/open-telemetry/opentelemetry-js/blob/v2.5.1/LICENSE):
|
|
2026
2026
|
|
|
2027
2027
|
```
|
|
2028
2028
|
Apache License
|
|
@@ -2231,7 +2231,7 @@ This product includes source derived from [@opentelemetry/sdk-metrics](https://g
|
|
|
2231
2231
|
|
|
2232
2232
|
### @opentelemetry/sdk-trace-base
|
|
2233
2233
|
|
|
2234
|
-
This product includes source derived from [@opentelemetry/sdk-trace-base](https://github.com/open-telemetry/opentelemetry-js) ([v2.5.
|
|
2234
|
+
This product includes source derived from [@opentelemetry/sdk-trace-base](https://github.com/open-telemetry/opentelemetry-js) ([v2.5.1](https://github.com/open-telemetry/opentelemetry-js/tree/v2.5.1)), distributed under the [Apache-2.0 License](https://github.com/open-telemetry/opentelemetry-js/blob/v2.5.1/LICENSE):
|
|
2235
2235
|
|
|
2236
2236
|
```
|
|
2237
2237
|
Apache License
|
|
@@ -2904,7 +2904,7 @@ SOFTWARE.
|
|
|
2904
2904
|
|
|
2905
2905
|
### semver
|
|
2906
2906
|
|
|
2907
|
-
This product includes source derived from [semver](https://github.com/npm/node-semver) ([v7.7.
|
|
2907
|
+
This product includes source derived from [semver](https://github.com/npm/node-semver) ([v7.7.4](https://github.com/npm/node-semver/tree/v7.7.4)), distributed under the [ISC License](https://github.com/npm/node-semver/blob/v7.7.4/LICENSE):
|
|
2908
2908
|
|
|
2909
2909
|
```
|
|
2910
2910
|
The ISC License
|
|
@@ -2960,7 +2960,7 @@ SOFTWARE.
|
|
|
2960
2960
|
|
|
2961
2961
|
### @aws-sdk/client-s3
|
|
2962
2962
|
|
|
2963
|
-
This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.
|
|
2963
|
+
This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.996.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.996.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.996.0/LICENSE):
|
|
2964
2964
|
|
|
2965
2965
|
```
|
|
2966
2966
|
Apache License
|
|
@@ -3169,7 +3169,7 @@ This product includes source derived from [@aws-sdk/client-s3](https://github.co
|
|
|
3169
3169
|
|
|
3170
3170
|
### @aws-sdk/s3-request-presigner
|
|
3171
3171
|
|
|
3172
|
-
This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.
|
|
3172
|
+
This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.996.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.996.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.996.0/LICENSE):
|
|
3173
3173
|
|
|
3174
3174
|
```
|
|
3175
3175
|
Apache License
|
|
@@ -4510,7 +4510,7 @@ Apache License
|
|
|
4510
4510
|
|
|
4511
4511
|
### ajv
|
|
4512
4512
|
|
|
4513
|
-
This product includes source derived from [ajv](https://github.com/ajv-validator/ajv) ([v6.
|
|
4513
|
+
This product includes source derived from [ajv](https://github.com/ajv-validator/ajv) ([v6.14.0](https://github.com/ajv-validator/ajv/tree/v6.14.0)), distributed under the [MIT License](https://github.com/ajv-validator/ajv/blob/v6.14.0/LICENSE):
|
|
4514
4514
|
|
|
4515
4515
|
```
|
|
4516
4516
|
The MIT License (MIT)
|
|
@@ -5000,7 +5000,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
5000
5000
|
|
|
5001
5001
|
### eslint
|
|
5002
5002
|
|
|
5003
|
-
This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v9.39.
|
|
5003
|
+
This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v9.39.3](https://github.com/eslint/eslint/tree/v9.39.3)), distributed under the [MIT License](https://github.com/eslint/eslint/blob/v9.39.3/LICENSE):
|
|
5004
5004
|
|
|
5005
5005
|
```
|
|
5006
5006
|
Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
|
@@ -160,6 +160,8 @@ class Aggregator extends EventEmitter {
|
|
|
160
160
|
|
|
161
161
|
this.defaultPeriod = this.periodMs = opts.periodMs
|
|
162
162
|
this.defaultLimit = this.limit = opts.limit
|
|
163
|
+
this.delay = opts.delay ?? 0
|
|
164
|
+
this.duration = opts.duration ?? 0
|
|
163
165
|
this.runId = opts.runId
|
|
164
166
|
this.isAsync = opts.isAsync || false
|
|
165
167
|
// function to pass in to determine if we can start a given aggregator
|
|
@@ -43,8 +43,13 @@ class ProfilingAggregator extends BaseAggregator {
|
|
|
43
43
|
* and send the gzipped binary encoded data for each profiler
|
|
44
44
|
*/
|
|
45
45
|
start() {
|
|
46
|
-
logger.trace(`${this.method} aggregator started.`)
|
|
47
46
|
this.profilingManager.register()
|
|
47
|
+
const started = this.profilingManager.start()
|
|
48
|
+
if (!started) {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
logger.trace(`${this.method} aggregator started.`)
|
|
48
53
|
|
|
49
54
|
if (!this.sendTimer) {
|
|
50
55
|
this.sendTimer = setInterval(this.collectData.bind(this), this.periodMs)
|
package/lib/errors/index.js
CHANGED
|
@@ -18,6 +18,19 @@ const {
|
|
|
18
18
|
const synthetics = require('../synthetics')
|
|
19
19
|
const ERROR_EXPECTED_PATH = 'error.expected'
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Wraps `Error` instances for delivery to the back end. The wrapper includes
|
|
23
|
+
* the original error along with metadata, such as custom attributes, to be
|
|
24
|
+
* delivered.
|
|
25
|
+
*
|
|
26
|
+
* @class
|
|
27
|
+
* @param {object} options Configuration options for the exception
|
|
28
|
+
* @param {Error} options.error The error object to be wrapped
|
|
29
|
+
* @param {number} [options.timestamp=0] Unix timestamp (in milliseconds) when the error occurred
|
|
30
|
+
* @param {object} [options.customAttributes={}] Custom user-defined attributes associated with the error
|
|
31
|
+
* @param {object} [options.agentAttributes={}] Agent-generated attributes associated with the error
|
|
32
|
+
* @param {boolean} [options.expected] Whether this error is expected (not a true failure)
|
|
33
|
+
*/
|
|
21
34
|
class Exception {
|
|
22
35
|
constructor({ error, timestamp, customAttributes, agentAttributes, expected }) {
|
|
23
36
|
this.error = error
|
|
@@ -45,6 +58,36 @@ class Exception {
|
|
|
45
58
|
}
|
|
46
59
|
}
|
|
47
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Given the `.cause` value from an `Error` instance, serialize the chain
|
|
63
|
+
* into an object than can be attached to the agent attributes object.
|
|
64
|
+
*
|
|
65
|
+
* @param {Error|string} input The error cause to serialize.
|
|
66
|
+
* @returns {object[]} Serialized causes object array.
|
|
67
|
+
*/
|
|
68
|
+
function serializeCauses(input) {
|
|
69
|
+
if (!input) {
|
|
70
|
+
return []
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (typeof input === 'string') {
|
|
74
|
+
return [{ message: input }]
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
Object.hasOwn(input, 'message') === false ||
|
|
79
|
+
Object.hasOwn(input, 'stack') === false
|
|
80
|
+
) {
|
|
81
|
+
return [{ message: input.message ?? 'cause does not look like an Error instance' }]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return [{
|
|
85
|
+
message: input.message,
|
|
86
|
+
stack: input.stack,
|
|
87
|
+
cause: input.cause ? serializeCauses(input.cause) : []
|
|
88
|
+
}]
|
|
89
|
+
}
|
|
90
|
+
|
|
48
91
|
/**
|
|
49
92
|
* Given either or both of a transaction and an exception, generate an error
|
|
50
93
|
* trace in the JSON format expected by the collector. Since this will be
|
|
@@ -110,6 +153,21 @@ function createError(transaction, exception, config) {
|
|
|
110
153
|
|
|
111
154
|
maybeAddAgentAttributes(params, exception)
|
|
112
155
|
|
|
156
|
+
// We need to detect error causes and do something with them. We don't have
|
|
157
|
+
// a spec, or ui expectation, for them. So we are opting to embed them as
|
|
158
|
+
// agent attributes. This does not account for `AggregateError` instances.
|
|
159
|
+
if (Object.hasOwn(error ?? {}, 'cause') === true) {
|
|
160
|
+
// We have to stringify the data in order for it to show up correctly
|
|
161
|
+
// in the errors inbox's list of attributes. If we rely on our aggregator
|
|
162
|
+
// to stringify it, then the backend will decode it to an array of objects
|
|
163
|
+
// and the attribute will not be presented in the UI. By doubly encoding
|
|
164
|
+
// it, the back end will decode it to a JSON _string_ and show the
|
|
165
|
+
// attribute in the UI as desired.
|
|
166
|
+
params.agentAttributes['error.cause'] = JSON.stringify(
|
|
167
|
+
serializeCauses(error.cause)
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
113
171
|
return [0, name, message, type, params, transaction?.id]
|
|
114
172
|
}
|
|
115
173
|
|
|
@@ -118,31 +176,33 @@ function isValidErrorGroupOutput(output) {
|
|
|
118
176
|
}
|
|
119
177
|
|
|
120
178
|
function maybeAddAgentAttributes(attributes, exception) {
|
|
121
|
-
if (exception.errorGroupCallback) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
customAttributes: Object.assign({}, attributes.userAttributes),
|
|
125
|
-
'request.uri': attributes.agentAttributes['request.uri'],
|
|
126
|
-
'http.statusCode': attributes.agentAttributes['http.statusCode'],
|
|
127
|
-
'http.method': attributes.agentAttributes['request.method'],
|
|
128
|
-
'error.expected': attributes.intrinsics[ERROR_EXPECTED_PATH]
|
|
129
|
-
}
|
|
179
|
+
if (typeof exception.errorGroupCallback !== 'function') {
|
|
180
|
+
return
|
|
181
|
+
}
|
|
130
182
|
|
|
131
|
-
|
|
132
|
-
|
|
183
|
+
const callbackInput = {
|
|
184
|
+
error: exception.error,
|
|
185
|
+
customAttributes: Object.assign({}, attributes.userAttributes),
|
|
186
|
+
'request.uri': attributes.agentAttributes['request.uri'],
|
|
187
|
+
'http.statusCode': attributes.agentAttributes['http.statusCode'],
|
|
188
|
+
'http.method': attributes.agentAttributes['request.method'],
|
|
189
|
+
'error.expected': attributes.intrinsics[ERROR_EXPECTED_PATH]
|
|
190
|
+
}
|
|
133
191
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return
|
|
137
|
-
}
|
|
192
|
+
try {
|
|
193
|
+
const callbackOutput = exception.errorGroupCallback(callbackInput)
|
|
138
194
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
err,
|
|
143
|
-
'Function provided via setErrorGroupCallback failed, not generating `error.group.name`'
|
|
144
|
-
)
|
|
195
|
+
if (!isValidErrorGroupOutput(callbackOutput)) {
|
|
196
|
+
logger.warn('Function provided via setErrorGroupCallback return value malformed')
|
|
197
|
+
return
|
|
145
198
|
}
|
|
199
|
+
|
|
200
|
+
attributes.agentAttributes['error.group.name'] = callbackOutput
|
|
201
|
+
} catch (err) {
|
|
202
|
+
logger.warn(
|
|
203
|
+
err,
|
|
204
|
+
'Function provided via setErrorGroupCallback failed, not generating `error.group.name`'
|
|
205
|
+
)
|
|
146
206
|
}
|
|
147
207
|
}
|
|
148
208
|
|
package/lib/harvester.js
CHANGED
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
* Copyright 2024 New Relic Corporation. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
5
|
'use strict'
|
|
6
|
+
const defaultLogger = require('./logger').child({ component: 'harvester' })
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @class
|
|
10
10
|
* @classdesc Used to keep track of all registered aggregators.
|
|
11
11
|
*/
|
|
12
12
|
module.exports = class Harvester {
|
|
13
|
-
constructor() {
|
|
13
|
+
constructor({ logger = defaultLogger } = {}) {
|
|
14
14
|
this.aggregators = []
|
|
15
|
+
this.logger = logger
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -19,9 +20,23 @@ module.exports = class Harvester {
|
|
|
19
20
|
*/
|
|
20
21
|
start() {
|
|
21
22
|
for (const aggregator of this.aggregators) {
|
|
22
|
-
if (aggregator.enabled) {
|
|
23
|
+
if (aggregator.enabled && aggregator.delay > 0) {
|
|
24
|
+
this.logger.debug(`Delay start of ${aggregator.method} by ${aggregator.delay} milliseconds`)
|
|
25
|
+
const timeout = setTimeout(() => {
|
|
26
|
+
aggregator.start()
|
|
27
|
+
}, aggregator.delay)
|
|
28
|
+
timeout.unref()
|
|
29
|
+
} else if (aggregator.enabled) {
|
|
23
30
|
aggregator.start()
|
|
24
31
|
}
|
|
32
|
+
|
|
33
|
+
if (aggregator.enabled && aggregator.duration > 0) {
|
|
34
|
+
this.logger.debug(`Running ${aggregator.method} for ${aggregator.duration} milliseconds`)
|
|
35
|
+
const durationTimeout = setTimeout(() => {
|
|
36
|
+
aggregator.stop()
|
|
37
|
+
}, aggregator.delay + aggregator.duration)
|
|
38
|
+
durationTimeout.unref()
|
|
39
|
+
}
|
|
25
40
|
}
|
|
26
41
|
}
|
|
27
42
|
|
|
@@ -10,6 +10,12 @@ const { Transform } = require('node:stream')
|
|
|
10
10
|
|
|
11
11
|
const backgroundRecorder = require('../../metrics/recorders/other.js')
|
|
12
12
|
const recordWeb = require('../../metrics/recorders/http')
|
|
13
|
+
const {
|
|
14
|
+
isApplicationLoggingEnabled,
|
|
15
|
+
isLogForwardingEnabled,
|
|
16
|
+
isMetricsEnabled,
|
|
17
|
+
incrementLoggingLinesMetrics
|
|
18
|
+
} = require('../../util/application-logging.js')
|
|
13
19
|
|
|
14
20
|
const {
|
|
15
21
|
DESTINATIONS: DESTS,
|
|
@@ -25,9 +31,16 @@ const SUBSCRIPTION_ID = WEBSITE_OWNER_NAME?.split('+').shift()
|
|
|
25
31
|
const RESOURCE_GROUP_NAME = WEBSITE_RESOURCE_GROUP ?? WEBSITE_OWNER_NAME?.split('+').pop().split('-Linux').shift()
|
|
26
32
|
const AZURE_FUNCTION_APP_NAME = WEBSITE_SITE_NAME
|
|
27
33
|
|
|
34
|
+
// Azure Functions uses 'information' as the context level for context.log and context.info and uses 'warning' as the context level for context.warn.
|
|
35
|
+
// These map to the NR standard names that LOGGING.LEVELS recognizes ('info', 'warn').
|
|
36
|
+
const AZURE_TO_NR_LEVEL = {
|
|
37
|
+
information: 'info',
|
|
38
|
+
warning: 'warn'
|
|
39
|
+
}
|
|
40
|
+
|
|
28
41
|
let coldStart = true
|
|
29
42
|
|
|
30
|
-
module.exports = function initialize(
|
|
43
|
+
module.exports = function initialize(agent, azureFunctions, _moduleName, shim, { logger = defaultLogger } = {}) {
|
|
31
44
|
if (!SUBSCRIPTION_ID || !RESOURCE_GROUP_NAME || !AZURE_FUNCTION_APP_NAME) {
|
|
32
45
|
logger.warn(
|
|
33
46
|
{
|
|
@@ -59,6 +72,8 @@ module.exports = function initialize(_agent, azureFunctions, _moduleName, shim,
|
|
|
59
72
|
'webPubSub'
|
|
60
73
|
]
|
|
61
74
|
shim.wrap(azureFunctions.app, backgroundMethods, wrapAzureBackgroundMethods)
|
|
75
|
+
|
|
76
|
+
registerAzureLogs(agent, azureFunctions, logger)
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
function wrapAzureHttpMethods(shim, appMethod) {
|
|
@@ -174,6 +189,35 @@ function wrapAzureBackgroundMethods(shim, appMethod) {
|
|
|
174
189
|
}
|
|
175
190
|
}
|
|
176
191
|
|
|
192
|
+
function registerAzureLogs(agent, azureFunctions, logger) {
|
|
193
|
+
if (!isApplicationLoggingEnabled(agent.config)) {
|
|
194
|
+
logger.debug('Application logging not enabled. Not auto capturing logs from Azure Functions.')
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
azureFunctions.app.hook?.log((context) => {
|
|
199
|
+
const logLevel = AZURE_TO_NR_LEVEL[context.level] ?? context.level
|
|
200
|
+
|
|
201
|
+
if (isLogForwardingEnabled(agent.config, agent)) {
|
|
202
|
+
const meta = agent.getLinkingMetadata(true)
|
|
203
|
+
|
|
204
|
+
const logData = {
|
|
205
|
+
message: context.message,
|
|
206
|
+
level: logLevel,
|
|
207
|
+
timestamp: Date.now(),
|
|
208
|
+
category: context.category,
|
|
209
|
+
...meta
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
agent.logs.add(logData)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (isMetricsEnabled(agent.config)) {
|
|
216
|
+
incrementLoggingLinesMetrics(logLevel, agent.metrics)
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
|
|
177
221
|
/**
|
|
178
222
|
* Add required New Relic attributes to the transaction.
|
|
179
223
|
*
|
|
@@ -4,22 +4,22 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
|
+
const StreamHandler = require('./stream-handler')
|
|
8
|
+
const ConverseStreamHandler = require('./converse-stream-handler')
|
|
7
9
|
const {
|
|
8
10
|
LlmChatCompletionMessage,
|
|
9
11
|
LlmChatCompletionSummary,
|
|
10
12
|
LlmEmbedding,
|
|
11
|
-
LlmErrorMessage,
|
|
12
13
|
BedrockCommand,
|
|
13
|
-
BedrockResponse
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
BedrockResponse
|
|
15
|
+
} = require('#agentlib/llm-events/aws-bedrock/index.js')
|
|
16
|
+
const LlmErrorMessage = require('#agentlib/llm-events/error-message.js')
|
|
16
17
|
|
|
17
18
|
const { DESTINATIONS } = require('../../../config/attribute-filter')
|
|
18
19
|
const { AI } = require('../../../metrics/names')
|
|
19
20
|
const { RecorderSpec } = require('../../../shim/specs')
|
|
20
21
|
const InstrumentationDescriptor = require('../../../instrumentation-descriptor')
|
|
21
22
|
const { extractLlmContext } = require('../../../util/llm-utils')
|
|
22
|
-
const ConverseStreamHandler = require('../../../llm-events/aws-bedrock/converse-stream-handler')
|
|
23
23
|
|
|
24
24
|
let TRACKING_METRIC
|
|
25
25
|
|
|
@@ -73,7 +73,6 @@ function isStreamingEnabled({ commandName, config }) {
|
|
|
73
73
|
* @param {object} params.msg LLM event
|
|
74
74
|
*/
|
|
75
75
|
function recordEvent({ agent, type, msg }) {
|
|
76
|
-
msg.serialize()
|
|
77
76
|
const llmContext = extractLlmContext(agent)
|
|
78
77
|
const timestamp = msg?.timestamp ?? Date.now()
|
|
79
78
|
|
|
@@ -113,6 +112,7 @@ function addLlmMeta({ agent, segment, transaction }) {
|
|
|
113
112
|
* @param {BedrockResponse} params.bedrockResponse parsed response
|
|
114
113
|
* @param {Shim} params.shim shim instance
|
|
115
114
|
* @param {Transaction} params.transaction active transaction
|
|
115
|
+
* @param {number} [params.timeOfFirstToken] For streaming requests only, timestamp of when first token was sent.
|
|
116
116
|
*/
|
|
117
117
|
function recordChatCompletionMessages({
|
|
118
118
|
agent,
|
|
@@ -121,7 +121,8 @@ function recordChatCompletionMessages({
|
|
|
121
121
|
transaction,
|
|
122
122
|
bedrockCommand,
|
|
123
123
|
bedrockResponse,
|
|
124
|
-
err
|
|
124
|
+
err,
|
|
125
|
+
timeOfFirstToken
|
|
125
126
|
}) {
|
|
126
127
|
if (shouldSkipInstrumentation(agent.config) === true) {
|
|
127
128
|
shim.logger.debug('skipping sending of ai data')
|
|
@@ -134,7 +135,8 @@ function recordChatCompletionMessages({
|
|
|
134
135
|
bedrockCommand,
|
|
135
136
|
transaction,
|
|
136
137
|
segment,
|
|
137
|
-
|
|
138
|
+
timeOfFirstToken,
|
|
139
|
+
error: err !== null
|
|
138
140
|
})
|
|
139
141
|
|
|
140
142
|
// Record context message(s)
|
|
@@ -149,7 +151,7 @@ function recordChatCompletionMessages({
|
|
|
149
151
|
content: contextMessage.content,
|
|
150
152
|
role: contextMessage.role,
|
|
151
153
|
bedrockResponse,
|
|
152
|
-
|
|
154
|
+
sequence: i,
|
|
153
155
|
completionId: summary.id
|
|
154
156
|
})
|
|
155
157
|
recordEvent({ agent, type: 'LlmChatCompletionMessage', msg })
|
|
@@ -164,7 +166,7 @@ function recordChatCompletionMessages({
|
|
|
164
166
|
bedrockCommand,
|
|
165
167
|
bedrockResponse,
|
|
166
168
|
isResponse: true,
|
|
167
|
-
|
|
169
|
+
sequence: promptContextMessages.length + i,
|
|
168
170
|
content,
|
|
169
171
|
role: 'assistant',
|
|
170
172
|
completionId: summary.id
|
|
@@ -217,9 +219,9 @@ function recordEmbeddingMessage({
|
|
|
217
219
|
segment,
|
|
218
220
|
transaction,
|
|
219
221
|
bedrockCommand,
|
|
220
|
-
|
|
222
|
+
requestInput: prompt.content,
|
|
221
223
|
bedrockResponse,
|
|
222
|
-
|
|
224
|
+
error: err !== null
|
|
223
225
|
}))
|
|
224
226
|
|
|
225
227
|
for (const embedding of embeddings) {
|
|
@@ -342,6 +344,7 @@ function handleResponse({ shim, err, response, segment, transaction, bedrockComm
|
|
|
342
344
|
transaction,
|
|
343
345
|
bedrockCommand,
|
|
344
346
|
bedrockResponse,
|
|
347
|
+
timeOfFirstToken: this?.timeOfFirstToken,
|
|
345
348
|
err
|
|
346
349
|
})
|
|
347
350
|
} else if (modelType === 'embedding') {
|
package/lib/{llm-events/aws-bedrock → instrumentation/aws-sdk/v3}/converse-stream-handler.js
RENAMED
|
@@ -80,12 +80,19 @@ class ConverseStreamHandler {
|
|
|
80
80
|
*/
|
|
81
81
|
onComplete
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Timestamp of when first token was sent; needed for construction of the
|
|
85
|
+
* `LlmChatCompletionSummary` event.
|
|
86
|
+
*/
|
|
87
|
+
timeOfFirstToken
|
|
88
|
+
|
|
83
89
|
constructor({ stream, passThroughParams, onComplete }) {
|
|
84
90
|
this.passThroughParams = passThroughParams
|
|
85
91
|
this.stream = stream
|
|
86
92
|
this.onComplete = onComplete
|
|
87
93
|
this.segment = passThroughParams.segment
|
|
88
94
|
this.generator = handleConverse
|
|
95
|
+
this.timeOfFirstToken = null
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
/**
|
|
@@ -97,6 +104,7 @@ class ConverseStreamHandler {
|
|
|
97
104
|
*/
|
|
98
105
|
finish() {
|
|
99
106
|
this.passThroughParams.response = this.response
|
|
107
|
+
this.passThroughParams.timeOfFirstToken = this.timeOfFirstToken
|
|
100
108
|
this.onComplete(this.passThroughParams)
|
|
101
109
|
|
|
102
110
|
this.segment.touch()
|
|
@@ -136,6 +144,10 @@ async function * handleConverse() {
|
|
|
136
144
|
activeChunk = null
|
|
137
145
|
}
|
|
138
146
|
} else if (event.contentBlockDelta?.delta) {
|
|
147
|
+
// Delta represents a letter/word/token
|
|
148
|
+
if (!this.timeOfFirstToken) {
|
|
149
|
+
this.timeOfFirstToken = Date.now()
|
|
150
|
+
}
|
|
139
151
|
// There are also deltas for tool use (stringified inputs) but we don't currently record them so we just ignore for now
|
|
140
152
|
if (event.contentBlockDelta.delta.text) {
|
|
141
153
|
// It seems like the first streamed chunk does not always start with a contentBlockStart message
|
|
@@ -83,11 +83,18 @@ class StreamHandler {
|
|
|
83
83
|
*/
|
|
84
84
|
onComplete
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Timestamp of when first token was sent; needed for construction of the
|
|
88
|
+
* `LlmChatCompletionSummary` event.
|
|
89
|
+
*/
|
|
90
|
+
timeOfFirstToken
|
|
91
|
+
|
|
86
92
|
constructor({ stream, passThroughParams, onComplete }) {
|
|
87
93
|
this.passThroughParams = passThroughParams
|
|
88
94
|
this.stream = stream
|
|
89
95
|
this.onComplete = onComplete
|
|
90
96
|
this.segment = passThroughParams.segment
|
|
97
|
+
this.timeOfFirstToken = null
|
|
91
98
|
|
|
92
99
|
const { bedrockCommand } = passThroughParams
|
|
93
100
|
|
|
@@ -204,6 +211,7 @@ async function * handleClaude() {
|
|
|
204
211
|
|
|
205
212
|
try {
|
|
206
213
|
for await (const event of this.stream) {
|
|
214
|
+
if (!this.timeOfFirstToken) this.timeOfFirstToken = Date.now()
|
|
207
215
|
yield event
|
|
208
216
|
const parsed = this.parseEvent(event)
|
|
209
217
|
this.updateHeaders(parsed)
|
|
@@ -224,6 +232,7 @@ async function * handleClaude3() {
|
|
|
224
232
|
|
|
225
233
|
try {
|
|
226
234
|
for await (const event of this.stream) {
|
|
235
|
+
if (!this.timeOfFirstToken) this.timeOfFirstToken = Date.now()
|
|
227
236
|
yield event
|
|
228
237
|
const parsed = this.parseEvent(event)
|
|
229
238
|
this.updateHeaders(parsed)
|
|
@@ -247,6 +256,7 @@ async function * handleCohere() {
|
|
|
247
256
|
const generations = []
|
|
248
257
|
try {
|
|
249
258
|
for await (const event of this.stream) {
|
|
259
|
+
if (!this.timeOfFirstToken) this.timeOfFirstToken = Date.now()
|
|
250
260
|
yield event
|
|
251
261
|
const parsed = this.parseEvent(event)
|
|
252
262
|
this.updateHeaders(parsed)
|
|
@@ -265,6 +275,7 @@ async function * handleCohereEmbed() {
|
|
|
265
275
|
const embeddings = []
|
|
266
276
|
try {
|
|
267
277
|
for await (const event of this.stream) {
|
|
278
|
+
if (!this.timeOfFirstToken) this.timeOfFirstToken = Date.now()
|
|
268
279
|
yield event
|
|
269
280
|
const parsed = this.parseEvent(event)
|
|
270
281
|
this.updateHeaders(parsed)
|
|
@@ -284,6 +295,7 @@ async function * handleLlama() {
|
|
|
284
295
|
|
|
285
296
|
try {
|
|
286
297
|
for await (const event of this.stream) {
|
|
298
|
+
if (!this.timeOfFirstToken) this.timeOfFirstToken = Date.now()
|
|
287
299
|
yield event
|
|
288
300
|
const parsed = this.parseEvent(event)
|
|
289
301
|
this.updateHeaders(parsed)
|
|
@@ -308,6 +320,7 @@ async function * handleTitan() {
|
|
|
308
320
|
|
|
309
321
|
try {
|
|
310
322
|
for await (const event of this.stream) {
|
|
323
|
+
if (!this.timeOfFirstToken) this.timeOfFirstToken = Date.now()
|
|
311
324
|
yield event // Pass it up to the real consumer of the stream.
|
|
312
325
|
const parsed = this.parseEvent(event)
|
|
313
326
|
this.updateHeaders(parsed)
|