@odigos/aws-cdk 0.0.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/.jsii +4531 -0
- package/README.md +191 -0
- package/lib/collector-config.d.ts +68 -0
- package/lib/collector-config.js +192 -0
- package/lib/generated/layers.d.ts +45 -0
- package/lib/generated/layers.js +101 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +37 -0
- package/lib/instrumentation.d.ts +186 -0
- package/lib/instrumentation.js +212 -0
- package/lib/layer-resolver.d.ts +46 -0
- package/lib/layer-resolver.js +118 -0
- package/lib/runtime.d.ts +49 -0
- package/lib/runtime.js +119 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types.d.ts +155 -0
- package/lib/types.js +90 -0
- package/package.json +115 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.SAR_SEMANTIC_VERSION = exports.SAR_APPLICATIONS = exports.LAYER_ARNS = exports.ODIGOS_VERSION = exports.ENV_LOGS_EXPORTER = exports.ENV_METRICS_EXPORTER = exports.ENV_TRACES_EXPORTER = exports.ENV_COLLECTOR_CONFIG_URI = exports.renderCollectorConfig = exports.layerNameFor = exports.execWrapperFor = exports.languageFromRuntime = exports.odigosLayerName = void 0;
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
__exportStar(require("./instrumentation"), exports);
|
|
20
|
+
var layer_resolver_1 = require("./layer-resolver");
|
|
21
|
+
Object.defineProperty(exports, "odigosLayerName", { enumerable: true, get: function () { return layer_resolver_1.odigosLayerName; } });
|
|
22
|
+
var runtime_1 = require("./runtime");
|
|
23
|
+
Object.defineProperty(exports, "languageFromRuntime", { enumerable: true, get: function () { return runtime_1.languageFromRuntime; } });
|
|
24
|
+
Object.defineProperty(exports, "execWrapperFor", { enumerable: true, get: function () { return runtime_1.execWrapperFor; } });
|
|
25
|
+
Object.defineProperty(exports, "layerNameFor", { enumerable: true, get: function () { return runtime_1.layerNameFor; } });
|
|
26
|
+
var collector_config_1 = require("./collector-config");
|
|
27
|
+
Object.defineProperty(exports, "renderCollectorConfig", { enumerable: true, get: function () { return collector_config_1.renderCollectorConfig; } });
|
|
28
|
+
Object.defineProperty(exports, "ENV_COLLECTOR_CONFIG_URI", { enumerable: true, get: function () { return collector_config_1.ENV_COLLECTOR_CONFIG_URI; } });
|
|
29
|
+
Object.defineProperty(exports, "ENV_TRACES_EXPORTER", { enumerable: true, get: function () { return collector_config_1.ENV_TRACES_EXPORTER; } });
|
|
30
|
+
Object.defineProperty(exports, "ENV_METRICS_EXPORTER", { enumerable: true, get: function () { return collector_config_1.ENV_METRICS_EXPORTER; } });
|
|
31
|
+
Object.defineProperty(exports, "ENV_LOGS_EXPORTER", { enumerable: true, get: function () { return collector_config_1.ENV_LOGS_EXPORTER; } });
|
|
32
|
+
var layers_1 = require("./generated/layers");
|
|
33
|
+
Object.defineProperty(exports, "ODIGOS_VERSION", { enumerable: true, get: function () { return layers_1.ODIGOS_VERSION; } });
|
|
34
|
+
Object.defineProperty(exports, "LAYER_ARNS", { enumerable: true, get: function () { return layers_1.LAYER_ARNS; } });
|
|
35
|
+
Object.defineProperty(exports, "SAR_APPLICATIONS", { enumerable: true, get: function () { return layers_1.SAR_APPLICATIONS; } });
|
|
36
|
+
Object.defineProperty(exports, "SAR_SEMANTIC_VERSION", { enumerable: true, get: function () { return layers_1.SAR_SEMANTIC_VERSION; } });
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwwQ0FBd0I7QUFDeEIsb0RBQWtDO0FBQ2xDLG1EQUFtRDtBQUExQyxpSEFBQSxlQUFlLE9BQUE7QUFDeEIscUNBQThFO0FBQXJFLDhHQUFBLG1CQUFtQixPQUFBO0FBQUUseUdBQUEsY0FBYyxPQUFBO0FBQUUsdUdBQUEsWUFBWSxPQUFBO0FBQzFELHVEQU00QjtBQUwxQix5SEFBQSxxQkFBcUIsT0FBQTtBQUNyQiw0SEFBQSx3QkFBd0IsT0FBQTtBQUN4Qix1SEFBQSxtQkFBbUIsT0FBQTtBQUNuQix3SEFBQSxvQkFBb0IsT0FBQTtBQUNwQixxSEFBQSxpQkFBaUIsT0FBQTtBQUVuQiw2Q0FBd0c7QUFBL0Ysd0dBQUEsY0FBYyxPQUFBO0FBQUUsb0dBQUEsVUFBVSxPQUFBO0FBQUUsMEdBQUEsZ0JBQWdCLE9BQUE7QUFBRSw4R0FBQSxvQkFBb0IsT0FBQSIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vdHlwZXMnO1xuZXhwb3J0ICogZnJvbSAnLi9pbnN0cnVtZW50YXRpb24nO1xuZXhwb3J0IHsgb2RpZ29zTGF5ZXJOYW1lIH0gZnJvbSAnLi9sYXllci1yZXNvbHZlcic7XG5leHBvcnQgeyBsYW5ndWFnZUZyb21SdW50aW1lLCBleGVjV3JhcHBlckZvciwgbGF5ZXJOYW1lRm9yIH0gZnJvbSAnLi9ydW50aW1lJztcbmV4cG9ydCB7XG4gIHJlbmRlckNvbGxlY3RvckNvbmZpZyxcbiAgRU5WX0NPTExFQ1RPUl9DT05GSUdfVVJJLFxuICBFTlZfVFJBQ0VTX0VYUE9SVEVSLFxuICBFTlZfTUVUUklDU19FWFBPUlRFUixcbiAgRU5WX0xPR1NfRVhQT1JURVIsXG59IGZyb20gJy4vY29sbGVjdG9yLWNvbmZpZyc7XG5leHBvcnQgeyBPRElHT1NfVkVSU0lPTiwgTEFZRVJfQVJOUywgU0FSX0FQUExJQ0FUSU9OUywgU0FSX1NFTUFOVElDX1ZFUlNJT04gfSBmcm9tICcuL2dlbmVyYXRlZC9sYXllcnMnO1xuIl19
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { IAspect } from 'aws-cdk-lib';
|
|
2
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
3
|
+
import { Construct, IConstruct } from 'constructs';
|
|
4
|
+
import { OdigosDestination, OdigosInstrumentationMode, OdigosJavaHandlerDistro, OdigosLayerSource } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Options shared by the construct and the aspect.
|
|
7
|
+
*/
|
|
8
|
+
export interface OdigosInstrumentationOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Where the in-Lambda collector exports to.
|
|
11
|
+
*/
|
|
12
|
+
readonly destination: OdigosDestination;
|
|
13
|
+
/**
|
|
14
|
+
* Where the Odigos layer comes from.
|
|
15
|
+
*
|
|
16
|
+
* @default OdigosLayerSource.ODIGOS_PUBLIC
|
|
17
|
+
*/
|
|
18
|
+
readonly layerSource?: OdigosLayerSource;
|
|
19
|
+
/**
|
|
20
|
+
* Handler mode or web-server (Lambda Web Adapter) mode.
|
|
21
|
+
*
|
|
22
|
+
* There is no auto-detection, and that is deliberate rather than an omission: detecting the web adapter
|
|
23
|
+
* means inspecting the function's other layers, which at synth time are frequently unresolved tokens.
|
|
24
|
+
* A detector that is right most of the time would silently break the functions it got wrong.
|
|
25
|
+
*
|
|
26
|
+
* @default OdigosInstrumentationMode.HANDLER
|
|
27
|
+
*/
|
|
28
|
+
readonly mode?: OdigosInstrumentationMode;
|
|
29
|
+
/**
|
|
30
|
+
* Which of the Java layer's four wrapper scripts to use. Ignored for other languages.
|
|
31
|
+
*
|
|
32
|
+
* @default OdigosJavaHandlerDistro.OTEL_HANDLER
|
|
33
|
+
*/
|
|
34
|
+
readonly javaHandlerDistro?: OdigosJavaHandlerDistro;
|
|
35
|
+
/**
|
|
36
|
+
* `OTEL_SERVICE_NAME` for every function this instruments.
|
|
37
|
+
*
|
|
38
|
+
* Usually wrong to set when instrumenting more than one function — they would all report as the same
|
|
39
|
+
* service.
|
|
40
|
+
*
|
|
41
|
+
* Left unset, a function reports as its explicitly-set physical name if it has one, and otherwise as
|
|
42
|
+
* its construct id. It deliberately does not default to the generated physical name: that value is a
|
|
43
|
+
* `Ref` to the function itself, and a function referencing itself in its own environment is a
|
|
44
|
+
* CloudFormation dependency cycle.
|
|
45
|
+
*
|
|
46
|
+
* @default - the function's physical name if explicitly set, otherwise its construct id
|
|
47
|
+
*/
|
|
48
|
+
readonly serviceName?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Raise in-function OpenTelemetry verbosity (`OTEL_LOG_LEVEL=debug`).
|
|
51
|
+
*
|
|
52
|
+
* The layer, SDK and collector then emit span and OTLP-export diagnostics into the function's CloudWatch
|
|
53
|
+
* log group. Useful while wiring up a destination, expensive to leave on.
|
|
54
|
+
*
|
|
55
|
+
* Has no effect in web-server mode, matching the connector, which never sets a log level there.
|
|
56
|
+
*
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
readonly debug?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Attach this layer instead of resolving one. Overrides `layerSource` entirely.
|
|
62
|
+
*
|
|
63
|
+
* The escape hatch for a layer mirrored into a private registry or an internal account. The layer must
|
|
64
|
+
* have the same contents as the Odigos one — the environment set here assumes its exact script layout.
|
|
65
|
+
*
|
|
66
|
+
* @default - resolved from layerSource
|
|
67
|
+
*/
|
|
68
|
+
readonly layerVersion?: lambda.ILayerVersion;
|
|
69
|
+
/**
|
|
70
|
+
* The value the function already needs in its language loader variable (`NODE_OPTIONS`,
|
|
71
|
+
* `JAVA_TOOL_OPTIONS` or `PYTHONPATH`), which the Odigos loader is joined to rather than replacing.
|
|
72
|
+
*
|
|
73
|
+
* Only used in web-server mode. It has to be passed explicitly because CDK's `lambda.Function` exposes
|
|
74
|
+
* no way to read back an environment variable set elsewhere in the app — an omitted value here is
|
|
75
|
+
* silently overwritten, which for `NODE_OPTIONS` can mean losing a flag the app needs to boot.
|
|
76
|
+
*
|
|
77
|
+
* @default - the loader variable is set to the Odigos value alone
|
|
78
|
+
*/
|
|
79
|
+
readonly existingLoaderValue?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Skip functions whose runtime has no OpenTelemetry Lambda layer instead of throwing.
|
|
82
|
+
*
|
|
83
|
+
* `dotnet*` and `provided.*` (Go, custom runtimes) have no language layer upstream. Explicitly
|
|
84
|
+
* instrumenting one is a mistake worth failing on; sweeping a whole stack with the aspect and hitting
|
|
85
|
+
* one is not, which is why the aspect defaults this to `true` and the construct to `false`.
|
|
86
|
+
*
|
|
87
|
+
* @default false
|
|
88
|
+
*/
|
|
89
|
+
readonly skipUnsupportedRuntimes?: boolean;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Props for {@link OdigosLambdaInstrumentation}.
|
|
93
|
+
*/
|
|
94
|
+
export interface OdigosLambdaInstrumentationProps extends OdigosInstrumentationOptions {
|
|
95
|
+
/**
|
|
96
|
+
* Functions to instrument on construction. More can be added with `instrument()`.
|
|
97
|
+
*
|
|
98
|
+
* @default - none
|
|
99
|
+
*/
|
|
100
|
+
readonly functions?: lambda.Function[];
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Instruments AWS Lambda functions with the Odigos OpenTelemetry layer.
|
|
104
|
+
*
|
|
105
|
+
* ```ts
|
|
106
|
+
* const odigos = new OdigosLambdaInstrumentation(this, 'Odigos', {
|
|
107
|
+
* destination: { endpoint: 'otlp.example.com:4317' },
|
|
108
|
+
* functions: [apiFn, workerFn],
|
|
109
|
+
* });
|
|
110
|
+
* odigos.instrument(anotherFn);
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* What it does to each function: attaches the layer for the function's language and architecture, sets
|
|
114
|
+
* `AWS_LAMBDA_EXEC_WRAPPER` so the layer loads the SDK, sets `OTEL_SERVICE_NAME`, and hands the in-Lambda
|
|
115
|
+
* collector its entire configuration inline through `OPENTELEMETRY_COLLECTOR_CONFIG_URI`.
|
|
116
|
+
*
|
|
117
|
+
* The function's SDK exports to the collector on localhost, not to your destination. The collector
|
|
118
|
+
* forwards after the handler has already returned, so a slow destination costs billed duration rather
|
|
119
|
+
* than caller latency.
|
|
120
|
+
*
|
|
121
|
+
* ## Do not also instrument these functions with the connector
|
|
122
|
+
*
|
|
123
|
+
* The Odigos AWS connector instruments live functions by mutating them, and reconciles them back to its
|
|
124
|
+
* own desired state on every pass. A function instrumented here and also enabled as a connector source
|
|
125
|
+
* ends up owned by both: each `cdk deploy` reasserts the CDK's environment, each reconcile reasserts the
|
|
126
|
+
* connector's, and every round trip publishes a new function version.
|
|
127
|
+
*
|
|
128
|
+
* Choose one per function. This construct never sets the connector's `ODIGOS_MANAGED` ownership marker,
|
|
129
|
+
* so an IaC-instrumented function is not one the connector will roll back — but it will happily take it
|
|
130
|
+
* over if you enable it as a source.
|
|
131
|
+
*/
|
|
132
|
+
export declare class OdigosLambdaInstrumentation extends Construct {
|
|
133
|
+
private readonly options;
|
|
134
|
+
private readonly resolver;
|
|
135
|
+
private readonly collectorConfig;
|
|
136
|
+
private readonly instrumented;
|
|
137
|
+
constructor(scope: Construct, id: string, props: OdigosLambdaInstrumentationProps);
|
|
138
|
+
/**
|
|
139
|
+
* Instruments one function. Idempotent — instrumenting the same function twice is a no-op rather than a
|
|
140
|
+
* doubled loader value.
|
|
141
|
+
*/
|
|
142
|
+
instrument(fn: lambda.Function): void;
|
|
143
|
+
/** Instruments every function in the list. */
|
|
144
|
+
instrumentAll(functions: lambda.Function[]): void;
|
|
145
|
+
/**
|
|
146
|
+
* The environment applied to one function.
|
|
147
|
+
*
|
|
148
|
+
* Mirrors `applyHandlerEnv` / `applyWebServerEnv` in the connector, including what is deliberately NOT
|
|
149
|
+
* set: `OTEL_EXPORTER_OTLP_ENDPOINT` stays unset so the SDK keeps exporting to the in-Lambda collector
|
|
150
|
+
* on localhost rather than blocking the invocation on the remote destination, and an enabled signal's
|
|
151
|
+
* `OTEL_*_EXPORTER` stays unset because `otlp` is already the SDK default.
|
|
152
|
+
*/
|
|
153
|
+
private environmentFor;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Props for {@link OdigosInstrumentationAspect}.
|
|
157
|
+
*/
|
|
158
|
+
export interface OdigosInstrumentationAspectProps extends OdigosInstrumentationOptions {
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Applies Odigos instrumentation to every `lambda.Function` in a scope.
|
|
162
|
+
*
|
|
163
|
+
* ```ts
|
|
164
|
+
* Aspects.of(stack).add(new OdigosInstrumentationAspect(stack, {
|
|
165
|
+
* destination: { endpoint: 'otlp.example.com:4317' },
|
|
166
|
+
* }));
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* `skipUnsupportedRuntimes` defaults to `true` here, unlike the construct: an aspect visits every function
|
|
170
|
+
* in the scope, including ones whose runtime has no OpenTelemetry layer, and failing the whole synth
|
|
171
|
+
* because a stack happens to contain one Go function is not useful. Each skip is reported as a synth
|
|
172
|
+
* warning, so it is visible rather than silent.
|
|
173
|
+
*
|
|
174
|
+
* The aspect instruments what exists in the tree when it runs. A function added by a later aspect is not
|
|
175
|
+
* visited; use the construct directly for those.
|
|
176
|
+
*/
|
|
177
|
+
export declare class OdigosInstrumentationAspect implements IAspect {
|
|
178
|
+
private readonly instrumentation;
|
|
179
|
+
/**
|
|
180
|
+
* @param scope where the shared layer constructs are created. Usually the same scope the aspect is
|
|
181
|
+
* applied to. It is a separate argument from the visited nodes because the layer (and, in `IN_ACCOUNT`
|
|
182
|
+
* mode, the nested SAR application) is created once and shared by every function the aspect visits.
|
|
183
|
+
*/
|
|
184
|
+
constructor(scope: Construct, props: OdigosInstrumentationAspectProps);
|
|
185
|
+
visit(node: IConstruct): void;
|
|
186
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a, _b;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.OdigosInstrumentationAspect = exports.OdigosLambdaInstrumentation = void 0;
|
|
5
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
7
|
+
const lambda = require("aws-cdk-lib/aws-lambda");
|
|
8
|
+
const constructs_1 = require("constructs");
|
|
9
|
+
const collector_config_1 = require("./collector-config");
|
|
10
|
+
const layers_1 = require("./generated/layers");
|
|
11
|
+
const layer_resolver_1 = require("./layer-resolver");
|
|
12
|
+
const runtime_1 = require("./runtime");
|
|
13
|
+
const types_1 = require("./types");
|
|
14
|
+
/** `AWS_LAMBDA_EXEC_WRAPPER` — the layer's entry point in handler mode. */
|
|
15
|
+
const ENV_EXEC_WRAPPER = 'AWS_LAMBDA_EXEC_WRAPPER';
|
|
16
|
+
/** Service name reported on every span, metric and log record. */
|
|
17
|
+
const ENV_SERVICE_NAME = 'OTEL_SERVICE_NAME';
|
|
18
|
+
/** Raises in-function OpenTelemetry verbosity into the function's CloudWatch log group. */
|
|
19
|
+
const ENV_OTEL_LOG_LEVEL = 'OTEL_LOG_LEVEL';
|
|
20
|
+
/**
|
|
21
|
+
* Marker recording that this function was instrumented by IaC, and by which version.
|
|
22
|
+
*
|
|
23
|
+
* Deliberately NOT `ODIGOS_MANAGED`. That variable is the connector's OWNERSHIP PROOF: a function
|
|
24
|
+
* carrying it is one the connector believes it instrumented, whose environment it will converge on every
|
|
25
|
+
* reconcile and strip on rollback — using a snapshot of "the customer's original values" that a CDK
|
|
26
|
+
* deployment never wrote. Setting it here would hand the connector a function it does not own, with a
|
|
27
|
+
* snapshot describing a state that never existed.
|
|
28
|
+
*
|
|
29
|
+
* This variable is informational only. Nothing reads it.
|
|
30
|
+
*/
|
|
31
|
+
const ENV_IAC_MARKER = 'ODIGOS_IAC';
|
|
32
|
+
/**
|
|
33
|
+
* The service a function reports as, when the caller has not named one.
|
|
34
|
+
*
|
|
35
|
+
* NOT `fn.functionName`. For a function whose physical name CloudFormation generates, that property is a
|
|
36
|
+
* `Ref` to the function itself — putting it in the function's own environment makes the resource depend
|
|
37
|
+
* on its own creation, and CloudFormation rejects the template with a dependency cycle. Every
|
|
38
|
+
* instrumented function would fail to deploy, at deploy time rather than synth time.
|
|
39
|
+
*
|
|
40
|
+
* So: use the physical name when the caller set one explicitly (`resolve` yields a literal string for a
|
|
41
|
+
* known physical name, and a `Ref` object otherwise), and otherwise fall back to the construct id, which
|
|
42
|
+
* is what the function is called in the code and needs no reference at all.
|
|
43
|
+
*
|
|
44
|
+
* The connector reports the real AWS function name for the functions IT instruments. A function with a
|
|
45
|
+
* generated physical name therefore reports differently under the two paths — pass `serviceName`
|
|
46
|
+
* explicitly if that matters.
|
|
47
|
+
*/
|
|
48
|
+
function defaultServiceName(fn) {
|
|
49
|
+
const resolved = aws_cdk_lib_1.Stack.of(fn).resolve(fn.functionName);
|
|
50
|
+
return typeof resolved === 'string' ? resolved : fn.node.id;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Instruments AWS Lambda functions with the Odigos OpenTelemetry layer.
|
|
54
|
+
*
|
|
55
|
+
* ```ts
|
|
56
|
+
* const odigos = new OdigosLambdaInstrumentation(this, 'Odigos', {
|
|
57
|
+
* destination: { endpoint: 'otlp.example.com:4317' },
|
|
58
|
+
* functions: [apiFn, workerFn],
|
|
59
|
+
* });
|
|
60
|
+
* odigos.instrument(anotherFn);
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* What it does to each function: attaches the layer for the function's language and architecture, sets
|
|
64
|
+
* `AWS_LAMBDA_EXEC_WRAPPER` so the layer loads the SDK, sets `OTEL_SERVICE_NAME`, and hands the in-Lambda
|
|
65
|
+
* collector its entire configuration inline through `OPENTELEMETRY_COLLECTOR_CONFIG_URI`.
|
|
66
|
+
*
|
|
67
|
+
* The function's SDK exports to the collector on localhost, not to your destination. The collector
|
|
68
|
+
* forwards after the handler has already returned, so a slow destination costs billed duration rather
|
|
69
|
+
* than caller latency.
|
|
70
|
+
*
|
|
71
|
+
* ## Do not also instrument these functions with the connector
|
|
72
|
+
*
|
|
73
|
+
* The Odigos AWS connector instruments live functions by mutating them, and reconciles them back to its
|
|
74
|
+
* own desired state on every pass. A function instrumented here and also enabled as a connector source
|
|
75
|
+
* ends up owned by both: each `cdk deploy` reasserts the CDK's environment, each reconcile reasserts the
|
|
76
|
+
* connector's, and every round trip publishes a new function version.
|
|
77
|
+
*
|
|
78
|
+
* Choose one per function. This construct never sets the connector's `ODIGOS_MANAGED` ownership marker,
|
|
79
|
+
* so an IaC-instrumented function is not one the connector will roll back — but it will happily take it
|
|
80
|
+
* over if you enable it as a source.
|
|
81
|
+
*/
|
|
82
|
+
class OdigosLambdaInstrumentation extends constructs_1.Construct {
|
|
83
|
+
constructor(scope, id, props) {
|
|
84
|
+
super(scope, id);
|
|
85
|
+
this.instrumented = new Set();
|
|
86
|
+
this.options = props;
|
|
87
|
+
this.resolver = new layer_resolver_1.OdigosLayerResolver(this, props.layerSource ?? types_1.OdigosLayerSource.ODIGOS_PUBLIC);
|
|
88
|
+
// Rendered once. It depends only on the destination, and rendering it per function would make an
|
|
89
|
+
// accidental difference between two functions possible.
|
|
90
|
+
this.collectorConfig = (0, collector_config_1.renderCollectorConfig)(props.destination);
|
|
91
|
+
for (const fn of props.functions ?? []) {
|
|
92
|
+
this.instrument(fn);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Instruments one function. Idempotent — instrumenting the same function twice is a no-op rather than a
|
|
97
|
+
* doubled loader value.
|
|
98
|
+
*/
|
|
99
|
+
instrument(fn) {
|
|
100
|
+
const key = fn.node.path;
|
|
101
|
+
if (this.instrumented.has(key)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const runtimeName = fn.runtime.name;
|
|
105
|
+
const language = (0, runtime_1.languageFromRuntime)(runtimeName);
|
|
106
|
+
if (!language) {
|
|
107
|
+
const message = `Odigos: runtime "${runtimeName}" has no OpenTelemetry Lambda layer ` +
|
|
108
|
+
'(upstream publishes layers for python, nodejs, java and ruby only), so this function cannot be instrumented.';
|
|
109
|
+
if (this.options.skipUnsupportedRuntimes) {
|
|
110
|
+
aws_cdk_lib_1.Annotations.of(fn).addWarningV2('@odigos/aws-cdk:unsupportedRuntime', `${message} Skipping.`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
throw new Error(`${message} Set skipUnsupportedRuntimes: true to skip it instead.`);
|
|
114
|
+
}
|
|
115
|
+
this.instrumented.add(key);
|
|
116
|
+
const architecture = fn.architecture.name;
|
|
117
|
+
const layer = this.options.layerVersion ?? this.resolver.resolve(language, architecture);
|
|
118
|
+
fn.addLayers(layer);
|
|
119
|
+
for (const [name, value] of Object.entries(this.environmentFor(fn, language))) {
|
|
120
|
+
fn.addEnvironment(name, value);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** Instruments every function in the list. */
|
|
124
|
+
instrumentAll(functions) {
|
|
125
|
+
for (const fn of functions) {
|
|
126
|
+
this.instrument(fn);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The environment applied to one function.
|
|
131
|
+
*
|
|
132
|
+
* Mirrors `applyHandlerEnv` / `applyWebServerEnv` in the connector, including what is deliberately NOT
|
|
133
|
+
* set: `OTEL_EXPORTER_OTLP_ENDPOINT` stays unset so the SDK keeps exporting to the in-Lambda collector
|
|
134
|
+
* on localhost rather than blocking the invocation on the remote destination, and an enabled signal's
|
|
135
|
+
* `OTEL_*_EXPORTER` stays unset because `otlp` is already the SDK default.
|
|
136
|
+
*/
|
|
137
|
+
environmentFor(fn, language) {
|
|
138
|
+
const { destination, mode, debug, serviceName, javaHandlerDistro, existingLoaderValue } = this.options;
|
|
139
|
+
const webServer = mode === types_1.OdigosInstrumentationMode.WEB_SERVER;
|
|
140
|
+
const env = {
|
|
141
|
+
[ENV_SERVICE_NAME]: serviceName ?? defaultServiceName(fn),
|
|
142
|
+
[collector_config_1.ENV_COLLECTOR_CONFIG_URI]: this.collectorConfig,
|
|
143
|
+
[ENV_IAC_MARKER]: JSON.stringify({ v: 1, source: 'cdk', version: layers_1.ODIGOS_VERSION || 'unreleased' }),
|
|
144
|
+
};
|
|
145
|
+
if (webServer) {
|
|
146
|
+
// No exec wrapper: the Lambda Web Adapter owns it, and overwriting it stops the function serving.
|
|
147
|
+
Object.assign(env, (0, runtime_1.webServerEnv)(language, existingLoaderValue));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
env[ENV_EXEC_WRAPPER] = (0, runtime_1.execWrapperFor)(language, javaHandlerDistro);
|
|
151
|
+
if (debug) {
|
|
152
|
+
env[ENV_OTEL_LOG_LEVEL] = 'debug';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Suppress the signals the destination does not accept. A signal with no collector pipeline is refused
|
|
156
|
+
// at the receiver on every batch, so telling the SDK not to produce it is the half that stops the
|
|
157
|
+
// error loop; the pipeline being absent is the half that stops the export.
|
|
158
|
+
const overrides = [
|
|
159
|
+
[collector_config_1.ENV_TRACES_EXPORTER, (0, collector_config_1.exporterOverrideFor)((0, collector_config_1.signalEnabled)(destination.traces))],
|
|
160
|
+
[collector_config_1.ENV_METRICS_EXPORTER, (0, collector_config_1.exporterOverrideFor)((0, collector_config_1.signalEnabled)(destination.metrics))],
|
|
161
|
+
[collector_config_1.ENV_LOGS_EXPORTER, (0, collector_config_1.exporterOverrideFor)((0, collector_config_1.signalEnabled)(destination.logs))],
|
|
162
|
+
];
|
|
163
|
+
for (const [name, value] of overrides) {
|
|
164
|
+
if (value !== undefined) {
|
|
165
|
+
env[name] = value;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return env;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.OdigosLambdaInstrumentation = OdigosLambdaInstrumentation;
|
|
172
|
+
_a = JSII_RTTI_SYMBOL_1;
|
|
173
|
+
OdigosLambdaInstrumentation[_a] = { fqn: "@odigos/aws-cdk.OdigosLambdaInstrumentation", version: "0.0.0" };
|
|
174
|
+
/**
|
|
175
|
+
* Applies Odigos instrumentation to every `lambda.Function` in a scope.
|
|
176
|
+
*
|
|
177
|
+
* ```ts
|
|
178
|
+
* Aspects.of(stack).add(new OdigosInstrumentationAspect(stack, {
|
|
179
|
+
* destination: { endpoint: 'otlp.example.com:4317' },
|
|
180
|
+
* }));
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* `skipUnsupportedRuntimes` defaults to `true` here, unlike the construct: an aspect visits every function
|
|
184
|
+
* in the scope, including ones whose runtime has no OpenTelemetry layer, and failing the whole synth
|
|
185
|
+
* because a stack happens to contain one Go function is not useful. Each skip is reported as a synth
|
|
186
|
+
* warning, so it is visible rather than silent.
|
|
187
|
+
*
|
|
188
|
+
* The aspect instruments what exists in the tree when it runs. A function added by a later aspect is not
|
|
189
|
+
* visited; use the construct directly for those.
|
|
190
|
+
*/
|
|
191
|
+
class OdigosInstrumentationAspect {
|
|
192
|
+
/**
|
|
193
|
+
* @param scope where the shared layer constructs are created. Usually the same scope the aspect is
|
|
194
|
+
* applied to. It is a separate argument from the visited nodes because the layer (and, in `IN_ACCOUNT`
|
|
195
|
+
* mode, the nested SAR application) is created once and shared by every function the aspect visits.
|
|
196
|
+
*/
|
|
197
|
+
constructor(scope, props) {
|
|
198
|
+
this.instrumentation = new OdigosLambdaInstrumentation(scope, 'OdigosInstrumentationAspect', {
|
|
199
|
+
skipUnsupportedRuntimes: true,
|
|
200
|
+
...props,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
visit(node) {
|
|
204
|
+
if (node instanceof lambda.Function) {
|
|
205
|
+
this.instrumentation.instrument(node);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.OdigosInstrumentationAspect = OdigosInstrumentationAspect;
|
|
210
|
+
_b = JSII_RTTI_SYMBOL_1;
|
|
211
|
+
OdigosInstrumentationAspect[_b] = { fqn: "@odigos/aws-cdk.OdigosInstrumentationAspect", version: "0.0.0" };
|
|
212
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdHJ1bWVudGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2luc3RydW1lbnRhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQUEwRDtBQUMxRCxpREFBaUQ7QUFDakQsMkNBQW1EO0FBQ25ELHlEQVE0QjtBQUM1QiwrQ0FBb0Q7QUFDcEQscURBQXVEO0FBQ3ZELHVDQUE4RTtBQUM5RSxtQ0FLaUI7QUFFakIsMkVBQTJFO0FBQzNFLE1BQU0sZ0JBQWdCLEdBQUcseUJBQXlCLENBQUM7QUFDbkQsa0VBQWtFO0FBQ2xFLE1BQU0sZ0JBQWdCLEdBQUcsbUJBQW1CLENBQUM7QUFDN0MsMkZBQTJGO0FBQzNGLE1BQU0sa0JBQWtCLEdBQUcsZ0JBQWdCLENBQUM7QUFFNUM7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQztBQUVwQzs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxTQUFTLGtCQUFrQixDQUFDLEVBQW1CO0lBQzdDLE1BQU0sUUFBUSxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDdkQsT0FBTyxPQUFPLFFBQVEsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7QUFDOUQsQ0FBQztBQTZHRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2Qkc7QUFDSCxNQUFhLDJCQUE0QixTQUFRLHNCQUFTO0lBTXhELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBdUM7UUFDL0UsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUhGLGlCQUFZLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUtoRCxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNyQixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksb0NBQW1CLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxXQUFXLElBQUkseUJBQWlCLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFcEcsaUdBQWlHO1FBQ2pHLHdEQUF3RDtRQUN4RCxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUEsd0NBQXFCLEVBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRWhFLEtBQUssTUFBTSxFQUFFLElBQUksS0FBSyxDQUFDLFNBQVMsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUN2QyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3RCLENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksVUFBVSxDQUFDLEVBQW1CO1FBQ25DLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ3pCLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUMvQixPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ3BDLE1BQU0sUUFBUSxHQUFHLElBQUEsNkJBQW1CLEVBQUMsV0FBVyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2QsTUFBTSxPQUFPLEdBQ1gsb0JBQW9CLFdBQVcsc0NBQXNDO2dCQUNyRSw4R0FBOEcsQ0FBQztZQUNqSCxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztnQkFDekMseUJBQVcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsWUFBWSxDQUFDLG9DQUFvQyxFQUFFLEdBQUcsT0FBTyxZQUFZLENBQUMsQ0FBQztnQkFDOUYsT0FBTztZQUNULENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsT0FBTyx3REFBd0QsQ0FBQyxDQUFDO1FBQ3RGLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUUzQixNQUFNLFlBQVksR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztRQUMxQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDekYsRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVwQixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDOUUsRUFBRSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDakMsQ0FBQztJQUNILENBQUM7SUFFRCw4Q0FBOEM7SUFDdkMsYUFBYSxDQUFDLFNBQTRCO1FBQy9DLEtBQUssTUFBTSxFQUFFLElBQUksU0FBUyxFQUFFLENBQUM7WUFDM0IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN0QixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSyxjQUFjLENBQUMsRUFBbUIsRUFBRSxRQUFnQjtRQUMxRCxNQUFNLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLG1CQUFtQixFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUN2RyxNQUFNLFNBQVMsR0FBRyxJQUFJLEtBQUssaUNBQXlCLENBQUMsVUFBVSxDQUFDO1FBRWhFLE1BQU0sR0FBRyxHQUE4QjtZQUNyQyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsV0FBVyxJQUFJLGtCQUFrQixDQUFDLEVBQUUsQ0FBQztZQUN6RCxDQUFDLDJDQUF3QixDQUFDLEVBQUUsSUFBSSxDQUFDLGVBQWU7WUFDaEQsQ0FBQyxjQUFjLENBQUMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSx1QkFBYyxJQUFJLFlBQVksRUFBRSxDQUFDO1NBQ25HLENBQUM7UUFFRixJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQ2Qsa0dBQWtHO1lBQ2xHLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLElBQUEsc0JBQVksRUFBQyxRQUFRLEVBQUUsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO1FBQ2xFLENBQUM7YUFBTSxDQUFDO1lBQ04sR0FBRyxDQUFDLGdCQUFnQixDQUFDLEdBQUcsSUFBQSx3QkFBYyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3BFLElBQUksS0FBSyxFQUFFLENBQUM7Z0JBQ1YsR0FBRyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsT0FBTyxDQUFDO1lBQ3BDLENBQUM7UUFDSCxDQUFDO1FBRUQsdUdBQXVHO1FBQ3ZHLGtHQUFrRztRQUNsRywyRUFBMkU7UUFDM0UsTUFBTSxTQUFTLEdBQXdDO1lBQ3JELENBQUMsc0NBQW1CLEVBQUUsSUFBQSxzQ0FBbUIsRUFBQyxJQUFBLGdDQUFhLEVBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDN0UsQ0FBQyx1Q0FBb0IsRUFBRSxJQUFBLHNDQUFtQixFQUFDLElBQUEsZ0NBQWEsRUFBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUMvRSxDQUFDLG9DQUFpQixFQUFFLElBQUEsc0NBQW1CLEVBQUMsSUFBQSxnQ0FBYSxFQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1NBQzFFLENBQUM7UUFDRixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksU0FBUyxFQUFFLENBQUM7WUFDdEMsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3hCLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7WUFDcEIsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7O0FBekdILGtFQTBHQzs7O0FBT0Q7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFhLDJCQUEyQjtJQUd0Qzs7OztPQUlHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEtBQXVDO1FBQ25FLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSwyQkFBMkIsQ0FBQyxLQUFLLEVBQUUsNkJBQTZCLEVBQUU7WUFDM0YsdUJBQXVCLEVBQUUsSUFBSTtZQUM3QixHQUFHLEtBQUs7U0FDVCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLElBQWdCO1FBQzNCLElBQUksSUFBSSxZQUFZLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QyxDQUFDO0lBQ0gsQ0FBQzs7QUFuQkgsa0VBb0JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQW5ub3RhdGlvbnMsIElBc3BlY3QsIFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQge1xuICBFTlZfQ09MTEVDVE9SX0NPTkZJR19VUkksXG4gIEVOVl9MT0dTX0VYUE9SVEVSLFxuICBFTlZfTUVUUklDU19FWFBPUlRFUixcbiAgRU5WX1RSQUNFU19FWFBPUlRFUixcbiAgZXhwb3J0ZXJPdmVycmlkZUZvcixcbiAgcmVuZGVyQ29sbGVjdG9yQ29uZmlnLFxuICBzaWduYWxFbmFibGVkLFxufSBmcm9tICcuL2NvbGxlY3Rvci1jb25maWcnO1xuaW1wb3J0IHsgT0RJR09TX1ZFUlNJT04gfSBmcm9tICcuL2dlbmVyYXRlZC9sYXllcnMnO1xuaW1wb3J0IHsgT2RpZ29zTGF5ZXJSZXNvbHZlciB9IGZyb20gJy4vbGF5ZXItcmVzb2x2ZXInO1xuaW1wb3J0IHsgZXhlY1dyYXBwZXJGb3IsIGxhbmd1YWdlRnJvbVJ1bnRpbWUsIHdlYlNlcnZlckVudiB9IGZyb20gJy4vcnVudGltZSc7XG5pbXBvcnQge1xuICBPZGlnb3NEZXN0aW5hdGlvbixcbiAgT2RpZ29zSW5zdHJ1bWVudGF0aW9uTW9kZSxcbiAgT2RpZ29zSmF2YUhhbmRsZXJEaXN0cm8sXG4gIE9kaWdvc0xheWVyU291cmNlLFxufSBmcm9tICcuL3R5cGVzJztcblxuLyoqIGBBV1NfTEFNQkRBX0VYRUNfV1JBUFBFUmAg4oCUIHRoZSBsYXllcidzIGVudHJ5IHBvaW50IGluIGhhbmRsZXIgbW9kZS4gKi9cbmNvbnN0IEVOVl9FWEVDX1dSQVBQRVIgPSAnQVdTX0xBTUJEQV9FWEVDX1dSQVBQRVInO1xuLyoqIFNlcnZpY2UgbmFtZSByZXBvcnRlZCBvbiBldmVyeSBzcGFuLCBtZXRyaWMgYW5kIGxvZyByZWNvcmQuICovXG5jb25zdCBFTlZfU0VSVklDRV9OQU1FID0gJ09URUxfU0VSVklDRV9OQU1FJztcbi8qKiBSYWlzZXMgaW4tZnVuY3Rpb24gT3BlblRlbGVtZXRyeSB2ZXJib3NpdHkgaW50byB0aGUgZnVuY3Rpb24ncyBDbG91ZFdhdGNoIGxvZyBncm91cC4gKi9cbmNvbnN0IEVOVl9PVEVMX0xPR19MRVZFTCA9ICdPVEVMX0xPR19MRVZFTCc7XG5cbi8qKlxuICogTWFya2VyIHJlY29yZGluZyB0aGF0IHRoaXMgZnVuY3Rpb24gd2FzIGluc3RydW1lbnRlZCBieSBJYUMsIGFuZCBieSB3aGljaCB2ZXJzaW9uLlxuICpcbiAqIERlbGliZXJhdGVseSBOT1QgYE9ESUdPU19NQU5BR0VEYC4gVGhhdCB2YXJpYWJsZSBpcyB0aGUgY29ubmVjdG9yJ3MgT1dORVJTSElQIFBST09GOiBhIGZ1bmN0aW9uXG4gKiBjYXJyeWluZyBpdCBpcyBvbmUgdGhlIGNvbm5lY3RvciBiZWxpZXZlcyBpdCBpbnN0cnVtZW50ZWQsIHdob3NlIGVudmlyb25tZW50IGl0IHdpbGwgY29udmVyZ2Ugb24gZXZlcnlcbiAqIHJlY29uY2lsZSBhbmQgc3RyaXAgb24gcm9sbGJhY2sg4oCUIHVzaW5nIGEgc25hcHNob3Qgb2YgXCJ0aGUgY3VzdG9tZXIncyBvcmlnaW5hbCB2YWx1ZXNcIiB0aGF0IGEgQ0RLXG4gKiBkZXBsb3ltZW50IG5ldmVyIHdyb3RlLiBTZXR0aW5nIGl0IGhlcmUgd291bGQgaGFuZCB0aGUgY29ubmVjdG9yIGEgZnVuY3Rpb24gaXQgZG9lcyBub3Qgb3duLCB3aXRoIGFcbiAqIHNuYXBzaG90IGRlc2NyaWJpbmcgYSBzdGF0ZSB0aGF0IG5ldmVyIGV4aXN0ZWQuXG4gKlxuICogVGhpcyB2YXJpYWJsZSBpcyBpbmZvcm1hdGlvbmFsIG9ubHkuIE5vdGhpbmcgcmVhZHMgaXQuXG4gKi9cbmNvbnN0IEVOVl9JQUNfTUFSS0VSID0gJ09ESUdPU19JQUMnO1xuXG4vKipcbiAqIFRoZSBzZXJ2aWNlIGEgZnVuY3Rpb24gcmVwb3J0cyBhcywgd2hlbiB0aGUgY2FsbGVyIGhhcyBub3QgbmFtZWQgb25lLlxuICpcbiAqIE5PVCBgZm4uZnVuY3Rpb25OYW1lYC4gRm9yIGEgZnVuY3Rpb24gd2hvc2UgcGh5c2ljYWwgbmFtZSBDbG91ZEZvcm1hdGlvbiBnZW5lcmF0ZXMsIHRoYXQgcHJvcGVydHkgaXMgYVxuICogYFJlZmAgdG8gdGhlIGZ1bmN0aW9uIGl0c2VsZiDigJQgcHV0dGluZyBpdCBpbiB0aGUgZnVuY3Rpb24ncyBvd24gZW52aXJvbm1lbnQgbWFrZXMgdGhlIHJlc291cmNlIGRlcGVuZFxuICogb24gaXRzIG93biBjcmVhdGlvbiwgYW5kIENsb3VkRm9ybWF0aW9uIHJlamVjdHMgdGhlIHRlbXBsYXRlIHdpdGggYSBkZXBlbmRlbmN5IGN5Y2xlLiBFdmVyeVxuICogaW5zdHJ1bWVudGVkIGZ1bmN0aW9uIHdvdWxkIGZhaWwgdG8gZGVwbG95LCBhdCBkZXBsb3kgdGltZSByYXRoZXIgdGhhbiBzeW50aCB0aW1lLlxuICpcbiAqIFNvOiB1c2UgdGhlIHBoeXNpY2FsIG5hbWUgd2hlbiB0aGUgY2FsbGVyIHNldCBvbmUgZXhwbGljaXRseSAoYHJlc29sdmVgIHlpZWxkcyBhIGxpdGVyYWwgc3RyaW5nIGZvciBhXG4gKiBrbm93biBwaHlzaWNhbCBuYW1lLCBhbmQgYSBgUmVmYCBvYmplY3Qgb3RoZXJ3aXNlKSwgYW5kIG90aGVyd2lzZSBmYWxsIGJhY2sgdG8gdGhlIGNvbnN0cnVjdCBpZCwgd2hpY2hcbiAqIGlzIHdoYXQgdGhlIGZ1bmN0aW9uIGlzIGNhbGxlZCBpbiB0aGUgY29kZSBhbmQgbmVlZHMgbm8gcmVmZXJlbmNlIGF0IGFsbC5cbiAqXG4gKiBUaGUgY29ubmVjdG9yIHJlcG9ydHMgdGhlIHJlYWwgQVdTIGZ1bmN0aW9uIG5hbWUgZm9yIHRoZSBmdW5jdGlvbnMgSVQgaW5zdHJ1bWVudHMuIEEgZnVuY3Rpb24gd2l0aCBhXG4gKiBnZW5lcmF0ZWQgcGh5c2ljYWwgbmFtZSB0aGVyZWZvcmUgcmVwb3J0cyBkaWZmZXJlbnRseSB1bmRlciB0aGUgdHdvIHBhdGhzIOKAlCBwYXNzIGBzZXJ2aWNlTmFtZWBcbiAqIGV4cGxpY2l0bHkgaWYgdGhhdCBtYXR0ZXJzLlxuICovXG5mdW5jdGlvbiBkZWZhdWx0U2VydmljZU5hbWUoZm46IGxhbWJkYS5GdW5jdGlvbik6IHN0cmluZyB7XG4gIGNvbnN0IHJlc29sdmVkID0gU3RhY2sub2YoZm4pLnJlc29sdmUoZm4uZnVuY3Rpb25OYW1lKTtcbiAgcmV0dXJuIHR5cGVvZiByZXNvbHZlZCA9PT0gJ3N0cmluZycgPyByZXNvbHZlZCA6IGZuLm5vZGUuaWQ7XG59XG5cbi8qKlxuICogT3B0aW9ucyBzaGFyZWQgYnkgdGhlIGNvbnN0cnVjdCBhbmQgdGhlIGFzcGVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPZGlnb3NJbnN0cnVtZW50YXRpb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZXJlIHRoZSBpbi1MYW1iZGEgY29sbGVjdG9yIGV4cG9ydHMgdG8uXG4gICAqL1xuICByZWFkb25seSBkZXN0aW5hdGlvbjogT2RpZ29zRGVzdGluYXRpb247XG5cbiAgLyoqXG4gICAqIFdoZXJlIHRoZSBPZGlnb3MgbGF5ZXIgY29tZXMgZnJvbS5cbiAgICpcbiAgICogQGRlZmF1bHQgT2RpZ29zTGF5ZXJTb3VyY2UuT0RJR09TX1BVQkxJQ1xuICAgKi9cbiAgcmVhZG9ubHkgbGF5ZXJTb3VyY2U/OiBPZGlnb3NMYXllclNvdXJjZTtcblxuICAvKipcbiAgICogSGFuZGxlciBtb2RlIG9yIHdlYi1zZXJ2ZXIgKExhbWJkYSBXZWIgQWRhcHRlcikgbW9kZS5cbiAgICpcbiAgICogVGhlcmUgaXMgbm8gYXV0by1kZXRlY3Rpb24sIGFuZCB0aGF0IGlzIGRlbGliZXJhdGUgcmF0aGVyIHRoYW4gYW4gb21pc3Npb246IGRldGVjdGluZyB0aGUgd2ViIGFkYXB0ZXJcbiAgICogbWVhbnMgaW5zcGVjdGluZyB0aGUgZnVuY3Rpb24ncyBvdGhlciBsYXllcnMsIHdoaWNoIGF0IHN5bnRoIHRpbWUgYXJlIGZyZXF1ZW50bHkgdW5yZXNvbHZlZCB0b2tlbnMuXG4gICAqIEEgZGV0ZWN0b3IgdGhhdCBpcyByaWdodCBtb3N0IG9mIHRoZSB0aW1lIHdvdWxkIHNpbGVudGx5IGJyZWFrIHRoZSBmdW5jdGlvbnMgaXQgZ290IHdyb25nLlxuICAgKlxuICAgKiBAZGVmYXVsdCBPZGlnb3NJbnN0cnVtZW50YXRpb25Nb2RlLkhBTkRMRVJcbiAgICovXG4gIHJlYWRvbmx5IG1vZGU/OiBPZGlnb3NJbnN0cnVtZW50YXRpb25Nb2RlO1xuXG4gIC8qKlxuICAgKiBXaGljaCBvZiB0aGUgSmF2YSBsYXllcidzIGZvdXIgd3JhcHBlciBzY3JpcHRzIHRvIHVzZS4gSWdub3JlZCBmb3Igb3RoZXIgbGFuZ3VhZ2VzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBPZGlnb3NKYXZhSGFuZGxlckRpc3Ryby5PVEVMX0hBTkRMRVJcbiAgICovXG4gIHJlYWRvbmx5IGphdmFIYW5kbGVyRGlzdHJvPzogT2RpZ29zSmF2YUhhbmRsZXJEaXN0cm87XG5cbiAgLyoqXG4gICAqIGBPVEVMX1NFUlZJQ0VfTkFNRWAgZm9yIGV2ZXJ5IGZ1bmN0aW9uIHRoaXMgaW5zdHJ1bWVudHMuXG4gICAqXG4gICAqIFVzdWFsbHkgd3JvbmcgdG8gc2V0IHdoZW4gaW5zdHJ1bWVudGluZyBtb3JlIHRoYW4gb25lIGZ1bmN0aW9uIOKAlCB0aGV5IHdvdWxkIGFsbCByZXBvcnQgYXMgdGhlIHNhbWVcbiAgICogc2VydmljZS5cbiAgICpcbiAgICogTGVmdCB1bnNldCwgYSBmdW5jdGlvbiByZXBvcnRzIGFzIGl0cyBleHBsaWNpdGx5LXNldCBwaHlzaWNhbCBuYW1lIGlmIGl0IGhhcyBvbmUsIGFuZCBvdGhlcndpc2UgYXNcbiAgICogaXRzIGNvbnN0cnVjdCBpZC4gSXQgZGVsaWJlcmF0ZWx5IGRvZXMgbm90IGRlZmF1bHQgdG8gdGhlIGdlbmVyYXRlZCBwaHlzaWNhbCBuYW1lOiB0aGF0IHZhbHVlIGlzIGFcbiAgICogYFJlZmAgdG8gdGhlIGZ1bmN0aW9uIGl0c2VsZiwgYW5kIGEgZnVuY3Rpb24gcmVmZXJlbmNpbmcgaXRzZWxmIGluIGl0cyBvd24gZW52aXJvbm1lbnQgaXMgYVxuICAgKiBDbG91ZEZvcm1hdGlvbiBkZXBlbmRlbmN5IGN5Y2xlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRoZSBmdW5jdGlvbidzIHBoeXNpY2FsIG5hbWUgaWYgZXhwbGljaXRseSBzZXQsIG90aGVyd2lzZSBpdHMgY29uc3RydWN0IGlkXG4gICAqL1xuICByZWFkb25seSBzZXJ2aWNlTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogUmFpc2UgaW4tZnVuY3Rpb24gT3BlblRlbGVtZXRyeSB2ZXJib3NpdHkgKGBPVEVMX0xPR19MRVZFTD1kZWJ1Z2ApLlxuICAgKlxuICAgKiBUaGUgbGF5ZXIsIFNESyBhbmQgY29sbGVjdG9yIHRoZW4gZW1pdCBzcGFuIGFuZCBPVExQLWV4cG9ydCBkaWFnbm9zdGljcyBpbnRvIHRoZSBmdW5jdGlvbidzIENsb3VkV2F0Y2hcbiAgICogbG9nIGdyb3VwLiBVc2VmdWwgd2hpbGUgd2lyaW5nIHVwIGEgZGVzdGluYXRpb24sIGV4cGVuc2l2ZSB0byBsZWF2ZSBvbi5cbiAgICpcbiAgICogSGFzIG5vIGVmZmVjdCBpbiB3ZWItc2VydmVyIG1vZGUsIG1hdGNoaW5nIHRoZSBjb25uZWN0b3IsIHdoaWNoIG5ldmVyIHNldHMgYSBsb2cgbGV2ZWwgdGhlcmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkZWJ1Zz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEF0dGFjaCB0aGlzIGxheWVyIGluc3RlYWQgb2YgcmVzb2x2aW5nIG9uZS4gT3ZlcnJpZGVzIGBsYXllclNvdXJjZWAgZW50aXJlbHkuXG4gICAqXG4gICAqIFRoZSBlc2NhcGUgaGF0Y2ggZm9yIGEgbGF5ZXIgbWlycm9yZWQgaW50byBhIHByaXZhdGUgcmVnaXN0cnkgb3IgYW4gaW50ZXJuYWwgYWNjb3VudC4gVGhlIGxheWVyIG11c3RcbiAgICogaGF2ZSB0aGUgc2FtZSBjb250ZW50cyBhcyB0aGUgT2RpZ29zIG9uZSDigJQgdGhlIGVudmlyb25tZW50IHNldCBoZXJlIGFzc3VtZXMgaXRzIGV4YWN0IHNjcmlwdCBsYXlvdXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gcmVzb2x2ZWQgZnJvbSBsYXllclNvdXJjZVxuICAgKi9cbiAgcmVhZG9ubHkgbGF5ZXJWZXJzaW9uPzogbGFtYmRhLklMYXllclZlcnNpb247XG5cbiAgLyoqXG4gICAqIFRoZSB2YWx1ZSB0aGUgZnVuY3Rpb24gYWxyZWFkeSBuZWVkcyBpbiBpdHMgbGFuZ3VhZ2UgbG9hZGVyIHZhcmlhYmxlIChgTk9ERV9PUFRJT05TYCxcbiAgICogYEpBVkFfVE9PTF9PUFRJT05TYCBvciBgUFlUSE9OUEFUSGApLCB3aGljaCB0aGUgT2RpZ29zIGxvYWRlciBpcyBqb2luZWQgdG8gcmF0aGVyIHRoYW4gcmVwbGFjaW5nLlxuICAgKlxuICAgKiBPbmx5IHVzZWQgaW4gd2ViLXNlcnZlciBtb2RlLiBJdCBoYXMgdG8gYmUgcGFzc2VkIGV4cGxpY2l0bHkgYmVjYXVzZSBDREsncyBgbGFtYmRhLkZ1bmN0aW9uYCBleHBvc2VzXG4gICAqIG5vIHdheSB0byByZWFkIGJhY2sgYW4gZW52aXJvbm1lbnQgdmFyaWFibGUgc2V0IGVsc2V3aGVyZSBpbiB0aGUgYXBwIOKAlCBhbiBvbWl0dGVkIHZhbHVlIGhlcmUgaXNcbiAgICogc2lsZW50bHkgb3ZlcndyaXR0ZW4sIHdoaWNoIGZvciBgTk9ERV9PUFRJT05TYCBjYW4gbWVhbiBsb3NpbmcgYSBmbGFnIHRoZSBhcHAgbmVlZHMgdG8gYm9vdC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgbG9hZGVyIHZhcmlhYmxlIGlzIHNldCB0byB0aGUgT2RpZ29zIHZhbHVlIGFsb25lXG4gICAqL1xuICByZWFkb25seSBleGlzdGluZ0xvYWRlclZhbHVlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTa2lwIGZ1bmN0aW9ucyB3aG9zZSBydW50aW1lIGhhcyBubyBPcGVuVGVsZW1ldHJ5IExhbWJkYSBsYXllciBpbnN0ZWFkIG9mIHRocm93aW5nLlxuICAgKlxuICAgKiBgZG90bmV0KmAgYW5kIGBwcm92aWRlZC4qYCAoR28sIGN1c3RvbSBydW50aW1lcykgaGF2ZSBubyBsYW5ndWFnZSBsYXllciB1cHN0cmVhbS4gRXhwbGljaXRseVxuICAgKiBpbnN0cnVtZW50aW5nIG9uZSBpcyBhIG1pc3Rha2Ugd29ydGggZmFpbGluZyBvbjsgc3dlZXBpbmcgYSB3aG9sZSBzdGFjayB3aXRoIHRoZSBhc3BlY3QgYW5kIGhpdHRpbmdcbiAgICogb25lIGlzIG5vdCwgd2hpY2ggaXMgd2h5IHRoZSBhc3BlY3QgZGVmYXVsdHMgdGhpcyB0byBgdHJ1ZWAgYW5kIHRoZSBjb25zdHJ1Y3QgdG8gYGZhbHNlYC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHNraXBVbnN1cHBvcnRlZFJ1bnRpbWVzPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBQcm9wcyBmb3Ige0BsaW5rIE9kaWdvc0xhbWJkYUluc3RydW1lbnRhdGlvbn0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT2RpZ29zTGFtYmRhSW5zdHJ1bWVudGF0aW9uUHJvcHMgZXh0ZW5kcyBPZGlnb3NJbnN0cnVtZW50YXRpb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIEZ1bmN0aW9ucyB0byBpbnN0cnVtZW50IG9uIGNvbnN0cnVjdGlvbi4gTW9yZSBjYW4gYmUgYWRkZWQgd2l0aCBgaW5zdHJ1bWVudCgpYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbnM/OiBsYW1iZGEuRnVuY3Rpb25bXTtcbn1cblxuLyoqXG4gKiBJbnN0cnVtZW50cyBBV1MgTGFtYmRhIGZ1bmN0aW9ucyB3aXRoIHRoZSBPZGlnb3MgT3BlblRlbGVtZXRyeSBsYXllci5cbiAqXG4gKiBgYGB0c1xuICogY29uc3Qgb2RpZ29zID0gbmV3IE9kaWdvc0xhbWJkYUluc3RydW1lbnRhdGlvbih0aGlzLCAnT2RpZ29zJywge1xuICogICBkZXN0aW5hdGlvbjogeyBlbmRwb2ludDogJ290bHAuZXhhbXBsZS5jb206NDMxNycgfSxcbiAqICAgZnVuY3Rpb25zOiBbYXBpRm4sIHdvcmtlckZuXSxcbiAqIH0pO1xuICogb2RpZ29zLmluc3RydW1lbnQoYW5vdGhlckZuKTtcbiAqIGBgYFxuICpcbiAqIFdoYXQgaXQgZG9lcyB0byBlYWNoIGZ1bmN0aW9uOiBhdHRhY2hlcyB0aGUgbGF5ZXIgZm9yIHRoZSBmdW5jdGlvbidzIGxhbmd1YWdlIGFuZCBhcmNoaXRlY3R1cmUsIHNldHNcbiAqIGBBV1NfTEFNQkRBX0VYRUNfV1JBUFBFUmAgc28gdGhlIGxheWVyIGxvYWRzIHRoZSBTREssIHNldHMgYE9URUxfU0VSVklDRV9OQU1FYCwgYW5kIGhhbmRzIHRoZSBpbi1MYW1iZGFcbiAqIGNvbGxlY3RvciBpdHMgZW50aXJlIGNvbmZpZ3VyYXRpb24gaW5saW5lIHRocm91Z2ggYE9QRU5URUxFTUVUUllfQ09MTEVDVE9SX0NPTkZJR19VUklgLlxuICpcbiAqIFRoZSBmdW5jdGlvbidzIFNESyBleHBvcnRzIHRvIHRoZSBjb2xsZWN0b3Igb24gbG9jYWxob3N0LCBub3QgdG8geW91ciBkZXN0aW5hdGlvbi4gVGhlIGNvbGxlY3RvclxuICogZm9yd2FyZHMgYWZ0ZXIgdGhlIGhhbmRsZXIgaGFzIGFscmVhZHkgcmV0dXJuZWQsIHNvIGEgc2xvdyBkZXN0aW5hdGlvbiBjb3N0cyBiaWxsZWQgZHVyYXRpb24gcmF0aGVyXG4gKiB0aGFuIGNhbGxlciBsYXRlbmN5LlxuICpcbiAqICMjIERvIG5vdCBhbHNvIGluc3RydW1lbnQgdGhlc2UgZnVuY3Rpb25zIHdpdGggdGhlIGNvbm5lY3RvclxuICpcbiAqIFRoZSBPZGlnb3MgQVdTIGNvbm5lY3RvciBpbnN0cnVtZW50cyBsaXZlIGZ1bmN0aW9ucyBieSBtdXRhdGluZyB0aGVtLCBhbmQgcmVjb25jaWxlcyB0aGVtIGJhY2sgdG8gaXRzXG4gKiBvd24gZGVzaXJlZCBzdGF0ZSBvbiBldmVyeSBwYXNzLiBBIGZ1bmN0aW9uIGluc3RydW1lbnRlZCBoZXJlIGFuZCBhbHNvIGVuYWJsZWQgYXMgYSBjb25uZWN0b3Igc291cmNlXG4gKiBlbmRzIHVwIG93bmVkIGJ5IGJvdGg6IGVhY2ggYGNkayBkZXBsb3lgIHJlYXNzZXJ0cyB0aGUgQ0RLJ3MgZW52aXJvbm1lbnQsIGVhY2ggcmVjb25jaWxlIHJlYXNzZXJ0cyB0aGVcbiAqIGNvbm5lY3RvcidzLCBhbmQgZXZlcnkgcm91bmQgdHJpcCBwdWJsaXNoZXMgYSBuZXcgZnVuY3Rpb24gdmVyc2lvbi5cbiAqXG4gKiBDaG9vc2Ugb25lIHBlciBmdW5jdGlvbi4gVGhpcyBjb25zdHJ1Y3QgbmV2ZXIgc2V0cyB0aGUgY29ubmVjdG9yJ3MgYE9ESUdPU19NQU5BR0VEYCBvd25lcnNoaXAgbWFya2VyLFxuICogc28gYW4gSWFDLWluc3RydW1lbnRlZCBmdW5jdGlvbiBpcyBub3Qgb25lIHRoZSBjb25uZWN0b3Igd2lsbCByb2xsIGJhY2sg4oCUIGJ1dCBpdCB3aWxsIGhhcHBpbHkgdGFrZSBpdFxuICogb3ZlciBpZiB5b3UgZW5hYmxlIGl0IGFzIGEgc291cmNlLlxuICovXG5leHBvcnQgY2xhc3MgT2RpZ29zTGFtYmRhSW5zdHJ1bWVudGF0aW9uIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBPZGlnb3NJbnN0cnVtZW50YXRpb25PcHRpb25zO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc29sdmVyOiBPZGlnb3NMYXllclJlc29sdmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbGxlY3RvckNvbmZpZzogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGluc3RydW1lbnRlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBPZGlnb3NMYW1iZGFJbnN0cnVtZW50YXRpb25Qcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLm9wdGlvbnMgPSBwcm9wcztcbiAgICB0aGlzLnJlc29sdmVyID0gbmV3IE9kaWdvc0xheWVyUmVzb2x2ZXIodGhpcywgcHJvcHMubGF5ZXJTb3VyY2UgPz8gT2RpZ29zTGF5ZXJTb3VyY2UuT0RJR09TX1BVQkxJQyk7XG5cbiAgICAvLyBSZW5kZXJlZCBvbmNlLiBJdCBkZXBlbmRzIG9ubHkgb24gdGhlIGRlc3RpbmF0aW9uLCBhbmQgcmVuZGVyaW5nIGl0IHBlciBmdW5jdGlvbiB3b3VsZCBtYWtlIGFuXG4gICAgLy8gYWNjaWRlbnRhbCBkaWZmZXJlbmNlIGJldHdlZW4gdHdvIGZ1bmN0aW9ucyBwb3NzaWJsZS5cbiAgICB0aGlzLmNvbGxlY3RvckNvbmZpZyA9IHJlbmRlckNvbGxlY3RvckNvbmZpZyhwcm9wcy5kZXN0aW5hdGlvbik7XG5cbiAgICBmb3IgKGNvbnN0IGZuIG9mIHByb3BzLmZ1bmN0aW9ucyA/PyBbXSkge1xuICAgICAgdGhpcy5pbnN0cnVtZW50KGZuKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5zdHJ1bWVudHMgb25lIGZ1bmN0aW9uLiBJZGVtcG90ZW50IOKAlCBpbnN0cnVtZW50aW5nIHRoZSBzYW1lIGZ1bmN0aW9uIHR3aWNlIGlzIGEgbm8tb3AgcmF0aGVyIHRoYW4gYVxuICAgKiBkb3VibGVkIGxvYWRlciB2YWx1ZS5cbiAgICovXG4gIHB1YmxpYyBpbnN0cnVtZW50KGZuOiBsYW1iZGEuRnVuY3Rpb24pOiB2b2lkIHtcbiAgICBjb25zdCBrZXkgPSBmbi5ub2RlLnBhdGg7XG4gICAgaWYgKHRoaXMuaW5zdHJ1bWVudGVkLmhhcyhrZXkpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcnVudGltZU5hbWUgPSBmbi5ydW50aW1lLm5hbWU7XG4gICAgY29uc3QgbGFuZ3VhZ2UgPSBsYW5ndWFnZUZyb21SdW50aW1lKHJ1bnRpbWVOYW1lKTtcbiAgICBpZiAoIWxhbmd1YWdlKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID1cbiAgICAgICAgYE9kaWdvczogcnVudGltZSBcIiR7cnVudGltZU5hbWV9XCIgaGFzIG5vIE9wZW5UZWxlbWV0cnkgTGFtYmRhIGxheWVyIGAgK1xuICAgICAgICAnKHVwc3RyZWFtIHB1Ymxpc2hlcyBsYXllcnMgZm9yIHB5dGhvbiwgbm9kZWpzLCBqYXZhIGFuZCBydWJ5IG9ubHkpLCBzbyB0aGlzIGZ1bmN0aW9uIGNhbm5vdCBiZSBpbnN0cnVtZW50ZWQuJztcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuc2tpcFVuc3VwcG9ydGVkUnVudGltZXMpIHtcbiAgICAgICAgQW5ub3RhdGlvbnMub2YoZm4pLmFkZFdhcm5pbmdWMignQG9kaWdvcy9hd3MtY2RrOnVuc3VwcG9ydGVkUnVudGltZScsIGAke21lc3NhZ2V9IFNraXBwaW5nLmApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bWVzc2FnZX0gU2V0IHNraXBVbnN1cHBvcnRlZFJ1bnRpbWVzOiB0cnVlIHRvIHNraXAgaXQgaW5zdGVhZC5gKTtcbiAgICB9XG5cbiAgICB0aGlzLmluc3RydW1lbnRlZC5hZGQoa2V5KTtcblxuICAgIGNvbnN0IGFyY2hpdGVjdHVyZSA9IGZuLmFyY2hpdGVjdHVyZS5uYW1lO1xuICAgIGNvbnN0IGxheWVyID0gdGhpcy5vcHRpb25zLmxheWVyVmVyc2lvbiA/PyB0aGlzLnJlc29sdmVyLnJlc29sdmUobGFuZ3VhZ2UsIGFyY2hpdGVjdHVyZSk7XG4gICAgZm4uYWRkTGF5ZXJzKGxheWVyKTtcblxuICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyh0aGlzLmVudmlyb25tZW50Rm9yKGZuLCBsYW5ndWFnZSkpKSB7XG4gICAgICBmbi5hZGRFbnZpcm9ubWVudChuYW1lLCB2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEluc3RydW1lbnRzIGV2ZXJ5IGZ1bmN0aW9uIGluIHRoZSBsaXN0LiAqL1xuICBwdWJsaWMgaW5zdHJ1bWVudEFsbChmdW5jdGlvbnM6IGxhbWJkYS5GdW5jdGlvbltdKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBmbiBvZiBmdW5jdGlvbnMpIHtcbiAgICAgIHRoaXMuaW5zdHJ1bWVudChmbik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBlbnZpcm9ubWVudCBhcHBsaWVkIHRvIG9uZSBmdW5jdGlvbi5cbiAgICpcbiAgICogTWlycm9ycyBgYXBwbHlIYW5kbGVyRW52YCAvIGBhcHBseVdlYlNlcnZlckVudmAgaW4gdGhlIGNvbm5lY3RvciwgaW5jbHVkaW5nIHdoYXQgaXMgZGVsaWJlcmF0ZWx5IE5PVFxuICAgKiBzZXQ6IGBPVEVMX0VYUE9SVEVSX09UTFBfRU5EUE9JTlRgIHN0YXlzIHVuc2V0IHNvIHRoZSBTREsga2VlcHMgZXhwb3J0aW5nIHRvIHRoZSBpbi1MYW1iZGEgY29sbGVjdG9yXG4gICAqIG9uIGxvY2FsaG9zdCByYXRoZXIgdGhhbiBibG9ja2luZyB0aGUgaW52b2NhdGlvbiBvbiB0aGUgcmVtb3RlIGRlc3RpbmF0aW9uLCBhbmQgYW4gZW5hYmxlZCBzaWduYWwnc1xuICAgKiBgT1RFTF8qX0VYUE9SVEVSYCBzdGF5cyB1bnNldCBiZWNhdXNlIGBvdGxwYCBpcyBhbHJlYWR5IHRoZSBTREsgZGVmYXVsdC5cbiAgICovXG4gIHByaXZhdGUgZW52aXJvbm1lbnRGb3IoZm46IGxhbWJkYS5GdW5jdGlvbiwgbGFuZ3VhZ2U6IHN0cmluZyk6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0ge1xuICAgIGNvbnN0IHsgZGVzdGluYXRpb24sIG1vZGUsIGRlYnVnLCBzZXJ2aWNlTmFtZSwgamF2YUhhbmRsZXJEaXN0cm8sIGV4aXN0aW5nTG9hZGVyVmFsdWUgfSA9IHRoaXMub3B0aW9ucztcbiAgICBjb25zdCB3ZWJTZXJ2ZXIgPSBtb2RlID09PSBPZGlnb3NJbnN0cnVtZW50YXRpb25Nb2RlLldFQl9TRVJWRVI7XG5cbiAgICBjb25zdCBlbnY6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICBbRU5WX1NFUlZJQ0VfTkFNRV06IHNlcnZpY2VOYW1lID8/IGRlZmF1bHRTZXJ2aWNlTmFtZShmbiksXG4gICAgICBbRU5WX0NPTExFQ1RPUl9DT05GSUdfVVJJXTogdGhpcy5jb2xsZWN0b3JDb25maWcsXG4gICAgICBbRU5WX0lBQ19NQVJLRVJdOiBKU09OLnN0cmluZ2lmeSh7IHY6IDEsIHNvdXJjZTogJ2NkaycsIHZlcnNpb246IE9ESUdPU19WRVJTSU9OIHx8ICd1bnJlbGVhc2VkJyB9KSxcbiAgICB9O1xuXG4gICAgaWYgKHdlYlNlcnZlcikge1xuICAgICAgLy8gTm8gZXhlYyB3cmFwcGVyOiB0aGUgTGFtYmRhIFdlYiBBZGFwdGVyIG93bnMgaXQsIGFuZCBvdmVyd3JpdGluZyBpdCBzdG9wcyB0aGUgZnVuY3Rpb24gc2VydmluZy5cbiAgICAgIE9iamVjdC5hc3NpZ24oZW52LCB3ZWJTZXJ2ZXJFbnYobGFuZ3VhZ2UsIGV4aXN0aW5nTG9hZGVyVmFsdWUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZW52W0VOVl9FWEVDX1dSQVBQRVJdID0gZXhlY1dyYXBwZXJGb3IobGFuZ3VhZ2UsIGphdmFIYW5kbGVyRGlzdHJvKTtcbiAgICAgIGlmIChkZWJ1Zykge1xuICAgICAgICBlbnZbRU5WX09URUxfTE9HX0xFVkVMXSA9ICdkZWJ1Zyc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU3VwcHJlc3MgdGhlIHNpZ25hbHMgdGhlIGRlc3RpbmF0aW9uIGRvZXMgbm90IGFjY2VwdC4gQSBzaWduYWwgd2l0aCBubyBjb2xsZWN0b3IgcGlwZWxpbmUgaXMgcmVmdXNlZFxuICAgIC8vIGF0IHRoZSByZWNlaXZlciBvbiBldmVyeSBiYXRjaCwgc28gdGVsbGluZyB0aGUgU0RLIG5vdCB0byBwcm9kdWNlIGl0IGlzIHRoZSBoYWxmIHRoYXQgc3RvcHMgdGhlXG4gICAgLy8gZXJyb3IgbG9vcDsgdGhlIHBpcGVsaW5lIGJlaW5nIGFic2VudCBpcyB0aGUgaGFsZiB0aGF0IHN0b3BzIHRoZSBleHBvcnQuXG4gICAgY29uc3Qgb3ZlcnJpZGVzOiBBcnJheTxbc3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWRdPiA9IFtcbiAgICAgIFtFTlZfVFJBQ0VTX0VYUE9SVEVSLCBleHBvcnRlck92ZXJyaWRlRm9yKHNpZ25hbEVuYWJsZWQoZGVzdGluYXRpb24udHJhY2VzKSldLFxuICAgICAgW0VOVl9NRVRSSUNTX0VYUE9SVEVSLCBleHBvcnRlck92ZXJyaWRlRm9yKHNpZ25hbEVuYWJsZWQoZGVzdGluYXRpb24ubWV0cmljcykpXSxcbiAgICAgIFtFTlZfTE9HU19FWFBPUlRFUiwgZXhwb3J0ZXJPdmVycmlkZUZvcihzaWduYWxFbmFibGVkKGRlc3RpbmF0aW9uLmxvZ3MpKV0sXG4gICAgXTtcbiAgICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZV0gb2Ygb3ZlcnJpZGVzKSB7XG4gICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbnZbbmFtZV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZW52O1xuICB9XG59XG5cbi8qKlxuICogUHJvcHMgZm9yIHtAbGluayBPZGlnb3NJbnN0cnVtZW50YXRpb25Bc3BlY3R9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9kaWdvc0luc3RydW1lbnRhdGlvbkFzcGVjdFByb3BzIGV4dGVuZHMgT2RpZ29zSW5zdHJ1bWVudGF0aW9uT3B0aW9ucyB7fVxuXG4vKipcbiAqIEFwcGxpZXMgT2RpZ29zIGluc3RydW1lbnRhdGlvbiB0byBldmVyeSBgbGFtYmRhLkZ1bmN0aW9uYCBpbiBhIHNjb3BlLlxuICpcbiAqIGBgYHRzXG4gKiBBc3BlY3RzLm9mKHN0YWNrKS5hZGQobmV3IE9kaWdvc0luc3RydW1lbnRhdGlvbkFzcGVjdChzdGFjaywge1xuICogICBkZXN0aW5hdGlvbjogeyBlbmRwb2ludDogJ290bHAuZXhhbXBsZS5jb206NDMxNycgfSxcbiAqIH0pKTtcbiAqIGBgYFxuICpcbiAqIGBza2lwVW5zdXBwb3J0ZWRSdW50aW1lc2AgZGVmYXVsdHMgdG8gYHRydWVgIGhlcmUsIHVubGlrZSB0aGUgY29uc3RydWN0OiBhbiBhc3BlY3QgdmlzaXRzIGV2ZXJ5IGZ1bmN0aW9uXG4gKiBpbiB0aGUgc2NvcGUsIGluY2x1ZGluZyBvbmVzIHdob3NlIHJ1bnRpbWUgaGFzIG5vIE9wZW5UZWxlbWV0cnkgbGF5ZXIsIGFuZCBmYWlsaW5nIHRoZSB3aG9sZSBzeW50aFxuICogYmVjYXVzZSBhIHN0YWNrIGhhcHBlbnMgdG8gY29udGFpbiBvbmUgR28gZnVuY3Rpb24gaXMgbm90IHVzZWZ1bC4gRWFjaCBza2lwIGlzIHJlcG9ydGVkIGFzIGEgc3ludGhcbiAqIHdhcm5pbmcsIHNvIGl0IGlzIHZpc2libGUgcmF0aGVyIHRoYW4gc2lsZW50LlxuICpcbiAqIFRoZSBhc3BlY3QgaW5zdHJ1bWVudHMgd2hhdCBleGlzdHMgaW4gdGhlIHRyZWUgd2hlbiBpdCBydW5zLiBBIGZ1bmN0aW9uIGFkZGVkIGJ5IGEgbGF0ZXIgYXNwZWN0IGlzIG5vdFxuICogdmlzaXRlZDsgdXNlIHRoZSBjb25zdHJ1Y3QgZGlyZWN0bHkgZm9yIHRob3NlLlxuICovXG5leHBvcnQgY2xhc3MgT2RpZ29zSW5zdHJ1bWVudGF0aW9uQXNwZWN0IGltcGxlbWVudHMgSUFzcGVjdCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW5zdHJ1bWVudGF0aW9uOiBPZGlnb3NMYW1iZGFJbnN0cnVtZW50YXRpb247XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBzY29wZSB3aGVyZSB0aGUgc2hhcmVkIGxheWVyIGNvbnN0cnVjdHMgYXJlIGNyZWF0ZWQuIFVzdWFsbHkgdGhlIHNhbWUgc2NvcGUgdGhlIGFzcGVjdCBpc1xuICAgKiBhcHBsaWVkIHRvLiBJdCBpcyBhIHNlcGFyYXRlIGFyZ3VtZW50IGZyb20gdGhlIHZpc2l0ZWQgbm9kZXMgYmVjYXVzZSB0aGUgbGF5ZXIgKGFuZCwgaW4gYElOX0FDQ09VTlRgXG4gICAqIG1vZGUsIHRoZSBuZXN0ZWQgU0FSIGFwcGxpY2F0aW9uKSBpcyBjcmVhdGVkIG9uY2UgYW5kIHNoYXJlZCBieSBldmVyeSBmdW5jdGlvbiB0aGUgYXNwZWN0IHZpc2l0cy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIHByb3BzOiBPZGlnb3NJbnN0cnVtZW50YXRpb25Bc3BlY3RQcm9wcykge1xuICAgIHRoaXMuaW5zdHJ1bWVudGF0aW9uID0gbmV3IE9kaWdvc0xhbWJkYUluc3RydW1lbnRhdGlvbihzY29wZSwgJ09kaWdvc0luc3RydW1lbnRhdGlvbkFzcGVjdCcsIHtcbiAgICAgIHNraXBVbnN1cHBvcnRlZFJ1bnRpbWVzOiB0cnVlLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgdmlzaXQobm9kZTogSUNvbnN0cnVjdCk6IHZvaWQge1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgbGFtYmRhLkZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLmluc3RydW1lbnRhdGlvbi5pbnN0cnVtZW50KG5vZGUpO1xuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as lambda from 'aws-cdk-lib/aws-lambda';
|
|
2
|
+
import { Construct } from 'constructs';
|
|
3
|
+
import { OdigosLayerSource } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Resolves the Odigos layer for a (language, architecture) to an `ILayerVersion`, and caches it so N
|
|
6
|
+
* functions of the same language and architecture share one layer construct — and, in `IN_ACCOUNT` mode,
|
|
7
|
+
* one nested SAR application rather than N copies of the same layer.
|
|
8
|
+
*/
|
|
9
|
+
export declare class OdigosLayerResolver {
|
|
10
|
+
private readonly scope;
|
|
11
|
+
private readonly source;
|
|
12
|
+
private readonly cache;
|
|
13
|
+
constructor(scope: Construct, source: OdigosLayerSource);
|
|
14
|
+
resolve(language: string, architecture: string): lambda.ILayerVersion;
|
|
15
|
+
/**
|
|
16
|
+
* The public layer version Odigos published in this stack's region, resolved from the table baked into
|
|
17
|
+
* this package at build time.
|
|
18
|
+
*
|
|
19
|
+
* A region with no entry throws rather than falling back to another region's ARN, which would not
|
|
20
|
+
* resolve, or to no layer, which would leave the function reporting healthy and exporting nothing.
|
|
21
|
+
*/
|
|
22
|
+
private fromPublicArn;
|
|
23
|
+
/**
|
|
24
|
+
* Deploys the Odigos SAR application into this account as a nested stack and attaches the layer it
|
|
25
|
+
* creates.
|
|
26
|
+
*
|
|
27
|
+
* Pinning `semanticVersion` is what makes this reproducible: a SAR application version is immutable, so
|
|
28
|
+
* the pinned version resolves to the same layer bytes forever. Leaving it unpinned would let a later
|
|
29
|
+
* `cdk deploy` of unchanged code pick up a different layer.
|
|
30
|
+
*/
|
|
31
|
+
private fromSar;
|
|
32
|
+
/** `Python_X8664` — a construct-id-safe suffix that keeps ids stable and readable in the template. */
|
|
33
|
+
private constructSuffix;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The layer name this package attaches, exposed so a stack can assert on it or build an allowlist.
|
|
37
|
+
*
|
|
38
|
+
* Deliberately identical to the name the connector publishes into an account
|
|
39
|
+
* (`store.OdigosLayerNamePrefix` + language + "-" + architecture). That is what lets a function
|
|
40
|
+
* instrumented here and later enabled as a connector source converge: the connector sees the same layer
|
|
41
|
+
* NAME, swaps its own version in rather than attaching a second OpenTelemetry layer, and recognises the
|
|
42
|
+
* layer as one it may manage.
|
|
43
|
+
*/
|
|
44
|
+
export declare function odigosLayerName(language: string, architecture: string): string;
|
|
45
|
+
/** Stable, human-readable construct id fragment for a function. Exported for the aspect. */
|
|
46
|
+
export declare function functionScopeId(fn: Construct): string;
|