weflayr 0.23.0 → 0.24.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/dist/api/generated/facade.gen.d.ts +77 -0
- package/dist/api/generated/facade.gen.js +7 -1
- package/dist/api/generated/index.d.ts +2 -2
- package/dist/api/generated/index.js +7 -1
- package/dist/api/generated/sdk.gen.d.ts +25 -1
- package/dist/api/generated/sdk.gen.js +55 -1
- package/dist/api/generated/types.gen.d.ts +256 -0
- package/index.d.ts +5 -2
- package/package.json +1 -1
- package/src/api/generated/facade.gen.ts +36 -0
- package/src/api/generated/index.ts +2 -2
- package/src/api/generated/sdk.gen.ts +55 -1
- package/src/api/generated/types.gen.ts +293 -0
- package/src/auto-instrument.js +1 -0
- package/src/instrumentation/anthropic/get_cache_and_reasoning_telemetry.js +11 -0
- package/src/instrumentation/anthropic/get_cache_config_telemetry.js +90 -0
- package/src/instrumentation/anthropic/get_tool_definitions_telemetry.js +6 -1
- package/src/instrumentation/anthropic/set_telemetry_attributes.js +2 -0
- package/src/instrumentation/bedrock/get_cache_config_telemetry.js +106 -0
- package/src/instrumentation/bedrock/get_cache_telemetry.js +11 -6
- package/src/instrumentation/bedrock/set_telemetry_attributes.js +6 -2
- package/src/instrumentation/google/get_cache_operations_telemetry.js +171 -0
- package/src/instrumentation/google/get_cache_telemetry.js +16 -2
- package/src/instrumentation/google/set_telemetry_attributes.js +8 -2
- package/src/instrumentation/openai/get_cache_config_telemetry.js +63 -0
- package/src/instrumentation/openai/set_telemetry_attributes.js +2 -0
- package/src/instrumentation/vercel/full_instrumentation.js +10 -2
- package/src/instrumentation/vercel/get_cache_creation_telemetry.js +70 -0
- package/src/otel/propagation.js +22 -9
- package/src/otel/span-filter.js +12 -12
- package/src/otel/span-processor.js +8 -0
- package/src/otel/vercel-ai-sdk-span-filter.js +1 -1
- package/tests/index.test.js +67 -7
- package/tests/instrumentation/anthropic/get_cache_and_reasoning_telemetry.test.js +23 -0
- package/tests/instrumentation/anthropic/get_cache_config_telemetry.test.js +92 -0
- package/tests/instrumentation/anthropic/get_tool_definitions_telemetry.test.js +15 -0
- package/tests/instrumentation/bedrock/get_cache_config_telemetry.test.js +107 -0
- package/tests/instrumentation/bedrock/get_cache_telemetry.test.js +16 -0
- package/tests/instrumentation/google/get_cache_operations_telemetry.test.js +130 -0
- package/tests/instrumentation/openai/get_cache_config_telemetry.test.js +83 -0
- package/tests/instrumentation/vercel/get_cache_creation_telemetry.test.js +96 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { client } from './client.gen.js';
|
|
4
4
|
import type { Client, ClientMeta, Options as Options2, RequestResult, TDataShape } from './client/index.js';
|
|
5
|
-
import type { DeleteCustomersTagsData, DeleteCustomersTagsErrors, DeleteCustomersTagsResponses, DeleteKeyMetricsData, DeleteKeyMetricsErrors, DeleteKeyMetricsResponses, DeleteRevenueData, DeleteRevenueErrors, DeleteRevenueResponses, GetCustomersTagsData, GetCustomersTagsErrors, GetCustomersTagsResponses, GetKeyMetricsData, GetKeyMetricsErrors, GetKeyMetricsResponses, GetMarginData, GetMarginErrors, GetMarginResponses, GetRevenueData, GetRevenueErrors, GetRevenueResponses, SetCustomersTagsData, SetCustomersTagsErrors, SetCustomersTagsResponses, SetKeyMetricsData, SetKeyMetricsErrors, SetKeyMetricsResponses, SetRevenueData, SetRevenueErrors, SetRevenueResponses } from './types.gen.js';
|
|
5
|
+
import type { DeleteCustomersTagsData, DeleteCustomersTagsErrors, DeleteCustomersTagsResponses, DeleteKeyMetricsData, DeleteKeyMetricsErrors, DeleteKeyMetricsResponses, DeleteRevenueData, DeleteRevenueErrors, DeleteRevenueResponses, GetCustomersData, GetCustomersErrors, GetCustomersResponses, GetCustomersTagsData, GetCustomersTagsErrors, GetCustomersTagsResponses, GetFeaturesData, GetFeaturesErrors, GetFeaturesResponses, GetKeyMetricsData, GetKeyMetricsErrors, GetKeyMetricsResponses, GetMarginData, GetMarginErrors, GetMarginResponses, GetModelsData, GetModelsErrors, GetModelsResponses, GetProjectData, GetProjectErrors, GetProjectResponses, GetProvidersData, GetProvidersErrors, GetProvidersResponses, GetRevenueData, GetRevenueErrors, GetRevenueResponses, GetTagsData, GetTagsErrors, GetTagsResponses, SetCustomersTagsData, SetCustomersTagsErrors, SetCustomersTagsResponses, SetKeyMetricsData, SetKeyMetricsErrors, SetKeyMetricsResponses, SetRevenueData, SetRevenueErrors, SetRevenueResponses } from './types.gen.js';
|
|
6
6
|
|
|
7
7
|
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = Options2<TData, ThrowOnError, TResponse> & {
|
|
8
8
|
/**
|
|
@@ -119,3 +119,57 @@ export const setCustomersTags = <ThrowOnError extends boolean = false>(options:
|
|
|
119
119
|
...options.headers
|
|
120
120
|
}
|
|
121
121
|
});
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Static identity of the project: name, type, key metrics, environment and creation date.
|
|
125
|
+
*/
|
|
126
|
+
export const getProject = <ThrowOnError extends boolean = false>(options?: Options<GetProjectData, ThrowOnError>): RequestResult<GetProjectResponses, GetProjectErrors, ThrowOnError> => (options?.client ?? client).get<GetProjectResponses, GetProjectErrors, ThrowOnError>({
|
|
127
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
128
|
+
url: '/project/',
|
|
129
|
+
...options
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* {key: [values]} facets for run tags and customer tags; pass include_run_tags/include_customer_tags=false to skip either one.
|
|
134
|
+
*/
|
|
135
|
+
export const getTags = <ThrowOnError extends boolean = false>(options?: Options<GetTagsData, ThrowOnError>): RequestResult<GetTagsResponses, GetTagsErrors, ThrowOnError> => (options?.client ?? client).get<GetTagsResponses, GetTagsErrors, ThrowOnError>({
|
|
136
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
137
|
+
url: '/tags/',
|
|
138
|
+
...options
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Every distinct model name seen for the project.
|
|
143
|
+
*/
|
|
144
|
+
export const getModels = <ThrowOnError extends boolean = false>(options?: Options<GetModelsData, ThrowOnError>): RequestResult<GetModelsResponses, GetModelsErrors, ThrowOnError> => (options?.client ?? client).get<GetModelsResponses, GetModelsErrors, ThrowOnError>({
|
|
145
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
146
|
+
url: '/models/',
|
|
147
|
+
...options
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Every distinct provider name seen for the project.
|
|
152
|
+
*/
|
|
153
|
+
export const getProviders = <ThrowOnError extends boolean = false>(options?: Options<GetProvidersData, ThrowOnError>): RequestResult<GetProvidersResponses, GetProvidersErrors, ThrowOnError> => (options?.client ?? client).get<GetProvidersResponses, GetProvidersErrors, ThrowOnError>({
|
|
154
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
155
|
+
url: '/providers/',
|
|
156
|
+
...options
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Every known customer of the project; pass include_customer_tags=false to omit each customer's tags.
|
|
161
|
+
*/
|
|
162
|
+
export const getCustomers = <ThrowOnError extends boolean = false>(options?: Options<GetCustomersData, ThrowOnError>): RequestResult<GetCustomersResponses, GetCustomersErrors, ThrowOnError> => (options?.client ?? client).get<GetCustomersResponses, GetCustomersErrors, ThrowOnError>({
|
|
163
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
164
|
+
url: '/customers/',
|
|
165
|
+
...options
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Every distinct feature tag seen for the project.
|
|
170
|
+
*/
|
|
171
|
+
export const getFeatures = <ThrowOnError extends boolean = false>(options?: Options<GetFeaturesData, ThrowOnError>): RequestResult<GetFeaturesResponses, GetFeaturesErrors, ThrowOnError> => (options?.client ?? client).get<GetFeaturesResponses, GetFeaturesErrors, ThrowOnError>({
|
|
172
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
173
|
+
url: '/features/',
|
|
174
|
+
...options
|
|
175
|
+
});
|
|
@@ -68,6 +68,24 @@ export type CustomerMarginRow = {
|
|
|
68
68
|
profitability_status: 'healthy' | 'watch' | 'at_risk' | 'unprofitable' | 'unknown';
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* CustomerOutput
|
|
73
|
+
*
|
|
74
|
+
* One customer, with its tags when requested (an empty dict otherwise).
|
|
75
|
+
*/
|
|
76
|
+
export type CustomerOutput = {
|
|
77
|
+
/**
|
|
78
|
+
* Customer Name
|
|
79
|
+
*/
|
|
80
|
+
customer_name: string;
|
|
81
|
+
/**
|
|
82
|
+
* Customer Tags
|
|
83
|
+
*/
|
|
84
|
+
customer_tags: {
|
|
85
|
+
[key: string]: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
71
89
|
/**
|
|
72
90
|
* CustomerTags
|
|
73
91
|
*
|
|
@@ -104,6 +122,26 @@ export type CustomerTagsOutput = {
|
|
|
104
122
|
};
|
|
105
123
|
};
|
|
106
124
|
|
|
125
|
+
/**
|
|
126
|
+
* CustomersOutput
|
|
127
|
+
*
|
|
128
|
+
* The customers GET response: every known customer of the project.
|
|
129
|
+
*/
|
|
130
|
+
export type CustomersOutput = {
|
|
131
|
+
/**
|
|
132
|
+
* Customers
|
|
133
|
+
*/
|
|
134
|
+
customers: Array<CustomerOutput>;
|
|
135
|
+
/**
|
|
136
|
+
* Next Cursor
|
|
137
|
+
*/
|
|
138
|
+
next_cursor: string | null;
|
|
139
|
+
/**
|
|
140
|
+
* Has More
|
|
141
|
+
*/
|
|
142
|
+
has_more: boolean;
|
|
143
|
+
};
|
|
144
|
+
|
|
107
145
|
/**
|
|
108
146
|
* CustomersUpdatedOutput
|
|
109
147
|
*
|
|
@@ -120,6 +158,18 @@ export type CustomersUpdatedOutput = {
|
|
|
120
158
|
customers_updated: number;
|
|
121
159
|
};
|
|
122
160
|
|
|
161
|
+
/**
|
|
162
|
+
* FeaturesOutput
|
|
163
|
+
*
|
|
164
|
+
* A features GET response: every distinct feature tag seen for the project.
|
|
165
|
+
*/
|
|
166
|
+
export type FeaturesOutput = {
|
|
167
|
+
/**
|
|
168
|
+
* Features
|
|
169
|
+
*/
|
|
170
|
+
features: Array<string>;
|
|
171
|
+
};
|
|
172
|
+
|
|
123
173
|
/**
|
|
124
174
|
* InvalidFieldDetail
|
|
125
175
|
*
|
|
@@ -265,6 +315,58 @@ export type MarginListOutput = {
|
|
|
265
315
|
has_more: boolean;
|
|
266
316
|
};
|
|
267
317
|
|
|
318
|
+
/**
|
|
319
|
+
* ModelsOutput
|
|
320
|
+
*
|
|
321
|
+
* A models GET response: every distinct model name seen for the project.
|
|
322
|
+
*/
|
|
323
|
+
export type ModelsOutput = {
|
|
324
|
+
/**
|
|
325
|
+
* Models
|
|
326
|
+
*/
|
|
327
|
+
models: Array<string>;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* ProjectOutput
|
|
332
|
+
*
|
|
333
|
+
* A project GET response: static identity of the project.
|
|
334
|
+
*/
|
|
335
|
+
export type ProjectOutput = {
|
|
336
|
+
/**
|
|
337
|
+
* Name
|
|
338
|
+
*/
|
|
339
|
+
name: string;
|
|
340
|
+
/**
|
|
341
|
+
* Project Type
|
|
342
|
+
*/
|
|
343
|
+
project_type: 'revenue' | 'internal';
|
|
344
|
+
/**
|
|
345
|
+
* Key Metric Names
|
|
346
|
+
*/
|
|
347
|
+
key_metric_names: Array<string>;
|
|
348
|
+
/**
|
|
349
|
+
* Environment
|
|
350
|
+
*/
|
|
351
|
+
environment: 'dev' | 'pre-prod' | 'staging' | 'prod';
|
|
352
|
+
/**
|
|
353
|
+
* Created At
|
|
354
|
+
*/
|
|
355
|
+
created_at: string;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* ProvidersOutput
|
|
360
|
+
*
|
|
361
|
+
* A providers GET response: every distinct provider name seen for the project.
|
|
362
|
+
*/
|
|
363
|
+
export type ProvidersOutput = {
|
|
364
|
+
/**
|
|
365
|
+
* Providers
|
|
366
|
+
*/
|
|
367
|
+
providers: Array<string>;
|
|
368
|
+
};
|
|
369
|
+
|
|
268
370
|
/**
|
|
269
371
|
* RevenueOrKeyMetricDeletedRowOutput
|
|
270
372
|
*
|
|
@@ -460,6 +562,28 @@ export type TagsDeletedOutput = {
|
|
|
460
562
|
tags_deleted: number;
|
|
461
563
|
};
|
|
462
564
|
|
|
565
|
+
/**
|
|
566
|
+
* TagsOutput
|
|
567
|
+
*
|
|
568
|
+
* A tags GET response: facets of every tag dimension seen on the project.
|
|
569
|
+
*
|
|
570
|
+
* Either field is an empty dict when its include_* flag was false.
|
|
571
|
+
*/
|
|
572
|
+
export type TagsOutput = {
|
|
573
|
+
/**
|
|
574
|
+
* Run Tags
|
|
575
|
+
*/
|
|
576
|
+
run_tags: {
|
|
577
|
+
[key: string]: Array<string>;
|
|
578
|
+
};
|
|
579
|
+
/**
|
|
580
|
+
* Customer Tags
|
|
581
|
+
*/
|
|
582
|
+
customer_tags: {
|
|
583
|
+
[key: string]: Array<string>;
|
|
584
|
+
};
|
|
585
|
+
};
|
|
586
|
+
|
|
463
587
|
export type GetMarginData = {
|
|
464
588
|
body?: never;
|
|
465
589
|
path?: never;
|
|
@@ -820,3 +944,172 @@ export type SetCustomersTagsResponses = {
|
|
|
820
944
|
};
|
|
821
945
|
|
|
822
946
|
export type SetCustomersTagsResponse = SetCustomersTagsResponses[keyof SetCustomersTagsResponses];
|
|
947
|
+
|
|
948
|
+
export type GetProjectData = {
|
|
949
|
+
body?: never;
|
|
950
|
+
path?: never;
|
|
951
|
+
query?: never;
|
|
952
|
+
url: '/project/';
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
export type GetProjectErrors = {
|
|
956
|
+
/**
|
|
957
|
+
* Missing or invalid API key.
|
|
958
|
+
*/
|
|
959
|
+
401: ApiErrorOutput;
|
|
960
|
+
};
|
|
961
|
+
|
|
962
|
+
export type GetProjectError = GetProjectErrors[keyof GetProjectErrors];
|
|
963
|
+
|
|
964
|
+
export type GetProjectResponses = {
|
|
965
|
+
/**
|
|
966
|
+
* Success.
|
|
967
|
+
*/
|
|
968
|
+
200: ProjectOutput;
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
export type GetProjectResponse = GetProjectResponses[keyof GetProjectResponses];
|
|
972
|
+
|
|
973
|
+
export type GetTagsData = {
|
|
974
|
+
body?: never;
|
|
975
|
+
path?: never;
|
|
976
|
+
query?: {
|
|
977
|
+
/**
|
|
978
|
+
* Include run-tag facets. Defaults to true.
|
|
979
|
+
*/
|
|
980
|
+
include_run_tags?: boolean;
|
|
981
|
+
/**
|
|
982
|
+
* Include customer-tag facets. Defaults to true.
|
|
983
|
+
*/
|
|
984
|
+
include_customer_tags?: boolean;
|
|
985
|
+
};
|
|
986
|
+
url: '/tags/';
|
|
987
|
+
};
|
|
988
|
+
|
|
989
|
+
export type GetTagsErrors = {
|
|
990
|
+
/**
|
|
991
|
+
* Missing or invalid API key.
|
|
992
|
+
*/
|
|
993
|
+
401: ApiErrorOutput;
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
export type GetTagsError = GetTagsErrors[keyof GetTagsErrors];
|
|
997
|
+
|
|
998
|
+
export type GetTagsResponses = {
|
|
999
|
+
/**
|
|
1000
|
+
* Success.
|
|
1001
|
+
*/
|
|
1002
|
+
200: TagsOutput;
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
export type GetTagsResponse = GetTagsResponses[keyof GetTagsResponses];
|
|
1006
|
+
|
|
1007
|
+
export type GetModelsData = {
|
|
1008
|
+
body?: never;
|
|
1009
|
+
path?: never;
|
|
1010
|
+
query?: never;
|
|
1011
|
+
url: '/models/';
|
|
1012
|
+
};
|
|
1013
|
+
|
|
1014
|
+
export type GetModelsErrors = {
|
|
1015
|
+
/**
|
|
1016
|
+
* Missing or invalid API key.
|
|
1017
|
+
*/
|
|
1018
|
+
401: ApiErrorOutput;
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
export type GetModelsError = GetModelsErrors[keyof GetModelsErrors];
|
|
1022
|
+
|
|
1023
|
+
export type GetModelsResponses = {
|
|
1024
|
+
/**
|
|
1025
|
+
* Success.
|
|
1026
|
+
*/
|
|
1027
|
+
200: ModelsOutput;
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
export type GetModelsResponse = GetModelsResponses[keyof GetModelsResponses];
|
|
1031
|
+
|
|
1032
|
+
export type GetProvidersData = {
|
|
1033
|
+
body?: never;
|
|
1034
|
+
path?: never;
|
|
1035
|
+
query?: never;
|
|
1036
|
+
url: '/providers/';
|
|
1037
|
+
};
|
|
1038
|
+
|
|
1039
|
+
export type GetProvidersErrors = {
|
|
1040
|
+
/**
|
|
1041
|
+
* Missing or invalid API key.
|
|
1042
|
+
*/
|
|
1043
|
+
401: ApiErrorOutput;
|
|
1044
|
+
};
|
|
1045
|
+
|
|
1046
|
+
export type GetProvidersError = GetProvidersErrors[keyof GetProvidersErrors];
|
|
1047
|
+
|
|
1048
|
+
export type GetProvidersResponses = {
|
|
1049
|
+
/**
|
|
1050
|
+
* Success.
|
|
1051
|
+
*/
|
|
1052
|
+
200: ProvidersOutput;
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
export type GetProvidersResponse = GetProvidersResponses[keyof GetProvidersResponses];
|
|
1056
|
+
|
|
1057
|
+
export type GetCustomersData = {
|
|
1058
|
+
body?: never;
|
|
1059
|
+
path?: never;
|
|
1060
|
+
query?: {
|
|
1061
|
+
/**
|
|
1062
|
+
* Opaque cursor from a previous page's next_cursor.
|
|
1063
|
+
*/
|
|
1064
|
+
cursor?: string;
|
|
1065
|
+
limit?: number;
|
|
1066
|
+
/**
|
|
1067
|
+
* Include each customer's tags. Defaults to true.
|
|
1068
|
+
*/
|
|
1069
|
+
include_customer_tags?: boolean;
|
|
1070
|
+
};
|
|
1071
|
+
url: '/customers/';
|
|
1072
|
+
};
|
|
1073
|
+
|
|
1074
|
+
export type GetCustomersErrors = {
|
|
1075
|
+
/**
|
|
1076
|
+
* Missing or invalid API key.
|
|
1077
|
+
*/
|
|
1078
|
+
401: ApiErrorOutput;
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
export type GetCustomersError = GetCustomersErrors[keyof GetCustomersErrors];
|
|
1082
|
+
|
|
1083
|
+
export type GetCustomersResponses = {
|
|
1084
|
+
/**
|
|
1085
|
+
* Success.
|
|
1086
|
+
*/
|
|
1087
|
+
200: CustomersOutput;
|
|
1088
|
+
};
|
|
1089
|
+
|
|
1090
|
+
export type GetCustomersResponse = GetCustomersResponses[keyof GetCustomersResponses];
|
|
1091
|
+
|
|
1092
|
+
export type GetFeaturesData = {
|
|
1093
|
+
body?: never;
|
|
1094
|
+
path?: never;
|
|
1095
|
+
query?: never;
|
|
1096
|
+
url: '/features/';
|
|
1097
|
+
};
|
|
1098
|
+
|
|
1099
|
+
export type GetFeaturesErrors = {
|
|
1100
|
+
/**
|
|
1101
|
+
* Missing or invalid API key.
|
|
1102
|
+
*/
|
|
1103
|
+
401: ApiErrorOutput;
|
|
1104
|
+
};
|
|
1105
|
+
|
|
1106
|
+
export type GetFeaturesError = GetFeaturesErrors[keyof GetFeaturesErrors];
|
|
1107
|
+
|
|
1108
|
+
export type GetFeaturesResponses = {
|
|
1109
|
+
/**
|
|
1110
|
+
* Success.
|
|
1111
|
+
*/
|
|
1112
|
+
200: FeaturesOutput;
|
|
1113
|
+
};
|
|
1114
|
+
|
|
1115
|
+
export type GetFeaturesResponse = GetFeaturesResponses[keyof GetFeaturesResponses];
|
package/src/auto-instrument.js
CHANGED
|
@@ -18,9 +18,19 @@
|
|
|
18
18
|
|
|
19
19
|
const CACHE_READ_INPUT_TOKENS_ATTR = 'gen_ai.usage.cache_read_input_tokens';
|
|
20
20
|
const CACHE_CREATION_INPUT_TOKENS_ATTR = 'gen_ai.usage.cache_creation_input_tokens';
|
|
21
|
+
const CACHE_CREATION_ATTR = 'weflayr.cache.creation';
|
|
21
22
|
const INPUT_TOKENS_ATTR = 'gen_ai.usage.input_tokens';
|
|
22
23
|
const THINKING_TOKENS_ATTR = 'gen_ai.usage.output_tokens_details.thinking_tokens';
|
|
23
24
|
|
|
25
|
+
// Stamp `usage.cache_creation` verbatim (the written tokens per TTL, billed at
|
|
26
|
+
// different rates); skipped when nothing was written so non-caching calls
|
|
27
|
+
// carry no attribute. The normalizer owns the mapping to TTL tiers.
|
|
28
|
+
function _setCacheCreation(span, cacheCreation) {
|
|
29
|
+
if (!cacheCreation) return;
|
|
30
|
+
if (!Object.values(cacheCreation).some(Boolean)) return;
|
|
31
|
+
span.setAttribute(CACHE_CREATION_ATTR, JSON.stringify(cacheCreation));
|
|
32
|
+
}
|
|
33
|
+
|
|
24
34
|
// Stamp cache counts (and the raw uncached input) from an Anthropic usage object.
|
|
25
35
|
// The instrumentor emits no `gen_ai.usage.cache_*` attribute; `input_tokens` in
|
|
26
36
|
// the stream events is the raw uncached count (cached tokens are reported
|
|
@@ -35,6 +45,7 @@ function _setUsage(span, usage) {
|
|
|
35
45
|
if (usage.cache_creation_input_tokens) {
|
|
36
46
|
span.setAttribute(CACHE_CREATION_INPUT_TOKENS_ATTR, usage.cache_creation_input_tokens);
|
|
37
47
|
}
|
|
48
|
+
_setCacheCreation(span, usage.cache_creation);
|
|
38
49
|
if (typeof usage.input_tokens === 'number') {
|
|
39
50
|
span.setAttribute(INPUT_TOKENS_ATTR, usage.input_tokens);
|
|
40
51
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Request-side prompt-caching config capture for Anthropic spans.
|
|
5
|
+
*
|
|
6
|
+
* Anthropic callers opt into caching by placing `cache_control` breakpoints on
|
|
7
|
+
* content blocks (`system` text blocks, message content blocks, tool
|
|
8
|
+
* definitions), each with an optional `ttl` ("5m" default, or "1h"). The
|
|
9
|
+
* traceloop instrumentor never records them, so cache-hit analysis cannot tell
|
|
10
|
+
* what the request asked to cache or for how long.
|
|
11
|
+
*
|
|
12
|
+
* Wrap `startSpan({ type, params })` (covering the streamed and non-streamed
|
|
13
|
+
* paths) to stamp every breakpoint found in the request as
|
|
14
|
+
* `weflayr.cache.breakpoints`: a JSON list of `{location, ttl}` where location
|
|
15
|
+
* is `system`, `messages[i]` or `tools[i]` and `ttl` is the raw cache_control
|
|
16
|
+
* string, omitted when the breakpoint sets none; the normalizer owns the TTL
|
|
17
|
+
* vocabulary.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const BREAKPOINTS_ATTR = 'weflayr.cache.breakpoints';
|
|
21
|
+
|
|
22
|
+
// A breakpoint as location + the raw cache_control `ttl` string, omitted when
|
|
23
|
+
// the request sets none.
|
|
24
|
+
function _breakpointEntry(location, cacheControl) {
|
|
25
|
+
const ttl = cacheControl && cacheControl.ttl;
|
|
26
|
+
return ttl ? { location, ttl: String(ttl) } : { location };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function _cacheControlsInBlocks(blocks) {
|
|
30
|
+
if (!Array.isArray(blocks)) return [];
|
|
31
|
+
return blocks.map((block) => block && block.cache_control).filter(Boolean);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Every `cache_control` breakpoint in the request, as location + the raw
|
|
35
|
+
// `ttl` string (omitted when the breakpoint sets none).
|
|
36
|
+
function extractCacheBreakpoints(params) {
|
|
37
|
+
const breakpoints = [];
|
|
38
|
+
for (const cacheControl of _cacheControlsInBlocks(params.system)) {
|
|
39
|
+
breakpoints.push(_breakpointEntry('system', cacheControl));
|
|
40
|
+
}
|
|
41
|
+
(params.messages || []).forEach((message, index) => {
|
|
42
|
+
for (const cacheControl of _cacheControlsInBlocks(message && message.content)) {
|
|
43
|
+
breakpoints.push(_breakpointEntry(`messages[${index}]`, cacheControl));
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
(params.tools || []).forEach((tool, index) => {
|
|
47
|
+
if (tool && tool.cache_control) {
|
|
48
|
+
breakpoints.push(_breakpointEntry(`tools[${index}]`, tool.cache_control));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return breakpoints;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
class AnthropicCacheConfigInstrumentor {
|
|
55
|
+
constructor() {
|
|
56
|
+
// [instrumentation, methodName, originalFunction] for uninstrument().
|
|
57
|
+
this._patched = [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// No-op (and never throws) if the instrumentor's internals have changed shape —
|
|
61
|
+
// the worst case is missing cache-config capture, never a crash.
|
|
62
|
+
instrument(instrumentation) {
|
|
63
|
+
if (!instrumentation) return;
|
|
64
|
+
const startSpanOriginal = instrumentation.startSpan;
|
|
65
|
+
if (typeof startSpanOriginal !== 'function') return;
|
|
66
|
+
|
|
67
|
+
instrumentation.startSpan = function startSpanWithCacheConfig(request) {
|
|
68
|
+
const span = startSpanOriginal.call(this, request);
|
|
69
|
+
try {
|
|
70
|
+
const breakpoints = extractCacheBreakpoints((request && request.params) || {});
|
|
71
|
+
if (breakpoints.length) {
|
|
72
|
+
span.setAttribute(BREAKPOINTS_ATTR, JSON.stringify(breakpoints));
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
// Never break span creation over an enrichment failure.
|
|
76
|
+
}
|
|
77
|
+
return span;
|
|
78
|
+
};
|
|
79
|
+
this._patched.push([instrumentation, 'startSpan', startSpanOriginal]);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
uninstrument() {
|
|
83
|
+
for (const [owner, methodName, original] of this._patched) {
|
|
84
|
+
owner[methodName] = original;
|
|
85
|
+
}
|
|
86
|
+
this._patched = [];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
module.exports = { AnthropicCacheConfigInstrumentor, extractCacheBreakpoints };
|
|
@@ -29,7 +29,12 @@ class AnthropicToolDefinitionsInstrumentor {
|
|
|
29
29
|
try {
|
|
30
30
|
const tools = request && request.params && request.params.tools;
|
|
31
31
|
if (Array.isArray(tools) && tools.length) {
|
|
32
|
-
|
|
32
|
+
// cache_control is dropped from the stamped definitions — the
|
|
33
|
+
// breakpoint is captured separately in cache_config.
|
|
34
|
+
const definitions = tools.map(
|
|
35
|
+
({ cache_control: _cacheControl, ...definition }) => definition
|
|
36
|
+
);
|
|
37
|
+
span.setAttribute('gen_ai.tool.definitions', JSON.stringify(definitions));
|
|
33
38
|
}
|
|
34
39
|
} catch {
|
|
35
40
|
// Never break span creation over an enrichment failure.
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* leaving an empty finish_reason on the output message).
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
const { AnthropicCacheConfigInstrumentor } = require('./get_cache_config_telemetry');
|
|
13
14
|
const { AnthropicPromptCachingInstrumentor } = require('./get_cache_and_reasoning_telemetry');
|
|
14
15
|
const {
|
|
15
16
|
AnthropicStreamingStopReasonInstrumentor,
|
|
@@ -20,6 +21,7 @@ class AnthropicTelemetryInstrumentor {
|
|
|
20
21
|
constructor() {
|
|
21
22
|
this._subInstrumentors = [
|
|
22
23
|
new AnthropicPromptCachingInstrumentor(),
|
|
24
|
+
new AnthropicCacheConfigInstrumentor(),
|
|
23
25
|
new AnthropicStreamingStopReasonInstrumentor(),
|
|
24
26
|
new AnthropicToolDefinitionsInstrumentor(),
|
|
25
27
|
];
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Request-side prompt-caching config capture for Bedrock invoke_model spans.
|
|
5
|
+
*
|
|
6
|
+
* Bedrock callers opt into caching in the request body, in the model vendor's
|
|
7
|
+
* own schema: Anthropic-on-Bedrock bodies carry `cache_control` blocks (the
|
|
8
|
+
* native Anthropic shape), Amazon Nova bodies carry `cachePoint` blocks (the
|
|
9
|
+
* Converse shape) — on system entries, message content blocks or tool
|
|
10
|
+
* definitions, each with an optional raw `ttl` string ("5m"/"1h"). The
|
|
11
|
+
* traceloop instrumentor never records them.
|
|
12
|
+
*
|
|
13
|
+
* Wrap the instrumentor's `_startSpan({ params })` (params.body is the raw
|
|
14
|
+
* request JSON) to stamp every breakpoint found as `weflayr.cache.breakpoints`.
|
|
15
|
+
* Bedrock responses report no TTL split of the written tokens; the worker
|
|
16
|
+
* derives it from these breakpoints when they all share one TTL.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const { extractCacheBreakpoints } = require('../anthropic/get_cache_config_telemetry');
|
|
20
|
+
|
|
21
|
+
const BREAKPOINTS_ATTR = 'weflayr.cache.breakpoints';
|
|
22
|
+
|
|
23
|
+
// A breakpoint as location + the raw `cachePoint` `ttl` string, omitted when
|
|
24
|
+
// the request sets none.
|
|
25
|
+
function _cachePointEntry(location, cachePoint) {
|
|
26
|
+
const ttl = cachePoint && cachePoint.ttl;
|
|
27
|
+
return ttl ? { location, ttl: String(ttl) } : { location };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// The first `cachePoint` among a list of blocks (attached to a content block,
|
|
31
|
+
// or standing alone as its own block), or undefined.
|
|
32
|
+
function _cachePointOfBlocks(blocks) {
|
|
33
|
+
if (!Array.isArray(blocks)) return undefined;
|
|
34
|
+
const block = blocks.find((entry) => entry && entry.cachePoint != null);
|
|
35
|
+
return block && block.cachePoint;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Every cache breakpoint in an InvokeModel request body, as location + the
|
|
39
|
+
// raw `ttl` string (omitted when the breakpoint sets none): the
|
|
40
|
+
// Anthropic-on-Bedrock `cache_control` shape and the Nova `cachePoint` shape
|
|
41
|
+
// (which never overlap in one body).
|
|
42
|
+
function extractBedrockCacheBreakpoints(body) {
|
|
43
|
+
const breakpoints = extractCacheBreakpoints(body);
|
|
44
|
+
const systemCachePoint = _cachePointOfBlocks(body.system);
|
|
45
|
+
if (systemCachePoint != null) {
|
|
46
|
+
breakpoints.push(_cachePointEntry('system', systemCachePoint));
|
|
47
|
+
}
|
|
48
|
+
(body.messages || []).forEach((message, index) => {
|
|
49
|
+
const cachePoint = _cachePointOfBlocks(message && message.content);
|
|
50
|
+
if (cachePoint != null) {
|
|
51
|
+
breakpoints.push(_cachePointEntry(`messages[${index}]`, cachePoint));
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const tools = (body.toolConfig && body.toolConfig.tools) || [];
|
|
55
|
+
tools.forEach((tool, index) => {
|
|
56
|
+
if (tool && tool.cachePoint != null) {
|
|
57
|
+
breakpoints.push(_cachePointEntry(`tools[${index}]`, tool.cachePoint));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return breakpoints;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class BedrockCacheConfigInstrumentor {
|
|
64
|
+
constructor() {
|
|
65
|
+
// [instrumentation, methodName, originalFunction] for uninstrument().
|
|
66
|
+
this._patched = [];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// No-op (and never throws) if the instrumentor's internals have changed shape —
|
|
70
|
+
// the worst case is missing cache-config capture, never a crash.
|
|
71
|
+
instrument(instrumentation) {
|
|
72
|
+
if (!instrumentation) return;
|
|
73
|
+
const startSpanOriginal = instrumentation._startSpan;
|
|
74
|
+
if (typeof startSpanOriginal !== 'function') return;
|
|
75
|
+
|
|
76
|
+
instrumentation._startSpan = function startSpanWithCacheConfig(request) {
|
|
77
|
+
const span = startSpanOriginal.call(this, request);
|
|
78
|
+
try {
|
|
79
|
+
const rawBody =
|
|
80
|
+
request && request.params && request.params.input && request.params.input.body;
|
|
81
|
+
if (typeof rawBody === 'string' || rawBody instanceof Uint8Array) {
|
|
82
|
+
const body = JSON.parse(
|
|
83
|
+
typeof rawBody === 'string' ? rawBody : new TextDecoder().decode(rawBody)
|
|
84
|
+
);
|
|
85
|
+
const breakpoints = extractBedrockCacheBreakpoints(body || {});
|
|
86
|
+
if (breakpoints.length) {
|
|
87
|
+
span.setAttribute(BREAKPOINTS_ATTR, JSON.stringify(breakpoints));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
// Never break span creation over an enrichment failure.
|
|
92
|
+
}
|
|
93
|
+
return span;
|
|
94
|
+
};
|
|
95
|
+
this._patched.push([instrumentation, '_startSpan', startSpanOriginal]);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
uninstrument() {
|
|
99
|
+
for (const [owner, methodName, original] of this._patched) {
|
|
100
|
+
owner[methodName] = original;
|
|
101
|
+
}
|
|
102
|
+
this._patched = [];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { BedrockCacheConfigInstrumentor, extractBedrockCacheBreakpoints };
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* off the InvokeModel response body but never reads its cache-token counts, so
|
|
8
8
|
* spans for prompt-cache hits carry no cached-token figures. Amazon Nova's native
|
|
9
9
|
* InvokeModel response includes `usage.cacheReadInputTokenCount` /
|
|
10
|
-
* `usage.cacheWriteInputTokenCount
|
|
10
|
+
* `usage.cacheWriteInputTokenCount` (Anthropic-on-Bedrock responses carry the
|
|
11
|
+
* native `usage.cache_read_input_tokens` / `cache_creation_input_tokens`);
|
|
12
|
+
* this maps them to the
|
|
11
13
|
* `gen_ai.usage.cache_read_input_tokens` / `cache_creation_input_tokens`
|
|
12
14
|
* attributes the worker reads, matching the Python SDK.
|
|
13
15
|
*
|
|
@@ -19,14 +21,17 @@
|
|
|
19
21
|
const CACHE_READ_INPUT_TOKENS_ATTR = 'gen_ai.usage.cache_read_input_tokens';
|
|
20
22
|
const CACHE_CREATION_INPUT_TOKENS_ATTR = 'gen_ai.usage.cache_creation_input_tokens';
|
|
21
23
|
|
|
22
|
-
// Stamp cache counts from a
|
|
24
|
+
// Stamp cache counts from a `usage` object onto the span: Nova's camelCase
|
|
25
|
+
// count fields, or Anthropic-on-Bedrock's native snake_case ones.
|
|
23
26
|
function _setCacheFromUsage(span, usage) {
|
|
24
27
|
if (!usage || !span || !span.isRecording || !span.isRecording()) return;
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
const read = usage.cacheReadInputTokenCount ?? usage.cache_read_input_tokens;
|
|
29
|
+
const write = usage.cacheWriteInputTokenCount ?? usage.cache_creation_input_tokens;
|
|
30
|
+
if (typeof read === 'number' && read) {
|
|
31
|
+
span.setAttribute(CACHE_READ_INPUT_TOKENS_ATTR, read);
|
|
27
32
|
}
|
|
28
|
-
if (typeof
|
|
29
|
-
span.setAttribute(CACHE_CREATION_INPUT_TOKENS_ATTR,
|
|
33
|
+
if (typeof write === 'number' && write) {
|
|
34
|
+
span.setAttribute(CACHE_CREATION_INPUT_TOKENS_ATTR, write);
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
37
|
|