@frengki0707/google-cloud-clone 1.33.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 +203 -0
- package/README.md +83 -0
- package/lib/auth.d.mts +33 -0
- package/lib/auth.d.ts +33 -0
- package/lib/auth.js +70 -0
- package/lib/auth.js.map +1 -0
- package/lib/auth.mjs +45 -0
- package/lib/auth.mjs.map +1 -0
- package/lib/gcpLogger.d.mts +25 -0
- package/lib/gcpLogger.d.ts +25 -0
- package/lib/gcpLogger.js +118 -0
- package/lib/gcpLogger.js.map +1 -0
- package/lib/gcpLogger.mjs +82 -0
- package/lib/gcpLogger.mjs.map +1 -0
- package/lib/gcpOpenTelemetry.d.mts +59 -0
- package/lib/gcpOpenTelemetry.d.ts +59 -0
- package/lib/gcpOpenTelemetry.js +374 -0
- package/lib/gcpOpenTelemetry.js.map +1 -0
- package/lib/gcpOpenTelemetry.mjs +364 -0
- package/lib/gcpOpenTelemetry.mjs.map +1 -0
- package/lib/index.d.mts +36 -0
- package/lib/index.d.ts +36 -0
- package/lib/index.js +56 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +29 -0
- package/lib/index.mjs.map +1 -0
- package/lib/metrics.d.mts +65 -0
- package/lib/metrics.d.ts +65 -0
- package/lib/metrics.js +91 -0
- package/lib/metrics.js.map +1 -0
- package/lib/metrics.mjs +65 -0
- package/lib/metrics.mjs.map +1 -0
- package/lib/model-armor.d.mts +59 -0
- package/lib/model-armor.d.ts +59 -0
- package/lib/model-armor.js +205 -0
- package/lib/model-armor.js.map +1 -0
- package/lib/model-armor.mjs +181 -0
- package/lib/model-armor.mjs.map +1 -0
- package/lib/telemetry/action.d.mts +27 -0
- package/lib/telemetry/action.d.ts +27 -0
- package/lib/telemetry/action.js +92 -0
- package/lib/telemetry/action.js.map +1 -0
- package/lib/telemetry/action.mjs +73 -0
- package/lib/telemetry/action.mjs.map +1 -0
- package/lib/telemetry/defaults.d.mts +30 -0
- package/lib/telemetry/defaults.d.ts +30 -0
- package/lib/telemetry/defaults.js +70 -0
- package/lib/telemetry/defaults.js.map +1 -0
- package/lib/telemetry/defaults.mjs +46 -0
- package/lib/telemetry/defaults.mjs.map +1 -0
- package/lib/telemetry/engagement.d.mts +35 -0
- package/lib/telemetry/engagement.d.ts +35 -0
- package/lib/telemetry/engagement.js +106 -0
- package/lib/telemetry/engagement.js.map +1 -0
- package/lib/telemetry/engagement.mjs +85 -0
- package/lib/telemetry/engagement.mjs.map +1 -0
- package/lib/telemetry/feature.d.mts +35 -0
- package/lib/telemetry/feature.d.ts +35 -0
- package/lib/telemetry/feature.js +142 -0
- package/lib/telemetry/feature.js.map +1 -0
- package/lib/telemetry/feature.mjs +127 -0
- package/lib/telemetry/feature.mjs.map +1 -0
- package/lib/telemetry/generate.d.mts +53 -0
- package/lib/telemetry/generate.d.ts +53 -0
- package/lib/telemetry/generate.js +326 -0
- package/lib/telemetry/generate.js.map +1 -0
- package/lib/telemetry/generate.mjs +314 -0
- package/lib/telemetry/generate.mjs.map +1 -0
- package/lib/telemetry/path.d.mts +32 -0
- package/lib/telemetry/path.d.ts +32 -0
- package/lib/telemetry/path.js +91 -0
- package/lib/telemetry/path.js.map +1 -0
- package/lib/telemetry/path.mjs +78 -0
- package/lib/telemetry/path.mjs.map +1 -0
- package/lib/types.d.mts +121 -0
- package/lib/types.d.ts +121 -0
- package/lib/types.js +17 -0
- package/lib/types.js.map +1 -0
- package/lib/types.mjs +1 -0
- package/lib/types.mjs.map +1 -0
- package/lib/utils.d.mts +57 -0
- package/lib/utils.d.ts +57 -0
- package/lib/utils.js +143 -0
- package/lib/utils.js.map +1 -0
- package/lib/utils.mjs +104 -0
- package/lib/utils.mjs.map +1 -0
- package/package.json +89 -0
- package/src/auth.ts +89 -0
- package/src/gcpLogger.ts +124 -0
- package/src/gcpOpenTelemetry.ts +485 -0
- package/src/index.ts +59 -0
- package/src/metrics.ts +122 -0
- package/src/model-armor.ts +317 -0
- package/src/telemetry/action.ts +106 -0
- package/src/telemetry/defaults.ts +72 -0
- package/src/telemetry/engagement.ts +120 -0
- package/src/telemetry/feature.ts +170 -0
- package/src/telemetry/generate.ts +454 -0
- package/src/telemetry/path.ts +111 -0
- package/src/types.ts +133 -0
- package/src/utils.ts +175 -0
- package/tests/logs_no_input_output_test.ts +267 -0
- package/tests/logs_session_test.ts +219 -0
- package/tests/logs_test.ts +633 -0
- package/tests/metrics_test.ts +792 -0
- package/tests/model_armor_test.ts +336 -0
- package/tests/traces_test.ts +380 -0
- package/typedoc.json +3 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gcpLogger.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggingWinston } from '@google-cloud/logging-winston';\nimport { getCurrentEnv } from 'genkit';\nimport { logger } from 'genkit/logging';\nimport type { Writable } from 'stream';\nimport type { GcpTelemetryConfig } from './types.js';\nimport { loggingDenied, loggingDeniedHelpText } from './utils.js';\n\n/**\n * Additional streams for writing log data to. Useful for unit testing.\n */\nlet additionalStream: Writable;\nlet useJsonFormatOverride = false;\n\n/**\n * Provides a logger for exporting Genkit debug logs to GCP Cloud\n * logs.\n */\nexport class GcpLogger {\n constructor(private readonly config: GcpTelemetryConfig) {}\n\n async getLogger(env: string) {\n // Dynamically importing winston here more strictly controls\n // the import order relative to registering instrumentation\n // with OpenTelemetry. Incorrect import order will trigger\n // an internal OT warning and will result in logs not being\n // associated with correct spans/traces.\n const winston = await import('winston');\n\n const format =\n useJsonFormatOverride || this.shouldExport(env)\n ? { format: winston.format.json() }\n : {\n format: winston.format.printf((info): string => {\n return `[${info.level}] ${info.message}`;\n }),\n };\n\n const transports: any[] = [];\n transports.push(\n this.shouldExport(env)\n ? new LoggingWinston({\n labels: { module: 'genkit' },\n prefix: 'genkit',\n logName: 'genkit_log',\n projectId: this.config.projectId,\n credentials: this.config.credentials,\n autoRetry: true,\n defaultCallback: await this.getErrorHandler(),\n })\n : new winston.transports.Console()\n );\n if (additionalStream) {\n transports.push(\n new winston.transports.Stream({ stream: additionalStream })\n );\n }\n return winston.createLogger({\n transports: transports,\n ...format,\n exceptionHandlers: [new winston.transports.Console()],\n });\n }\n\n private async getErrorHandler(): Promise<(err: Error | null) => void> {\n // only log the first time\n let instructionsLogged = false;\n const helpInstructions = await loggingDeniedHelpText();\n\n return async (err: Error | null) => {\n // Use the defaultLogger so that logs don't get swallowed by\n // the open telemetry exporter\n const defaultLogger = logger.defaultLogger;\n if (err && loggingDenied(err)) {\n if (!instructionsLogged) {\n instructionsLogged = true;\n defaultLogger.error(\n `Unable to send logs to Google Cloud: ${err.message}\\n\\n${helpInstructions}\\n`\n );\n }\n } else if (err) {\n defaultLogger.error(`Unable to send logs to Google Cloud: ${err}`);\n }\n\n if (err) {\n // Assume the logger is compromised, and we need a new one\n // Reinitialize the genkit logger with a new instance with the same config\n logger.init(\n await new GcpLogger(this.config).getLogger(getCurrentEnv())\n );\n defaultLogger.info('Initialized a new GcpLogger.');\n }\n };\n }\n\n private shouldExport(env?: string) {\n return this.config.export;\n }\n}\n\n/** @hidden */\nexport function __addTransportStreamForTesting(stream: Writable) {\n additionalStream = stream;\n}\n\n/** @hidden */\nexport function __useJsonFormatForTesting() {\n useJsonFormatOverride = true;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,6BAA+B;AAC/B,oBAA8B;AAC9B,qBAAuB;AAGvB,mBAAqD;AAKrD,IAAI;AACJ,IAAI,wBAAwB;AAMrB,MAAM,UAAU;AAAA,EACrB,YAA6B,QAA4B;AAA5B;AAAA,EAA6B;AAAA,EAE1D,MAAM,UAAU,KAAa;AAM3B,UAAM,UAAU,MAAM,OAAO,SAAS;AAEtC,UAAM,SACJ,yBAAyB,KAAK,aAAa,GAAG,IAC1C,EAAE,QAAQ,QAAQ,OAAO,KAAK,EAAE,IAChC;AAAA,MACE,QAAQ,QAAQ,OAAO,OAAO,CAAC,SAAiB;AAC9C,eAAO,IAAI,KAAK,KAAK,KAAK,KAAK,OAAO;AAAA,MACxC,CAAC;AAAA,IACH;AAEN,UAAM,aAAoB,CAAC;AAC3B,eAAW;AAAA,MACT,KAAK,aAAa,GAAG,IACjB,IAAI,sCAAe;AAAA,QACjB,QAAQ,EAAE,QAAQ,SAAS;AAAA,QAC3B,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,WAAW,KAAK,OAAO;AAAA,QACvB,aAAa,KAAK,OAAO;AAAA,QACzB,WAAW;AAAA,QACX,iBAAiB,MAAM,KAAK,gBAAgB;AAAA,MAC9C,CAAC,IACD,IAAI,QAAQ,WAAW,QAAQ;AAAA,IACrC;AACA,QAAI,kBAAkB;AACpB,iBAAW;AAAA,QACT,IAAI,QAAQ,WAAW,OAAO,EAAE,QAAQ,iBAAiB,CAAC;AAAA,MAC5D;AAAA,IACF;AACA,WAAO,QAAQ,aAAa;AAAA,MAC1B;AAAA,MACA,GAAG;AAAA,MACH,mBAAmB,CAAC,IAAI,QAAQ,WAAW,QAAQ,CAAC;AAAA,IACtD,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,kBAAwD;AAEpE,QAAI,qBAAqB;AACzB,UAAM,mBAAmB,UAAM,oCAAsB;AAErD,WAAO,OAAO,QAAsB;AAGlC,YAAM,gBAAgB,sBAAO;AAC7B,UAAI,WAAO,4BAAc,GAAG,GAAG;AAC7B,YAAI,CAAC,oBAAoB;AACvB,+BAAqB;AACrB,wBAAc;AAAA,YACZ,wCAAwC,IAAI,OAAO;AAAA;AAAA,EAAO,gBAAgB;AAAA;AAAA,UAC5E;AAAA,QACF;AAAA,MACF,WAAW,KAAK;AACd,sBAAc,MAAM,wCAAwC,GAAG,EAAE;AAAA,MACnE;AAEA,UAAI,KAAK;AAGP,8BAAO;AAAA,UACL,MAAM,IAAI,UAAU,KAAK,MAAM,EAAE,cAAU,6BAAc,CAAC;AAAA,QAC5D;AACA,sBAAc,KAAK,8BAA8B;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,aAAa,KAAc;AACjC,WAAO,KAAK,OAAO;AAAA,EACrB;AACF;AAGO,SAAS,+BAA+B,QAAkB;AAC/D,qBAAmB;AACrB;AAGO,SAAS,4BAA4B;AAC1C,0BAAwB;AAC1B;","names":[]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { LoggingWinston } from "@google-cloud/logging-winston";
|
|
2
|
+
import { getCurrentEnv } from "genkit";
|
|
3
|
+
import { logger } from "genkit/logging";
|
|
4
|
+
import { loggingDenied, loggingDeniedHelpText } from "./utils.js";
|
|
5
|
+
let additionalStream;
|
|
6
|
+
let useJsonFormatOverride = false;
|
|
7
|
+
class GcpLogger {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
}
|
|
11
|
+
async getLogger(env) {
|
|
12
|
+
const winston = await import("winston");
|
|
13
|
+
const format = useJsonFormatOverride || this.shouldExport(env) ? { format: winston.format.json() } : {
|
|
14
|
+
format: winston.format.printf((info) => {
|
|
15
|
+
return `[${info.level}] ${info.message}`;
|
|
16
|
+
})
|
|
17
|
+
};
|
|
18
|
+
const transports = [];
|
|
19
|
+
transports.push(
|
|
20
|
+
this.shouldExport(env) ? new LoggingWinston({
|
|
21
|
+
labels: { module: "genkit" },
|
|
22
|
+
prefix: "genkit",
|
|
23
|
+
logName: "genkit_log",
|
|
24
|
+
projectId: this.config.projectId,
|
|
25
|
+
credentials: this.config.credentials,
|
|
26
|
+
autoRetry: true,
|
|
27
|
+
defaultCallback: await this.getErrorHandler()
|
|
28
|
+
}) : new winston.transports.Console()
|
|
29
|
+
);
|
|
30
|
+
if (additionalStream) {
|
|
31
|
+
transports.push(
|
|
32
|
+
new winston.transports.Stream({ stream: additionalStream })
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return winston.createLogger({
|
|
36
|
+
transports,
|
|
37
|
+
...format,
|
|
38
|
+
exceptionHandlers: [new winston.transports.Console()]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async getErrorHandler() {
|
|
42
|
+
let instructionsLogged = false;
|
|
43
|
+
const helpInstructions = await loggingDeniedHelpText();
|
|
44
|
+
return async (err) => {
|
|
45
|
+
const defaultLogger = logger.defaultLogger;
|
|
46
|
+
if (err && loggingDenied(err)) {
|
|
47
|
+
if (!instructionsLogged) {
|
|
48
|
+
instructionsLogged = true;
|
|
49
|
+
defaultLogger.error(
|
|
50
|
+
`Unable to send logs to Google Cloud: ${err.message}
|
|
51
|
+
|
|
52
|
+
${helpInstructions}
|
|
53
|
+
`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
} else if (err) {
|
|
57
|
+
defaultLogger.error(`Unable to send logs to Google Cloud: ${err}`);
|
|
58
|
+
}
|
|
59
|
+
if (err) {
|
|
60
|
+
logger.init(
|
|
61
|
+
await new GcpLogger(this.config).getLogger(getCurrentEnv())
|
|
62
|
+
);
|
|
63
|
+
defaultLogger.info("Initialized a new GcpLogger.");
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
shouldExport(env) {
|
|
68
|
+
return this.config.export;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function __addTransportStreamForTesting(stream) {
|
|
72
|
+
additionalStream = stream;
|
|
73
|
+
}
|
|
74
|
+
function __useJsonFormatForTesting() {
|
|
75
|
+
useJsonFormatOverride = true;
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
GcpLogger,
|
|
79
|
+
__addTransportStreamForTesting,
|
|
80
|
+
__useJsonFormatForTesting
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=gcpLogger.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gcpLogger.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggingWinston } from '@google-cloud/logging-winston';\nimport { getCurrentEnv } from 'genkit';\nimport { logger } from 'genkit/logging';\nimport type { Writable } from 'stream';\nimport type { GcpTelemetryConfig } from './types.js';\nimport { loggingDenied, loggingDeniedHelpText } from './utils.js';\n\n/**\n * Additional streams for writing log data to. Useful for unit testing.\n */\nlet additionalStream: Writable;\nlet useJsonFormatOverride = false;\n\n/**\n * Provides a logger for exporting Genkit debug logs to GCP Cloud\n * logs.\n */\nexport class GcpLogger {\n constructor(private readonly config: GcpTelemetryConfig) {}\n\n async getLogger(env: string) {\n // Dynamically importing winston here more strictly controls\n // the import order relative to registering instrumentation\n // with OpenTelemetry. Incorrect import order will trigger\n // an internal OT warning and will result in logs not being\n // associated with correct spans/traces.\n const winston = await import('winston');\n\n const format =\n useJsonFormatOverride || this.shouldExport(env)\n ? { format: winston.format.json() }\n : {\n format: winston.format.printf((info): string => {\n return `[${info.level}] ${info.message}`;\n }),\n };\n\n const transports: any[] = [];\n transports.push(\n this.shouldExport(env)\n ? new LoggingWinston({\n labels: { module: 'genkit' },\n prefix: 'genkit',\n logName: 'genkit_log',\n projectId: this.config.projectId,\n credentials: this.config.credentials,\n autoRetry: true,\n defaultCallback: await this.getErrorHandler(),\n })\n : new winston.transports.Console()\n );\n if (additionalStream) {\n transports.push(\n new winston.transports.Stream({ stream: additionalStream })\n );\n }\n return winston.createLogger({\n transports: transports,\n ...format,\n exceptionHandlers: [new winston.transports.Console()],\n });\n }\n\n private async getErrorHandler(): Promise<(err: Error | null) => void> {\n // only log the first time\n let instructionsLogged = false;\n const helpInstructions = await loggingDeniedHelpText();\n\n return async (err: Error | null) => {\n // Use the defaultLogger so that logs don't get swallowed by\n // the open telemetry exporter\n const defaultLogger = logger.defaultLogger;\n if (err && loggingDenied(err)) {\n if (!instructionsLogged) {\n instructionsLogged = true;\n defaultLogger.error(\n `Unable to send logs to Google Cloud: ${err.message}\\n\\n${helpInstructions}\\n`\n );\n }\n } else if (err) {\n defaultLogger.error(`Unable to send logs to Google Cloud: ${err}`);\n }\n\n if (err) {\n // Assume the logger is compromised, and we need a new one\n // Reinitialize the genkit logger with a new instance with the same config\n logger.init(\n await new GcpLogger(this.config).getLogger(getCurrentEnv())\n );\n defaultLogger.info('Initialized a new GcpLogger.');\n }\n };\n }\n\n private shouldExport(env?: string) {\n return this.config.export;\n }\n}\n\n/** @hidden */\nexport function __addTransportStreamForTesting(stream: Writable) {\n additionalStream = stream;\n}\n\n/** @hidden */\nexport function __useJsonFormatForTesting() {\n useJsonFormatOverride = true;\n}\n"],"mappings":"AAgBA,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,cAAc;AAGvB,SAAS,eAAe,6BAA6B;AAKrD,IAAI;AACJ,IAAI,wBAAwB;AAMrB,MAAM,UAAU;AAAA,EACrB,YAA6B,QAA4B;AAA5B;AAAA,EAA6B;AAAA,EAE1D,MAAM,UAAU,KAAa;AAM3B,UAAM,UAAU,MAAM,OAAO,SAAS;AAEtC,UAAM,SACJ,yBAAyB,KAAK,aAAa,GAAG,IAC1C,EAAE,QAAQ,QAAQ,OAAO,KAAK,EAAE,IAChC;AAAA,MACE,QAAQ,QAAQ,OAAO,OAAO,CAAC,SAAiB;AAC9C,eAAO,IAAI,KAAK,KAAK,KAAK,KAAK,OAAO;AAAA,MACxC,CAAC;AAAA,IACH;AAEN,UAAM,aAAoB,CAAC;AAC3B,eAAW;AAAA,MACT,KAAK,aAAa,GAAG,IACjB,IAAI,eAAe;AAAA,QACjB,QAAQ,EAAE,QAAQ,SAAS;AAAA,QAC3B,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,WAAW,KAAK,OAAO;AAAA,QACvB,aAAa,KAAK,OAAO;AAAA,QACzB,WAAW;AAAA,QACX,iBAAiB,MAAM,KAAK,gBAAgB;AAAA,MAC9C,CAAC,IACD,IAAI,QAAQ,WAAW,QAAQ;AAAA,IACrC;AACA,QAAI,kBAAkB;AACpB,iBAAW;AAAA,QACT,IAAI,QAAQ,WAAW,OAAO,EAAE,QAAQ,iBAAiB,CAAC;AAAA,MAC5D;AAAA,IACF;AACA,WAAO,QAAQ,aAAa;AAAA,MAC1B;AAAA,MACA,GAAG;AAAA,MACH,mBAAmB,CAAC,IAAI,QAAQ,WAAW,QAAQ,CAAC;AAAA,IACtD,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,kBAAwD;AAEpE,QAAI,qBAAqB;AACzB,UAAM,mBAAmB,MAAM,sBAAsB;AAErD,WAAO,OAAO,QAAsB;AAGlC,YAAM,gBAAgB,OAAO;AAC7B,UAAI,OAAO,cAAc,GAAG,GAAG;AAC7B,YAAI,CAAC,oBAAoB;AACvB,+BAAqB;AACrB,wBAAc;AAAA,YACZ,wCAAwC,IAAI,OAAO;AAAA;AAAA,EAAO,gBAAgB;AAAA;AAAA,UAC5E;AAAA,QACF;AAAA,MACF,WAAW,KAAK;AACd,sBAAc,MAAM,wCAAwC,GAAG,EAAE;AAAA,MACnE;AAEA,UAAI,KAAK;AAGP,eAAO;AAAA,UACL,MAAM,IAAI,UAAU,KAAK,MAAM,EAAE,UAAU,cAAc,CAAC;AAAA,QAC5D;AACA,sBAAc,KAAK,8BAA8B;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,aAAa,KAAc;AACjC,WAAO,KAAK,OAAO;AAAA,EACrB;AACF;AAGO,SAAS,+BAA+B,QAAkB;AAC/D,qBAAmB;AACrB;AAGO,SAAS,4BAA4B;AAC1C,0BAAwB;AAC1B;","names":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { InMemoryMetricExporter } from '@opentelemetry/sdk-metrics';
|
|
2
|
+
import { NodeSDKConfiguration } from '@opentelemetry/sdk-node';
|
|
3
|
+
import { InMemorySpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
|
+
import { GcpTelemetryConfig } from './types.mjs';
|
|
5
|
+
import '@opentelemetry/auto-instrumentations-node';
|
|
6
|
+
import '@opentelemetry/instrumentation';
|
|
7
|
+
import 'google-auth-library';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Copyright 2024 Google LLC
|
|
11
|
+
*
|
|
12
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
+
* you may not use this file except in compliance with the License.
|
|
14
|
+
* You may obtain a copy of the License at
|
|
15
|
+
*
|
|
16
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
*
|
|
18
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
+
* See the License for the specific language governing permissions and
|
|
22
|
+
* limitations under the License.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Provides a {TelemetryConfig} for exporting OpenTelemetry data (Traces,
|
|
27
|
+
* Metrics, and Logs) to the Google Cloud Operations Suite.
|
|
28
|
+
*/
|
|
29
|
+
declare class GcpOpenTelemetry {
|
|
30
|
+
private readonly config;
|
|
31
|
+
private readonly resource;
|
|
32
|
+
constructor(config: GcpTelemetryConfig);
|
|
33
|
+
/**
|
|
34
|
+
* Log hook for writing trace and span metadata to log messages in the format
|
|
35
|
+
* required by GCP.
|
|
36
|
+
*/
|
|
37
|
+
private gcpTraceLogHook;
|
|
38
|
+
getConfig(): Promise<Partial<NodeSDKConfiguration>>;
|
|
39
|
+
private createSpanExporter;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a {MetricReader} for pushing metrics out to GCP via OpenTelemetry.
|
|
42
|
+
*/
|
|
43
|
+
private createMetricReader;
|
|
44
|
+
/** Gets all open telemetry instrumentations as configured by the plugin. */
|
|
45
|
+
private getInstrumentations;
|
|
46
|
+
private shouldExportTraces;
|
|
47
|
+
private shouldExportMetrics;
|
|
48
|
+
/** Always configure the Pino and Winston instrumentations */
|
|
49
|
+
private getDefaultLoggingInstrumentations;
|
|
50
|
+
private buildMetricExporter;
|
|
51
|
+
}
|
|
52
|
+
/** @hidden */
|
|
53
|
+
declare function __getMetricExporterForTesting(): InMemoryMetricExporter;
|
|
54
|
+
/** @hidden */
|
|
55
|
+
declare function __getSpanExporterForTesting(): InMemorySpanExporter;
|
|
56
|
+
/** @hidden */
|
|
57
|
+
declare function __forceFlushSpansForTesting(): void;
|
|
58
|
+
|
|
59
|
+
export { GcpOpenTelemetry, __forceFlushSpansForTesting, __getMetricExporterForTesting, __getSpanExporterForTesting };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { InMemoryMetricExporter } from '@opentelemetry/sdk-metrics';
|
|
2
|
+
import { NodeSDKConfiguration } from '@opentelemetry/sdk-node';
|
|
3
|
+
import { InMemorySpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
|
+
import { GcpTelemetryConfig } from './types.js';
|
|
5
|
+
import '@opentelemetry/auto-instrumentations-node';
|
|
6
|
+
import '@opentelemetry/instrumentation';
|
|
7
|
+
import 'google-auth-library';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Copyright 2024 Google LLC
|
|
11
|
+
*
|
|
12
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
+
* you may not use this file except in compliance with the License.
|
|
14
|
+
* You may obtain a copy of the License at
|
|
15
|
+
*
|
|
16
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
*
|
|
18
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
+
* See the License for the specific language governing permissions and
|
|
22
|
+
* limitations under the License.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Provides a {TelemetryConfig} for exporting OpenTelemetry data (Traces,
|
|
27
|
+
* Metrics, and Logs) to the Google Cloud Operations Suite.
|
|
28
|
+
*/
|
|
29
|
+
declare class GcpOpenTelemetry {
|
|
30
|
+
private readonly config;
|
|
31
|
+
private readonly resource;
|
|
32
|
+
constructor(config: GcpTelemetryConfig);
|
|
33
|
+
/**
|
|
34
|
+
* Log hook for writing trace and span metadata to log messages in the format
|
|
35
|
+
* required by GCP.
|
|
36
|
+
*/
|
|
37
|
+
private gcpTraceLogHook;
|
|
38
|
+
getConfig(): Promise<Partial<NodeSDKConfiguration>>;
|
|
39
|
+
private createSpanExporter;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a {MetricReader} for pushing metrics out to GCP via OpenTelemetry.
|
|
42
|
+
*/
|
|
43
|
+
private createMetricReader;
|
|
44
|
+
/** Gets all open telemetry instrumentations as configured by the plugin. */
|
|
45
|
+
private getInstrumentations;
|
|
46
|
+
private shouldExportTraces;
|
|
47
|
+
private shouldExportMetrics;
|
|
48
|
+
/** Always configure the Pino and Winston instrumentations */
|
|
49
|
+
private getDefaultLoggingInstrumentations;
|
|
50
|
+
private buildMetricExporter;
|
|
51
|
+
}
|
|
52
|
+
/** @hidden */
|
|
53
|
+
declare function __getMetricExporterForTesting(): InMemoryMetricExporter;
|
|
54
|
+
/** @hidden */
|
|
55
|
+
declare function __getSpanExporterForTesting(): InMemorySpanExporter;
|
|
56
|
+
/** @hidden */
|
|
57
|
+
declare function __forceFlushSpansForTesting(): void;
|
|
58
|
+
|
|
59
|
+
export { GcpOpenTelemetry, __forceFlushSpansForTesting, __getMetricExporterForTesting, __getSpanExporterForTesting };
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var gcpOpenTelemetry_exports = {};
|
|
20
|
+
__export(gcpOpenTelemetry_exports, {
|
|
21
|
+
GcpOpenTelemetry: () => GcpOpenTelemetry,
|
|
22
|
+
__forceFlushSpansForTesting: () => __forceFlushSpansForTesting,
|
|
23
|
+
__getMetricExporterForTesting: () => __getMetricExporterForTesting,
|
|
24
|
+
__getSpanExporterForTesting: () => __getSpanExporterForTesting
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(gcpOpenTelemetry_exports);
|
|
27
|
+
var import_opentelemetry_cloud_monitoring_exporter = require("@google-cloud/opentelemetry-cloud-monitoring-exporter");
|
|
28
|
+
var import_opentelemetry_cloud_trace_exporter = require("@google-cloud/opentelemetry-cloud-trace-exporter");
|
|
29
|
+
var import_opentelemetry_resource_util = require("@google-cloud/opentelemetry-resource-util");
|
|
30
|
+
var import_api = require("@opentelemetry/api");
|
|
31
|
+
var import_auto_instrumentations_node = require("@opentelemetry/auto-instrumentations-node");
|
|
32
|
+
var import_instrumentation_pino = require("@opentelemetry/instrumentation-pino");
|
|
33
|
+
var import_instrumentation_winston = require("@opentelemetry/instrumentation-winston");
|
|
34
|
+
var import_resources = require("@opentelemetry/resources");
|
|
35
|
+
var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
|
|
36
|
+
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
37
|
+
var import_genkit = require("genkit");
|
|
38
|
+
var import_logging = require("genkit/logging");
|
|
39
|
+
var import_action = require("./telemetry/action.js");
|
|
40
|
+
var import_engagement = require("./telemetry/engagement.js");
|
|
41
|
+
var import_feature = require("./telemetry/feature.js");
|
|
42
|
+
var import_generate = require("./telemetry/generate.js");
|
|
43
|
+
var import_path = require("./telemetry/path.js");
|
|
44
|
+
var import_utils = require("./utils.js");
|
|
45
|
+
let metricExporter;
|
|
46
|
+
let spanProcessor;
|
|
47
|
+
let spanExporter;
|
|
48
|
+
class GcpOpenTelemetry {
|
|
49
|
+
config;
|
|
50
|
+
resource;
|
|
51
|
+
constructor(config) {
|
|
52
|
+
this.config = config;
|
|
53
|
+
this.resource = new import_resources.Resource({ type: "global" }).merge(
|
|
54
|
+
new import_opentelemetry_resource_util.GcpDetectorSync().detect()
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Log hook for writing trace and span metadata to log messages in the format
|
|
59
|
+
* required by GCP.
|
|
60
|
+
*/
|
|
61
|
+
gcpTraceLogHook = (span, record) => {
|
|
62
|
+
const spanContext = span.spanContext();
|
|
63
|
+
const isSampled = !!(spanContext.traceFlags & import_api.TraceFlags.SAMPLED);
|
|
64
|
+
const projectId = this.config.projectId;
|
|
65
|
+
record["logging.googleapis.com/trace"] ??= `projects/${projectId}/traces/${spanContext.traceId}`;
|
|
66
|
+
record["logging.googleapis.com/trace_sampled"] ??= isSampled ? "1" : "0";
|
|
67
|
+
record["logging.googleapis.com/spanId"] ??= spanContext.spanId;
|
|
68
|
+
delete record["span_id"];
|
|
69
|
+
delete record["trace_id"];
|
|
70
|
+
delete record["trace_flags"];
|
|
71
|
+
};
|
|
72
|
+
async getConfig() {
|
|
73
|
+
spanProcessor = new import_sdk_trace_base.BatchSpanProcessor(await this.createSpanExporter());
|
|
74
|
+
return {
|
|
75
|
+
resource: this.resource,
|
|
76
|
+
spanProcessor,
|
|
77
|
+
sampler: this.config.sampler,
|
|
78
|
+
instrumentations: this.getInstrumentations(),
|
|
79
|
+
metricReader: await this.createMetricReader()
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async createSpanExporter() {
|
|
83
|
+
spanExporter = new AdjustingTraceExporter(
|
|
84
|
+
this.shouldExportTraces() ? new import_opentelemetry_cloud_trace_exporter.TraceExporter({
|
|
85
|
+
// provided projectId should take precedence over env vars, etc
|
|
86
|
+
projectId: this.config.projectId,
|
|
87
|
+
// creds for non-GCP environments, in lieu of using ADC.
|
|
88
|
+
credentials: this.config.credentials
|
|
89
|
+
}) : new import_sdk_trace_base.InMemorySpanExporter(),
|
|
90
|
+
this.config.exportInputAndOutput,
|
|
91
|
+
this.config.projectId,
|
|
92
|
+
getErrorHandler(
|
|
93
|
+
(err) => {
|
|
94
|
+
return (0, import_utils.tracingDenied)(err);
|
|
95
|
+
},
|
|
96
|
+
await (0, import_utils.tracingDeniedHelpText)()
|
|
97
|
+
)
|
|
98
|
+
);
|
|
99
|
+
return spanExporter;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Creates a {MetricReader} for pushing metrics out to GCP via OpenTelemetry.
|
|
103
|
+
*/
|
|
104
|
+
async createMetricReader() {
|
|
105
|
+
metricExporter = await this.buildMetricExporter();
|
|
106
|
+
return new import_sdk_metrics.PeriodicExportingMetricReader({
|
|
107
|
+
exportIntervalMillis: this.config.metricExportIntervalMillis,
|
|
108
|
+
exportTimeoutMillis: this.config.metricExportTimeoutMillis,
|
|
109
|
+
exporter: metricExporter
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/** Gets all open telemetry instrumentations as configured by the plugin. */
|
|
113
|
+
getInstrumentations() {
|
|
114
|
+
let instrumentations = [];
|
|
115
|
+
if (this.config.autoInstrumentation) {
|
|
116
|
+
instrumentations = (0, import_auto_instrumentations_node.getNodeAutoInstrumentations)(
|
|
117
|
+
this.config.autoInstrumentationConfig
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return instrumentations.concat(this.getDefaultLoggingInstrumentations()).concat(this.config.instrumentations ?? []);
|
|
121
|
+
}
|
|
122
|
+
shouldExportTraces() {
|
|
123
|
+
return this.config.export && !this.config.disableTraces;
|
|
124
|
+
}
|
|
125
|
+
shouldExportMetrics() {
|
|
126
|
+
return this.config.export && !this.config.disableMetrics;
|
|
127
|
+
}
|
|
128
|
+
/** Always configure the Pino and Winston instrumentations */
|
|
129
|
+
getDefaultLoggingInstrumentations() {
|
|
130
|
+
return [
|
|
131
|
+
new import_instrumentation_winston.WinstonInstrumentation({ logHook: this.gcpTraceLogHook }),
|
|
132
|
+
new import_instrumentation_pino.PinoInstrumentation({ logHook: this.gcpTraceLogHook })
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
async buildMetricExporter() {
|
|
136
|
+
const exporter = this.shouldExportMetrics() ? new MetricExporterWrapper(
|
|
137
|
+
{
|
|
138
|
+
userAgent: {
|
|
139
|
+
product: "genkit",
|
|
140
|
+
version: import_genkit.GENKIT_VERSION
|
|
141
|
+
},
|
|
142
|
+
// provided projectId should take precedence over env vars, etc
|
|
143
|
+
projectId: this.config.projectId,
|
|
144
|
+
// creds for non-GCP environments, in lieu of using ADC.
|
|
145
|
+
credentials: this.config.credentials
|
|
146
|
+
},
|
|
147
|
+
getErrorHandler(
|
|
148
|
+
(err) => {
|
|
149
|
+
return (0, import_utils.metricsDenied)(err);
|
|
150
|
+
},
|
|
151
|
+
await (0, import_utils.metricsDeniedHelpText)()
|
|
152
|
+
)
|
|
153
|
+
) : new import_sdk_metrics.InMemoryMetricExporter(import_sdk_metrics.AggregationTemporality.DELTA);
|
|
154
|
+
return exporter;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
class MetricExporterWrapper extends import_opentelemetry_cloud_monitoring_exporter.MetricExporter {
|
|
158
|
+
constructor(options, errorHandler) {
|
|
159
|
+
super(options);
|
|
160
|
+
this.errorHandler = errorHandler;
|
|
161
|
+
}
|
|
162
|
+
promise = new Promise((resolve) => resolve());
|
|
163
|
+
async export(metrics, resultCallback) {
|
|
164
|
+
await this.promise;
|
|
165
|
+
this.modifyStartTimes(metrics);
|
|
166
|
+
this.promise = new Promise((resolve) => {
|
|
167
|
+
super.export(metrics, (result) => {
|
|
168
|
+
try {
|
|
169
|
+
if (this.errorHandler && result.error) {
|
|
170
|
+
this.errorHandler(result.error);
|
|
171
|
+
}
|
|
172
|
+
resultCallback(result);
|
|
173
|
+
} finally {
|
|
174
|
+
resolve();
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
selectAggregation(instrumentType) {
|
|
180
|
+
if (instrumentType === import_sdk_metrics.InstrumentType.HISTOGRAM) {
|
|
181
|
+
return new import_sdk_metrics.ExponentialHistogramAggregation();
|
|
182
|
+
}
|
|
183
|
+
return new import_sdk_metrics.DefaultAggregation();
|
|
184
|
+
}
|
|
185
|
+
selectAggregationTemporality(instrumentType) {
|
|
186
|
+
return import_sdk_metrics.AggregationTemporality.DELTA;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Modify the start times of each data point to ensure no
|
|
190
|
+
* overlap with previous exports.
|
|
191
|
+
*
|
|
192
|
+
* Cloud metrics do not support delta metrics for custom metrics
|
|
193
|
+
* and will convert any DELTA aggregations to CUMULATIVE ones on
|
|
194
|
+
* export. There is implicit overlap in the start/end times that
|
|
195
|
+
* the Metric reader is sending -- the end_time of the previous
|
|
196
|
+
* export will become the start_time of the current export. The
|
|
197
|
+
* overlap in times means that only one of those records will
|
|
198
|
+
* persist and the other will be overwritten. This
|
|
199
|
+
* method adds a thousandth of a second to ensure discrete export
|
|
200
|
+
* timeframes.
|
|
201
|
+
*/
|
|
202
|
+
modifyStartTimes(metrics) {
|
|
203
|
+
metrics.scopeMetrics.forEach((scopeMetric) => {
|
|
204
|
+
scopeMetric.metrics.forEach((metric) => {
|
|
205
|
+
metric.dataPoints.forEach((dataPoint) => {
|
|
206
|
+
dataPoint.startTime[1] = dataPoint.startTime[1] + 1e6;
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
async shutdown() {
|
|
212
|
+
return await this.forceFlush();
|
|
213
|
+
}
|
|
214
|
+
async forceFlush() {
|
|
215
|
+
await this.promise;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
class AdjustingTraceExporter {
|
|
219
|
+
constructor(exporter, logInputAndOutput, projectId, errorHandler) {
|
|
220
|
+
this.exporter = exporter;
|
|
221
|
+
this.logInputAndOutput = logInputAndOutput;
|
|
222
|
+
this.projectId = projectId;
|
|
223
|
+
this.errorHandler = errorHandler;
|
|
224
|
+
}
|
|
225
|
+
export(spans, resultCallback) {
|
|
226
|
+
this.exporter?.export(this.adjust(spans), (result) => {
|
|
227
|
+
if (this.errorHandler && result.error) {
|
|
228
|
+
this.errorHandler(result.error);
|
|
229
|
+
}
|
|
230
|
+
resultCallback(result);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
shutdown() {
|
|
234
|
+
return this.exporter?.shutdown();
|
|
235
|
+
}
|
|
236
|
+
getExporter() {
|
|
237
|
+
return this.exporter;
|
|
238
|
+
}
|
|
239
|
+
forceFlush() {
|
|
240
|
+
if (this.exporter?.forceFlush) {
|
|
241
|
+
return this.exporter.forceFlush();
|
|
242
|
+
}
|
|
243
|
+
return Promise.resolve();
|
|
244
|
+
}
|
|
245
|
+
adjust(spans) {
|
|
246
|
+
return spans.map((span) => {
|
|
247
|
+
this.tickTelemetry(span);
|
|
248
|
+
span = this.redactInputOutput(span);
|
|
249
|
+
span = this.markErrorSpanAsError(span);
|
|
250
|
+
span = this.markFailedSpan(span);
|
|
251
|
+
span = this.markGenkitFeature(span);
|
|
252
|
+
span = this.markGenkitModel(span);
|
|
253
|
+
span = this.normalizeLabels(span);
|
|
254
|
+
return span;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
tickTelemetry(span) {
|
|
258
|
+
const attributes = span.attributes;
|
|
259
|
+
if (!Object.keys(attributes).includes("genkit:type")) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const type = attributes["genkit:type"];
|
|
263
|
+
const subtype = attributes["genkit:metadata:subtype"];
|
|
264
|
+
const isRoot = !!span.attributes["genkit:isRoot"];
|
|
265
|
+
import_path.pathsTelemetry.tick(span, this.logInputAndOutput, this.projectId);
|
|
266
|
+
if (isRoot) {
|
|
267
|
+
import_feature.featuresTelemetry.tick(span, this.logInputAndOutput, this.projectId);
|
|
268
|
+
span.attributes["genkit:rootState"] = span.attributes["genkit:state"];
|
|
269
|
+
} else {
|
|
270
|
+
if (type === "action" && subtype === "model") {
|
|
271
|
+
import_generate.generateTelemetry.tick(span, this.logInputAndOutput, this.projectId);
|
|
272
|
+
}
|
|
273
|
+
if (type === "action" && subtype === "tool") {
|
|
274
|
+
}
|
|
275
|
+
if (type === "action" || type === "flow" || type == "flowStep" || type == "util") {
|
|
276
|
+
import_action.actionTelemetry.tick(span, this.logInputAndOutput, this.projectId);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (type === "userEngagement") {
|
|
280
|
+
import_engagement.engagementTelemetry.tick(span, this.logInputAndOutput, this.projectId);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
redactInputOutput(span) {
|
|
284
|
+
const hasInput = "genkit:input" in span.attributes;
|
|
285
|
+
const hasOutput = "genkit:output" in span.attributes;
|
|
286
|
+
return !hasInput && !hasOutput ? span : {
|
|
287
|
+
...span,
|
|
288
|
+
spanContext: span.spanContext,
|
|
289
|
+
attributes: {
|
|
290
|
+
...span.attributes,
|
|
291
|
+
"genkit:input": "<redacted>",
|
|
292
|
+
"genkit:output": "<redacted>"
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
// This is a workaround for GCP Trace to mark a span with a red
|
|
297
|
+
// exclamation mark indicating that it is an error.
|
|
298
|
+
markErrorSpanAsError(span) {
|
|
299
|
+
return span.status.code !== import_api.SpanStatusCode.ERROR ? span : {
|
|
300
|
+
...span,
|
|
301
|
+
spanContext: span.spanContext,
|
|
302
|
+
attributes: {
|
|
303
|
+
...span.attributes,
|
|
304
|
+
"/http/status_code": "599"
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
normalizeLabels(span) {
|
|
309
|
+
const normalized = {};
|
|
310
|
+
for (const [key, value] of Object.entries(span.attributes)) {
|
|
311
|
+
normalized[key.replace(/\:/g, "/")] = value;
|
|
312
|
+
}
|
|
313
|
+
return {
|
|
314
|
+
...span,
|
|
315
|
+
spanContext: span.spanContext,
|
|
316
|
+
attributes: normalized
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
markFailedSpan(span) {
|
|
320
|
+
if (span.attributes["genkit:isFailureSource"]) {
|
|
321
|
+
span.attributes["genkit:failedSpan"] = span.attributes["genkit:name"];
|
|
322
|
+
span.attributes["genkit:failedPath"] = span.attributes["genkit:path"];
|
|
323
|
+
}
|
|
324
|
+
return span;
|
|
325
|
+
}
|
|
326
|
+
markGenkitFeature(span) {
|
|
327
|
+
if (span.attributes["genkit:isRoot"] && !!span.attributes["genkit:name"]) {
|
|
328
|
+
span.attributes["genkit:feature"] = span.attributes["genkit:name"];
|
|
329
|
+
}
|
|
330
|
+
return span;
|
|
331
|
+
}
|
|
332
|
+
markGenkitModel(span) {
|
|
333
|
+
if (span.attributes["genkit:metadata:subtype"] === "model" && !!span.attributes["genkit:name"]) {
|
|
334
|
+
span.attributes["genkit:model"] = span.attributes["genkit:name"];
|
|
335
|
+
}
|
|
336
|
+
return span;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function getErrorHandler(shouldLogFn, helpText) {
|
|
340
|
+
let instructionsLogged = false;
|
|
341
|
+
return (err) => {
|
|
342
|
+
const defaultLogger = import_logging.logger.defaultLogger;
|
|
343
|
+
if (err && shouldLogFn(err)) {
|
|
344
|
+
if (!instructionsLogged) {
|
|
345
|
+
instructionsLogged = true;
|
|
346
|
+
defaultLogger.error(
|
|
347
|
+
`Unable to send telemetry to Google Cloud: ${err.message}
|
|
348
|
+
|
|
349
|
+
${helpText}
|
|
350
|
+
`
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
} else if (err) {
|
|
354
|
+
defaultLogger.error(`Unable to send telemetry to Google Cloud: ${err}`);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function __getMetricExporterForTesting() {
|
|
359
|
+
return metricExporter;
|
|
360
|
+
}
|
|
361
|
+
function __getSpanExporterForTesting() {
|
|
362
|
+
return spanExporter.getExporter();
|
|
363
|
+
}
|
|
364
|
+
function __forceFlushSpansForTesting() {
|
|
365
|
+
spanProcessor.forceFlush();
|
|
366
|
+
}
|
|
367
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
368
|
+
0 && (module.exports = {
|
|
369
|
+
GcpOpenTelemetry,
|
|
370
|
+
__forceFlushSpansForTesting,
|
|
371
|
+
__getMetricExporterForTesting,
|
|
372
|
+
__getSpanExporterForTesting
|
|
373
|
+
});
|
|
374
|
+
//# sourceMappingURL=gcpOpenTelemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gcpOpenTelemetry.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n MetricExporter,\n type ExporterOptions,\n} from '@google-cloud/opentelemetry-cloud-monitoring-exporter';\nimport { TraceExporter } from '@google-cloud/opentelemetry-cloud-trace-exporter';\nimport { GcpDetectorSync } from '@google-cloud/opentelemetry-resource-util';\nimport { SpanStatusCode, TraceFlags, type Span } from '@opentelemetry/api';\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';\nimport { type ExportResult } from '@opentelemetry/core';\nimport type { Instrumentation } from '@opentelemetry/instrumentation';\nimport { PinoInstrumentation } from '@opentelemetry/instrumentation-pino';\nimport { WinstonInstrumentation } from '@opentelemetry/instrumentation-winston';\nimport { Resource } from '@opentelemetry/resources';\nimport {\n AggregationTemporality,\n DefaultAggregation,\n ExponentialHistogramAggregation,\n InMemoryMetricExporter,\n InstrumentType,\n PeriodicExportingMetricReader,\n type PushMetricExporter,\n type ResourceMetrics,\n} from '@opentelemetry/sdk-metrics';\nimport type { NodeSDKConfiguration } from '@opentelemetry/sdk-node';\nimport {\n BatchSpanProcessor,\n InMemorySpanExporter,\n type ReadableSpan,\n type SpanExporter,\n} from '@opentelemetry/sdk-trace-base';\nimport { GENKIT_VERSION } from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { actionTelemetry } from './telemetry/action.js';\nimport { engagementTelemetry } from './telemetry/engagement.js';\nimport { featuresTelemetry } from './telemetry/feature.js';\nimport { generateTelemetry } from './telemetry/generate.js';\nimport { pathsTelemetry } from './telemetry/path.js';\nimport type { GcpTelemetryConfig } from './types.js';\nimport {\n metricsDenied,\n metricsDeniedHelpText,\n tracingDenied,\n tracingDeniedHelpText,\n} from './utils.js';\n\nlet metricExporter: PushMetricExporter;\nlet spanProcessor: BatchSpanProcessor;\nlet spanExporter: AdjustingTraceExporter;\n\n/**\n * Provides a {TelemetryConfig} for exporting OpenTelemetry data (Traces,\n * Metrics, and Logs) to the Google Cloud Operations Suite.\n */\nexport class GcpOpenTelemetry {\n private readonly config: GcpTelemetryConfig;\n private readonly resource: Resource;\n\n constructor(config: GcpTelemetryConfig) {\n this.config = config;\n this.resource = new Resource({ type: 'global' }).merge(\n new GcpDetectorSync().detect()\n );\n }\n\n /**\n * Log hook for writing trace and span metadata to log messages in the format\n * required by GCP.\n */\n private gcpTraceLogHook = (span: Span, record: any) => {\n const spanContext = span.spanContext();\n const isSampled = !!(spanContext.traceFlags & TraceFlags.SAMPLED);\n const projectId = this.config.projectId;\n\n record['logging.googleapis.com/trace'] ??=\n `projects/${projectId}/traces/${spanContext.traceId}`;\n record['logging.googleapis.com/trace_sampled'] ??= isSampled ? '1' : '0';\n record['logging.googleapis.com/spanId'] ??= spanContext.spanId;\n\n // Clear out the duplicate trace and span information in the log metadata.\n // These will be incorrect for logs written during span export time since\n // the logs are written after the span has fully executed. Those logs are\n // explicitly tied to the correct span in createCommonLogAttributes in\n // utils.ts.\n delete record['span_id'];\n delete record['trace_id'];\n delete record['trace_flags'];\n };\n\n async getConfig(): Promise<Partial<NodeSDKConfiguration>> {\n spanProcessor = new BatchSpanProcessor(await this.createSpanExporter());\n return {\n resource: this.resource,\n spanProcessor: spanProcessor,\n sampler: this.config.sampler,\n instrumentations: this.getInstrumentations(),\n metricReader: await this.createMetricReader(),\n };\n }\n\n private async createSpanExporter(): Promise<SpanExporter> {\n spanExporter = new AdjustingTraceExporter(\n this.shouldExportTraces()\n ? new TraceExporter({\n // provided projectId should take precedence over env vars, etc\n projectId: this.config.projectId,\n // creds for non-GCP environments, in lieu of using ADC.\n credentials: this.config.credentials,\n })\n : new InMemorySpanExporter(),\n this.config.exportInputAndOutput,\n this.config.projectId,\n getErrorHandler(\n (err) => {\n return tracingDenied(err);\n },\n await tracingDeniedHelpText()\n )\n );\n return spanExporter;\n }\n\n /**\n * Creates a {MetricReader} for pushing metrics out to GCP via OpenTelemetry.\n */\n private async createMetricReader(): Promise<PeriodicExportingMetricReader> {\n metricExporter = await this.buildMetricExporter();\n return new PeriodicExportingMetricReader({\n exportIntervalMillis: this.config.metricExportIntervalMillis,\n exportTimeoutMillis: this.config.metricExportTimeoutMillis,\n exporter: metricExporter,\n });\n }\n\n /** Gets all open telemetry instrumentations as configured by the plugin. */\n private getInstrumentations() {\n let instrumentations: Instrumentation[] = [];\n\n if (this.config.autoInstrumentation) {\n instrumentations = getNodeAutoInstrumentations(\n this.config.autoInstrumentationConfig\n );\n }\n\n return instrumentations\n .concat(this.getDefaultLoggingInstrumentations())\n .concat(this.config.instrumentations ?? []);\n }\n\n private shouldExportTraces(): boolean {\n return this.config.export && !this.config.disableTraces;\n }\n\n private shouldExportMetrics(): boolean {\n return this.config.export && !this.config.disableMetrics;\n }\n\n /** Always configure the Pino and Winston instrumentations */\n private getDefaultLoggingInstrumentations(): Instrumentation[] {\n return [\n new WinstonInstrumentation({ logHook: this.gcpTraceLogHook }),\n new PinoInstrumentation({ logHook: this.gcpTraceLogHook }),\n ];\n }\n\n private async buildMetricExporter(): Promise<PushMetricExporter> {\n const exporter: PushMetricExporter = this.shouldExportMetrics()\n ? new MetricExporterWrapper(\n {\n userAgent: {\n product: 'genkit',\n version: GENKIT_VERSION,\n },\n // provided projectId should take precedence over env vars, etc\n projectId: this.config.projectId,\n // creds for non-GCP environments, in lieu of using ADC.\n credentials: this.config.credentials,\n },\n getErrorHandler(\n (err) => {\n return metricsDenied(err);\n },\n await metricsDeniedHelpText()\n )\n )\n : new InMemoryMetricExporter(AggregationTemporality.DELTA);\n return exporter;\n }\n}\n\n/**\n * Rewrites the export method to include an error handler which logs\n * helpful information about how to set up metrics/telemetry in GCP.\n */\nclass MetricExporterWrapper extends MetricExporter {\n private promise = new Promise<void>((resolve) => resolve());\n\n constructor(\n options?: ExporterOptions,\n private errorHandler?: (error: Error) => void\n ) {\n super(options);\n }\n\n async export(\n metrics: ResourceMetrics,\n resultCallback: (result: ExportResult) => void\n ): Promise<void> {\n await this.promise;\n this.modifyStartTimes(metrics);\n this.promise = new Promise<void>((resolve) => {\n super.export(metrics, (result) => {\n try {\n if (this.errorHandler && result.error) {\n this.errorHandler(result.error);\n }\n resultCallback(result);\n } finally {\n resolve();\n }\n });\n });\n }\n\n selectAggregation(instrumentType: InstrumentType) {\n if (instrumentType === InstrumentType.HISTOGRAM) {\n return new ExponentialHistogramAggregation();\n }\n return new DefaultAggregation();\n }\n\n selectAggregationTemporality(instrumentType: InstrumentType) {\n return AggregationTemporality.DELTA;\n }\n\n /**\n * Modify the start times of each data point to ensure no\n * overlap with previous exports.\n *\n * Cloud metrics do not support delta metrics for custom metrics\n * and will convert any DELTA aggregations to CUMULATIVE ones on\n * export. There is implicit overlap in the start/end times that\n * the Metric reader is sending -- the end_time of the previous\n * export will become the start_time of the current export. The\n * overlap in times means that only one of those records will\n * persist and the other will be overwritten. This\n * method adds a thousandth of a second to ensure discrete export\n * timeframes.\n */\n private modifyStartTimes(metrics: ResourceMetrics): void {\n metrics.scopeMetrics.forEach((scopeMetric) => {\n scopeMetric.metrics.forEach((metric) => {\n metric.dataPoints.forEach((dataPoint) => {\n dataPoint.startTime[1] = dataPoint.startTime[1] + 1_000_000;\n });\n });\n });\n }\n\n async shutdown(): Promise<void> {\n return await this.forceFlush();\n }\n\n async forceFlush(): Promise<void> {\n await this.promise;\n }\n}\n\n/**\n * Adjusts spans before exporting to GCP. Redacts model input\n * and output content, and augments span attributes before sending to GCP.\n */\nclass AdjustingTraceExporter implements SpanExporter {\n constructor(\n private exporter: SpanExporter,\n private logInputAndOutput: boolean,\n private projectId?: string,\n private errorHandler?: (error: Error) => void\n ) {}\n\n export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void\n ): void {\n this.exporter?.export(this.adjust(spans), (result) => {\n if (this.errorHandler && result.error) {\n this.errorHandler(result.error);\n }\n resultCallback(result);\n });\n }\n\n shutdown(): Promise<void> {\n return this.exporter?.shutdown();\n }\n\n getExporter(): SpanExporter {\n return this.exporter;\n }\n\n forceFlush(): Promise<void> {\n if (this.exporter?.forceFlush) {\n return this.exporter.forceFlush();\n }\n return Promise.resolve();\n }\n\n private adjust(spans: ReadableSpan[]): ReadableSpan[] {\n return spans.map((span) => {\n this.tickTelemetry(span);\n\n span = this.redactInputOutput(span);\n span = this.markErrorSpanAsError(span);\n span = this.markFailedSpan(span);\n span = this.markGenkitFeature(span);\n span = this.markGenkitModel(span);\n span = this.normalizeLabels(span);\n return span;\n });\n }\n\n private tickTelemetry(span: ReadableSpan) {\n const attributes = span.attributes;\n if (!Object.keys(attributes).includes('genkit:type')) {\n return;\n }\n\n const type = attributes['genkit:type'] as string;\n const subtype = attributes['genkit:metadata:subtype'] as string;\n const isRoot = !!span.attributes['genkit:isRoot'];\n\n pathsTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n if (isRoot) {\n // Report top level feature request and latency only for root spans\n // Log input to and output from to the feature\n featuresTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n // Set root status explicitly\n span.attributes['genkit:rootState'] = span.attributes['genkit:state'];\n } else {\n if (type === 'action' && subtype === 'model') {\n // Report generate metrics () for all model actions\n generateTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n }\n if (type === 'action' && subtype === 'tool') {\n // TODO: Report input and output for tool actions\n }\n if (\n type === 'action' ||\n type === 'flow' ||\n type == 'flowStep' ||\n type == 'util'\n ) {\n // Report request and latency metrics for all actions\n actionTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n }\n }\n if (type === 'userEngagement') {\n // Report user acceptance and feedback metrics\n engagementTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n }\n }\n\n private redactInputOutput(span: ReadableSpan): ReadableSpan {\n const hasInput = 'genkit:input' in span.attributes;\n const hasOutput = 'genkit:output' in span.attributes;\n\n return !hasInput && !hasOutput\n ? span\n : {\n ...span,\n spanContext: span.spanContext,\n attributes: {\n ...span.attributes,\n 'genkit:input': '<redacted>',\n 'genkit:output': '<redacted>',\n },\n };\n }\n\n // This is a workaround for GCP Trace to mark a span with a red\n // exclamation mark indicating that it is an error.\n private markErrorSpanAsError(span: ReadableSpan): ReadableSpan {\n return span.status.code !== SpanStatusCode.ERROR\n ? span\n : {\n ...span,\n spanContext: span.spanContext,\n attributes: {\n ...span.attributes,\n '/http/status_code': '599',\n },\n };\n }\n\n private normalizeLabels(span: ReadableSpan): ReadableSpan {\n const normalized = {} as Record<string, any>;\n for (const [key, value] of Object.entries(span.attributes)) {\n normalized[key.replace(/\\:/g, '/')] = value;\n }\n return {\n ...span,\n spanContext: span.spanContext,\n attributes: normalized,\n };\n }\n\n private markFailedSpan(span: ReadableSpan): ReadableSpan {\n if (span.attributes['genkit:isFailureSource']) {\n span.attributes['genkit:failedSpan'] = span.attributes['genkit:name'];\n span.attributes['genkit:failedPath'] = span.attributes['genkit:path'];\n }\n return span;\n }\n\n private markGenkitFeature(span: ReadableSpan): ReadableSpan {\n if (span.attributes['genkit:isRoot'] && !!span.attributes['genkit:name']) {\n span.attributes['genkit:feature'] = span.attributes['genkit:name'];\n }\n return span;\n }\n\n private markGenkitModel(span: ReadableSpan): ReadableSpan {\n if (\n span.attributes['genkit:metadata:subtype'] === 'model' &&\n !!span.attributes['genkit:name']\n ) {\n span.attributes['genkit:model'] = span.attributes['genkit:name'];\n }\n return span;\n }\n}\n\nfunction getErrorHandler(\n shouldLogFn: (err: Error) => boolean,\n helpText: string\n): (err: Error) => void {\n // only log the first time\n let instructionsLogged = false;\n\n return (err) => {\n // Use the defaultLogger so that logs don't get swallowed by the open\n // telemetry exporter\n const defaultLogger = logger.defaultLogger;\n if (err && shouldLogFn(err)) {\n if (!instructionsLogged) {\n instructionsLogged = true;\n defaultLogger.error(\n `Unable to send telemetry to Google Cloud: ${err.message}\\n\\n${helpText}\\n`\n );\n }\n } else if (err) {\n defaultLogger.error(`Unable to send telemetry to Google Cloud: ${err}`);\n }\n };\n}\n\n/** @hidden */\nexport function __getMetricExporterForTesting(): InMemoryMetricExporter {\n return metricExporter as InMemoryMetricExporter;\n}\n\n/** @hidden */\nexport function __getSpanExporterForTesting(): InMemorySpanExporter {\n return spanExporter.getExporter() as InMemorySpanExporter;\n}\n\n/** @hidden */\nexport function __forceFlushSpansForTesting() {\n spanProcessor.forceFlush();\n}\n"],"mappings":"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","names":[]}
|