@mastra/deployer 0.1.0-alpha.61 → 0.1.0-alpha.62
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/CHANGELOG.md +16 -0
- package/dist/_tsup-dts-rollup.d.ts +11 -0
- package/dist/build/index.d.ts +1 -0
- package/dist/build/index.js +2 -2
- package/dist/bundler/index.js +2 -2
- package/dist/{chunk-XSSW3PB4.js → chunk-3MSZJSZW.js} +16 -10
- package/dist/{chunk-Q3WKR6OZ.js → chunk-E4D6R3B4.js} +113 -1
- package/dist/index.js +5 -5
- package/dist/templates/instrumentation-template.js +85 -0
- package/package.json +3 -3
- package/public/templates/instrumentation-template.js +85 -0
- package/src/build/babel/get-telemetry-config.ts +62 -0
- package/src/build/index.ts +1 -0
- package/src/build/telemetry.ts +76 -0
- package/src/bundler/index.ts +20 -9
- /package/dist/{chunk-I7EFK2FV.js → chunk-VCRMX3ZD.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @mastra/deployer
|
|
2
2
|
|
|
3
|
+
## 0.1.0-alpha.62
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 382f4dc: move telemetry init to instrumentation.mjs file in build directory
|
|
8
|
+
- Updated dependencies [016493a]
|
|
9
|
+
- Updated dependencies [382f4dc]
|
|
10
|
+
- Updated dependencies [176bc42]
|
|
11
|
+
- Updated dependencies [d68b532]
|
|
12
|
+
- Updated dependencies [fe3dcb0]
|
|
13
|
+
- Updated dependencies [e448a26]
|
|
14
|
+
- Updated dependencies [fd75f3c]
|
|
15
|
+
- Updated dependencies [ccf115c]
|
|
16
|
+
- Updated dependencies [a221426]
|
|
17
|
+
- @mastra/core@0.2.0-alpha.110
|
|
18
|
+
|
|
3
19
|
## 0.1.0-alpha.61
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -54,6 +54,7 @@ export declare abstract class Bundler extends MastraBundler {
|
|
|
54
54
|
protected outputDir: string;
|
|
55
55
|
constructor(name: string, component?: 'BUNDLER' | 'DEPLOYER');
|
|
56
56
|
prepare(outputDirectory: string): Promise<void>;
|
|
57
|
+
writeInstrumentationFile(outputDirectory: string): Promise<void>;
|
|
57
58
|
writePackageJson(outputDirectory: string, dependencies: Map<string, string>): Promise<void>;
|
|
58
59
|
protected createBundler(inputOptions: InputOptions, outputOptions: Partial<OutputOptions> & {
|
|
59
60
|
dir: string;
|
|
@@ -307,6 +308,10 @@ export declare function queryVectors(c: Context): Promise<Response>;
|
|
|
307
308
|
|
|
308
309
|
export declare function removeAllExceptDeployer(): babel_2.PluginObj;
|
|
309
310
|
|
|
311
|
+
export declare function removeAllExceptTelemetryConfig(result: {
|
|
312
|
+
hasCustomConfig: boolean;
|
|
313
|
+
}): babel_2.PluginObj;
|
|
314
|
+
|
|
310
315
|
export declare function removeDeployer(): babel_2.PluginObj;
|
|
311
316
|
|
|
312
317
|
export declare function removeDeployer_alias_1(mastraEntry: string): Plugin_2;
|
|
@@ -342,4 +347,10 @@ declare type Variables = {
|
|
|
342
347
|
playground: boolean;
|
|
343
348
|
};
|
|
344
349
|
|
|
350
|
+
declare function writeTelemetryConfig(entryFile: string, outputDir: string): Promise<{
|
|
351
|
+
hasCustomConfig: boolean;
|
|
352
|
+
}>;
|
|
353
|
+
export { writeTelemetryConfig }
|
|
354
|
+
export { writeTelemetryConfig as writeTelemetryConfig_alias_1 }
|
|
355
|
+
|
|
345
356
|
export { }
|
package/dist/build/index.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export { getWatcherInputOptions } from '../_tsup-dts-rollup.js';
|
|
|
7
7
|
export { analyzeBundle_alias_1 as analyzeBundle } from '../_tsup-dts-rollup.js';
|
|
8
8
|
export { FileService_alias_2 as FileService } from '../_tsup-dts-rollup.js';
|
|
9
9
|
export { Deps_alias_2 as Deps } from '../_tsup-dts-rollup.js';
|
|
10
|
+
export { writeTelemetryConfig } from '../_tsup-dts-rollup.js';
|
package/dist/build/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { FileService, createWatcher, getBundler, getWatcher, getInputOptions as getWatcherInputOptions } from '../chunk-
|
|
2
|
-
export { Deps } from '../chunk-
|
|
1
|
+
export { FileService, createWatcher, getBundler, getWatcher, getInputOptions as getWatcherInputOptions } from '../chunk-VCRMX3ZD.js';
|
|
2
|
+
export { Deps, writeTelemetryConfig } from '../chunk-E4D6R3B4.js';
|
|
3
3
|
export { analyzeBundle } from '../chunk-ERNQNTBH.js';
|
|
4
4
|
export { createBundler, getInputOptions as getBundlerInputOptions } from '../chunk-KXS4XYEJ.js';
|
|
5
5
|
import '../chunk-YNXJO2XU.js';
|
package/dist/bundler/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { Deps } from './chunk-
|
|
1
|
+
import { Deps, writeTelemetryConfig } from './chunk-E4D6R3B4.js';
|
|
2
2
|
import { analyzeBundle } from './chunk-ERNQNTBH.js';
|
|
3
3
|
import { createBundler, getInputOptions } from './chunk-KXS4XYEJ.js';
|
|
4
4
|
import { MastraBundler } from '@mastra/core/bundler';
|
|
5
5
|
import virtual from '@rollup/plugin-virtual';
|
|
6
|
-
import { ensureDir } from 'fs-extra';
|
|
6
|
+
import { ensureDir, copy } from 'fs-extra';
|
|
7
7
|
import { existsSync } from 'node:fs';
|
|
8
8
|
import { writeFile } from 'node:fs/promises';
|
|
9
|
-
import { join } from 'node:path';
|
|
9
|
+
import { join, dirname } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
10
11
|
import fsExtra from 'fs-extra/esm';
|
|
11
12
|
|
|
12
13
|
var Bundler = class extends MastraBundler {
|
|
@@ -20,6 +21,11 @@ var Bundler = class extends MastraBundler {
|
|
|
20
21
|
await ensureDir(join(outputDirectory, this.analyzeOutputDir));
|
|
21
22
|
await ensureDir(join(outputDirectory, this.outputDir));
|
|
22
23
|
}
|
|
24
|
+
async writeInstrumentationFile(outputDirectory) {
|
|
25
|
+
const instrumentationFile = join(outputDirectory, "instrumentation.mjs");
|
|
26
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
await copy(join(__dirname, "templates", "instrumentation-template.js"), instrumentationFile);
|
|
28
|
+
}
|
|
23
29
|
async writePackageJson(outputDirectory, dependencies) {
|
|
24
30
|
this.logger.debug(`Writing project's package.json`);
|
|
25
31
|
await ensureDir(outputDirectory);
|
|
@@ -75,13 +81,13 @@ var Bundler = class extends MastraBundler {
|
|
|
75
81
|
"node",
|
|
76
82
|
this.logger
|
|
77
83
|
);
|
|
78
|
-
await this.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
);
|
|
84
|
+
await writeTelemetryConfig(mastraEntryFile, join(outputDirectory, this.outputDir));
|
|
85
|
+
const dependenciesToInstall = Array.from(analyzedBundleInfo.externalDependencies).reduce((acc, dep) => {
|
|
86
|
+
acc.set(dep, "latest");
|
|
87
|
+
return acc;
|
|
88
|
+
}, /* @__PURE__ */ new Map());
|
|
89
|
+
await this.writePackageJson(join(outputDirectory, this.outputDir), dependenciesToInstall);
|
|
90
|
+
await this.writeInstrumentationFile(join(outputDirectory, this.outputDir));
|
|
85
91
|
this.logger.info("Bundling Mastra application");
|
|
86
92
|
const inputOptions = await getInputOptions(mastraEntryFile, analyzedBundleInfo, "node");
|
|
87
93
|
if (isVirtual) {
|
|
@@ -7,6 +7,10 @@ import path, { dirname } from 'path';
|
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import fsExtra from 'fs-extra/esm';
|
|
9
9
|
import fsPromises from 'fs/promises';
|
|
10
|
+
import * as babel from '@babel/core';
|
|
11
|
+
import babel__default from '@babel/core';
|
|
12
|
+
import { rollup } from 'rollup';
|
|
13
|
+
import esbuild from 'rollup-plugin-esbuild';
|
|
10
14
|
|
|
11
15
|
// src/deploy/log.ts
|
|
12
16
|
var createPinoStream = (logger) => {
|
|
@@ -175,5 +179,113 @@ var Deps = class extends MastraBase {
|
|
|
175
179
|
await fsPromises.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
176
180
|
}
|
|
177
181
|
};
|
|
182
|
+
function removeAllExceptTelemetryConfig(result) {
|
|
183
|
+
let mastraClass = null;
|
|
184
|
+
const t = babel__default.types;
|
|
185
|
+
return {
|
|
186
|
+
name: "remove-all-except-telemetry-config",
|
|
187
|
+
visitor: {
|
|
188
|
+
ExportNamedDeclaration: {
|
|
189
|
+
// remove all exports
|
|
190
|
+
exit(path2) {
|
|
191
|
+
path2.remove();
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
ImportDeclaration(path2) {
|
|
195
|
+
if ((path2.node.source.value === "@mastra/core" || path2.node.source.value === "@mastra/core/mastra") && path2.node.specifiers) {
|
|
196
|
+
mastraClass = path2.node.specifiers.find(
|
|
197
|
+
// @ts-ignore - no need to type
|
|
198
|
+
(p) => p.imported?.name === "Mastra"
|
|
199
|
+
)?.local?.name ?? null;
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
NewExpression(path2) {
|
|
203
|
+
if (mastraClass && path2.node.callee.name === mastraClass) {
|
|
204
|
+
let telemetry = path2.node.arguments[0]?.properties?.find(
|
|
205
|
+
// @ts-ignore
|
|
206
|
+
(prop) => prop.key.name === "telemetry"
|
|
207
|
+
);
|
|
208
|
+
const programPath = path2.scope.getProgramParent().path;
|
|
209
|
+
if (!programPath) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (telemetry) {
|
|
213
|
+
result.hasCustomConfig = true;
|
|
214
|
+
} else {
|
|
215
|
+
telemetry = {
|
|
216
|
+
value: t.objectExpression([])
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const exportDeclaration = t.exportNamedDeclaration(
|
|
220
|
+
t.variableDeclaration("const", [t.variableDeclarator(t.identifier("telemetry"), telemetry.value)]),
|
|
221
|
+
[]
|
|
222
|
+
);
|
|
223
|
+
programPath.node.body.push(exportDeclaration);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/build/telemetry.ts
|
|
231
|
+
async function writeTelemetryConfig(entryFile, outputDir) {
|
|
232
|
+
const result = {
|
|
233
|
+
hasCustomConfig: false
|
|
234
|
+
};
|
|
235
|
+
const bundle = await rollup({
|
|
236
|
+
input: {
|
|
237
|
+
"telemetry-config": entryFile
|
|
238
|
+
},
|
|
239
|
+
treeshake: true,
|
|
240
|
+
plugins: [
|
|
241
|
+
// transpile typescript to something we understand
|
|
242
|
+
esbuild({
|
|
243
|
+
target: "node20",
|
|
244
|
+
platform: "node",
|
|
245
|
+
minify: false
|
|
246
|
+
}),
|
|
247
|
+
{
|
|
248
|
+
name: "get-telemetry-config",
|
|
249
|
+
transform(code, id) {
|
|
250
|
+
if (!this.getModuleInfo(id)?.isEntry) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
return new Promise((resolve, reject) => {
|
|
254
|
+
babel.transform(
|
|
255
|
+
code,
|
|
256
|
+
{
|
|
257
|
+
babelrc: false,
|
|
258
|
+
configFile: false,
|
|
259
|
+
filename: id,
|
|
260
|
+
plugins: [removeAllExceptTelemetryConfig(result)]
|
|
261
|
+
},
|
|
262
|
+
(err, result2) => {
|
|
263
|
+
if (err) {
|
|
264
|
+
return reject(err);
|
|
265
|
+
}
|
|
266
|
+
resolve({
|
|
267
|
+
code: result2.code,
|
|
268
|
+
map: result2.map
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
// let esbuild remove all unused imports
|
|
276
|
+
esbuild({
|
|
277
|
+
target: "node20",
|
|
278
|
+
platform: "node",
|
|
279
|
+
minify: false
|
|
280
|
+
})
|
|
281
|
+
]
|
|
282
|
+
});
|
|
283
|
+
await bundle.write({
|
|
284
|
+
dir: outputDir,
|
|
285
|
+
format: "es",
|
|
286
|
+
entryFileNames: "[name].mjs"
|
|
287
|
+
});
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
178
290
|
|
|
179
|
-
export { Deps, createChildProcessLogger, createPinoStream };
|
|
291
|
+
export { Deps, createChildProcessLogger, createPinoStream, writeTelemetryConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { Deps } from './chunk-
|
|
5
|
-
export { Deps, createChildProcessLogger, createPinoStream } from './chunk-
|
|
1
|
+
import { FileService } from './chunk-VCRMX3ZD.js';
|
|
2
|
+
export { FileService, getBundler, getWatcher } from './chunk-VCRMX3ZD.js';
|
|
3
|
+
import { Bundler } from './chunk-3MSZJSZW.js';
|
|
4
|
+
import { Deps } from './chunk-E4D6R3B4.js';
|
|
5
|
+
export { Deps, createChildProcessLogger, createPinoStream } from './chunk-E4D6R3B4.js';
|
|
6
6
|
import './chunk-ERNQNTBH.js';
|
|
7
7
|
import './chunk-KXS4XYEJ.js';
|
|
8
8
|
import './chunk-YNXJO2XU.js';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NodeSDK, getNodeAutoInstrumentations, ATTR_SERVICE_NAME, Resource,
|
|
3
|
+
ParentBasedSampler,
|
|
4
|
+
TraceIdRatioBasedSampler,
|
|
5
|
+
AlwaysOnSampler,
|
|
6
|
+
AlwaysOffSampler,
|
|
7
|
+
} from '@mastra/core/telemetry/otel-vendor';
|
|
8
|
+
import { OTLPStorageExporter } from '@mastra/core/telemetry'
|
|
9
|
+
import { MastraStorageLibSql } from '@mastra/core/storage'
|
|
10
|
+
import { createLogger } from '@mastra/core/logger'
|
|
11
|
+
import { telemetry } from './telemetry-config.mjs'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
function getSampler(config) {
|
|
15
|
+
if (!config.sampling) {
|
|
16
|
+
return new AlwaysOnSampler();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!config.enabled) {
|
|
20
|
+
return new AlwaysOffSampler();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
switch (config.sampling.type) {
|
|
24
|
+
case 'ratio':
|
|
25
|
+
return new TraceIdRatioBasedSampler(config.sampling.probability);
|
|
26
|
+
case 'always_on':
|
|
27
|
+
return new AlwaysOnSampler();
|
|
28
|
+
case 'always_off':
|
|
29
|
+
return new AlwaysOffSampler();
|
|
30
|
+
case 'parent_based':
|
|
31
|
+
const rootSampler = new TraceIdRatioBasedSampler(config.sampling.root?.probability || 1.0);
|
|
32
|
+
return new ParentBasedSampler({ root: rootSampler });
|
|
33
|
+
default:
|
|
34
|
+
return new AlwaysOnSampler();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function getExporter(config) {
|
|
40
|
+
if (config.export?.type === 'otlp') {
|
|
41
|
+
return new OTLPHttpExporter({
|
|
42
|
+
url: config.export.endpoint,
|
|
43
|
+
headers: config.export.headers,
|
|
44
|
+
})
|
|
45
|
+
} else if (config.export?.type === 'custom') {
|
|
46
|
+
return config.export.exporter
|
|
47
|
+
} else {
|
|
48
|
+
const storage = new MastraStorageLibSql({
|
|
49
|
+
config: {
|
|
50
|
+
// file lives in ./.mastra/output, and we need to write to ./.mastra/mastra.db
|
|
51
|
+
url: "file:../mastra.db",
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
await storage.init()
|
|
55
|
+
|
|
56
|
+
return new OTLPStorageExporter({
|
|
57
|
+
logger: createLogger({
|
|
58
|
+
name: 'telemetry',
|
|
59
|
+
level: 'silent',
|
|
60
|
+
}),
|
|
61
|
+
storage,
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const sampler = getSampler(telemetry);
|
|
67
|
+
const exporter = await getExporter(telemetry);
|
|
68
|
+
|
|
69
|
+
const sdk = new NodeSDK({
|
|
70
|
+
resource: new Resource({
|
|
71
|
+
[ATTR_SERVICE_NAME]: telemetry.serviceName || 'default-service',
|
|
72
|
+
}),
|
|
73
|
+
sampler,
|
|
74
|
+
traceExporter: exporter,
|
|
75
|
+
instrumentations: [getNodeAutoInstrumentations()],
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
sdk.start();
|
|
79
|
+
|
|
80
|
+
// gracefully shut down the SDK on process exit
|
|
81
|
+
process.on('SIGTERM', () => {
|
|
82
|
+
sdk.shutdown().catch(() => {
|
|
83
|
+
// do nothing
|
|
84
|
+
})
|
|
85
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/deployer",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.62",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"rollup-plugin-esbuild": "^6.1.1",
|
|
53
53
|
"rollup-plugin-node-externals": "^8.0.0",
|
|
54
54
|
"zod": "^3.24.1",
|
|
55
|
-
"@mastra/core": "^0.2.0-alpha.
|
|
55
|
+
"@mastra/core": "^0.2.0-alpha.110"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@hono/node-server": "^1.13.7",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"zod-to-json-schema": "^3.24.1"
|
|
74
74
|
},
|
|
75
75
|
"scripts": {
|
|
76
|
-
"build": "tsup src/index.ts src/build/index.ts src/server/index.ts src/build/bundler.ts src/build/analyze.ts src/bundler/index.ts --format esm --clean --experimental-dts --treeshake",
|
|
76
|
+
"build": "tsup src/index.ts src/build/index.ts src/server/index.ts src/build/bundler.ts src/build/analyze.ts src/bundler/index.ts --format esm --clean --experimental-dts --treeshake --publicDir",
|
|
77
77
|
"build:watch": "pnpm build --watch",
|
|
78
78
|
"pull:openapispec": "node src/server/openapi.script.js",
|
|
79
79
|
"test": "vitest run"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NodeSDK, getNodeAutoInstrumentations, ATTR_SERVICE_NAME, Resource,
|
|
3
|
+
ParentBasedSampler,
|
|
4
|
+
TraceIdRatioBasedSampler,
|
|
5
|
+
AlwaysOnSampler,
|
|
6
|
+
AlwaysOffSampler,
|
|
7
|
+
} from '@mastra/core/telemetry/otel-vendor';
|
|
8
|
+
import { OTLPStorageExporter } from '@mastra/core/telemetry'
|
|
9
|
+
import { MastraStorageLibSql } from '@mastra/core/storage'
|
|
10
|
+
import { createLogger } from '@mastra/core/logger'
|
|
11
|
+
import { telemetry } from './telemetry-config.mjs'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
function getSampler(config) {
|
|
15
|
+
if (!config.sampling) {
|
|
16
|
+
return new AlwaysOnSampler();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!config.enabled) {
|
|
20
|
+
return new AlwaysOffSampler();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
switch (config.sampling.type) {
|
|
24
|
+
case 'ratio':
|
|
25
|
+
return new TraceIdRatioBasedSampler(config.sampling.probability);
|
|
26
|
+
case 'always_on':
|
|
27
|
+
return new AlwaysOnSampler();
|
|
28
|
+
case 'always_off':
|
|
29
|
+
return new AlwaysOffSampler();
|
|
30
|
+
case 'parent_based':
|
|
31
|
+
const rootSampler = new TraceIdRatioBasedSampler(config.sampling.root?.probability || 1.0);
|
|
32
|
+
return new ParentBasedSampler({ root: rootSampler });
|
|
33
|
+
default:
|
|
34
|
+
return new AlwaysOnSampler();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function getExporter(config) {
|
|
40
|
+
if (config.export?.type === 'otlp') {
|
|
41
|
+
return new OTLPHttpExporter({
|
|
42
|
+
url: config.export.endpoint,
|
|
43
|
+
headers: config.export.headers,
|
|
44
|
+
})
|
|
45
|
+
} else if (config.export?.type === 'custom') {
|
|
46
|
+
return config.export.exporter
|
|
47
|
+
} else {
|
|
48
|
+
const storage = new MastraStorageLibSql({
|
|
49
|
+
config: {
|
|
50
|
+
// file lives in ./.mastra/output, and we need to write to ./.mastra/mastra.db
|
|
51
|
+
url: "file:../mastra.db",
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
await storage.init()
|
|
55
|
+
|
|
56
|
+
return new OTLPStorageExporter({
|
|
57
|
+
logger: createLogger({
|
|
58
|
+
name: 'telemetry',
|
|
59
|
+
level: 'silent',
|
|
60
|
+
}),
|
|
61
|
+
storage,
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const sampler = getSampler(telemetry);
|
|
67
|
+
const exporter = await getExporter(telemetry);
|
|
68
|
+
|
|
69
|
+
const sdk = new NodeSDK({
|
|
70
|
+
resource: new Resource({
|
|
71
|
+
[ATTR_SERVICE_NAME]: telemetry.serviceName || 'default-service',
|
|
72
|
+
}),
|
|
73
|
+
sampler,
|
|
74
|
+
traceExporter: exporter,
|
|
75
|
+
instrumentations: [getNodeAutoInstrumentations()],
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
sdk.start();
|
|
79
|
+
|
|
80
|
+
// gracefully shut down the SDK on process exit
|
|
81
|
+
process.on('SIGTERM', () => {
|
|
82
|
+
sdk.shutdown().catch(() => {
|
|
83
|
+
// do nothing
|
|
84
|
+
})
|
|
85
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import babel from '@babel/core';
|
|
2
|
+
|
|
3
|
+
export function removeAllExceptTelemetryConfig(result: { hasCustomConfig: boolean }) {
|
|
4
|
+
let mastraClass: string | null = null;
|
|
5
|
+
|
|
6
|
+
const t = babel.types;
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
name: 'remove-all-except-telemetry-config',
|
|
10
|
+
visitor: {
|
|
11
|
+
ExportNamedDeclaration: {
|
|
12
|
+
// remove all exports
|
|
13
|
+
exit(path) {
|
|
14
|
+
path.remove();
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
ImportDeclaration(path) {
|
|
18
|
+
if (
|
|
19
|
+
(path.node.source.value === '@mastra/core' || path.node.source.value === '@mastra/core/mastra') &&
|
|
20
|
+
path.node.specifiers
|
|
21
|
+
) {
|
|
22
|
+
mastraClass =
|
|
23
|
+
path.node.specifiers.find(
|
|
24
|
+
// @ts-ignore - no need to type
|
|
25
|
+
p => p.imported?.name === 'Mastra',
|
|
26
|
+
)?.local?.name ?? null;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
NewExpression(path) {
|
|
30
|
+
if (mastraClass && (path.node.callee as babel.types.Identifier).name === mastraClass) {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
let telemetry = path.node.arguments[0]?.properties?.find(
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
prop => prop.key.name === 'telemetry',
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const programPath = path.scope.getProgramParent().path;
|
|
38
|
+
if (!programPath) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (telemetry) {
|
|
43
|
+
result.hasCustomConfig = true;
|
|
44
|
+
} else {
|
|
45
|
+
telemetry = {
|
|
46
|
+
value: t.objectExpression([]),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// add the deployer export
|
|
51
|
+
const exportDeclaration = t.exportNamedDeclaration(
|
|
52
|
+
t.variableDeclaration('const', [t.variableDeclarator(t.identifier('telemetry'), telemetry.value)]),
|
|
53
|
+
[],
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// @ts-ignore
|
|
57
|
+
programPath.node.body.push(exportDeclaration);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
} as babel.PluginObj;
|
|
62
|
+
}
|
package/src/build/index.ts
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as babel from '@babel/core';
|
|
2
|
+
import type { MastraDeployer } from '@mastra/core';
|
|
3
|
+
import { rollup } from 'rollup';
|
|
4
|
+
import esbuild from 'rollup-plugin-esbuild';
|
|
5
|
+
|
|
6
|
+
import { removeAllExceptTelemetryConfig } from './babel/get-telemetry-config';
|
|
7
|
+
|
|
8
|
+
export async function writeTelemetryConfig(
|
|
9
|
+
entryFile: string,
|
|
10
|
+
outputDir: string,
|
|
11
|
+
): Promise<{
|
|
12
|
+
hasCustomConfig: boolean;
|
|
13
|
+
}> {
|
|
14
|
+
const result = {
|
|
15
|
+
hasCustomConfig: false,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const bundle = await rollup({
|
|
19
|
+
input: {
|
|
20
|
+
'telemetry-config': entryFile,
|
|
21
|
+
},
|
|
22
|
+
treeshake: true,
|
|
23
|
+
plugins: [
|
|
24
|
+
// transpile typescript to something we understand
|
|
25
|
+
esbuild({
|
|
26
|
+
target: 'node20',
|
|
27
|
+
platform: 'node',
|
|
28
|
+
minify: false,
|
|
29
|
+
}),
|
|
30
|
+
{
|
|
31
|
+
name: 'get-telemetry-config',
|
|
32
|
+
transform(code, id) {
|
|
33
|
+
if (!this.getModuleInfo(id)?.isEntry) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
babel.transform(
|
|
39
|
+
code,
|
|
40
|
+
{
|
|
41
|
+
babelrc: false,
|
|
42
|
+
configFile: false,
|
|
43
|
+
filename: id,
|
|
44
|
+
plugins: [removeAllExceptTelemetryConfig(result)],
|
|
45
|
+
},
|
|
46
|
+
(err, result) => {
|
|
47
|
+
if (err) {
|
|
48
|
+
return reject(err);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
resolve({
|
|
52
|
+
code: result!.code!,
|
|
53
|
+
map: result!.map!,
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
// let esbuild remove all unused imports
|
|
61
|
+
esbuild({
|
|
62
|
+
target: 'node20',
|
|
63
|
+
platform: 'node',
|
|
64
|
+
minify: false,
|
|
65
|
+
}),
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await bundle.write({
|
|
70
|
+
dir: outputDir,
|
|
71
|
+
format: 'es',
|
|
72
|
+
entryFileNames: '[name].mjs',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return result;
|
|
76
|
+
}
|
package/src/bundler/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { MastraBundler } from '@mastra/core/bundler';
|
|
2
2
|
import virtual from '@rollup/plugin-virtual';
|
|
3
|
-
import { ensureDir } from 'fs-extra';
|
|
3
|
+
import { copy, ensureDir } from 'fs-extra';
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
5
|
import { writeFile } from 'node:fs/promises';
|
|
6
|
-
import { join } from 'node:path';
|
|
6
|
+
import { dirname, join } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
7
8
|
import type { InputOptions, OutputOptions } from 'rollup';
|
|
8
9
|
|
|
9
10
|
import fsExtra from 'fs-extra/esm';
|
|
@@ -11,6 +12,7 @@ import fsExtra from 'fs-extra/esm';
|
|
|
11
12
|
import { analyzeBundle } from '../build/analyze';
|
|
12
13
|
import { createBundler as createBundlerUtil, getInputOptions } from '../build/bundler';
|
|
13
14
|
import { Deps } from '../build/deps';
|
|
15
|
+
import { writeTelemetryConfig } from '../build/telemetry';
|
|
14
16
|
|
|
15
17
|
export abstract class Bundler extends MastraBundler {
|
|
16
18
|
protected analyzeOutputDir = '.build';
|
|
@@ -28,6 +30,13 @@ export abstract class Bundler extends MastraBundler {
|
|
|
28
30
|
await ensureDir(join(outputDirectory, this.outputDir));
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
async writeInstrumentationFile(outputDirectory: string) {
|
|
34
|
+
const instrumentationFile = join(outputDirectory, 'instrumentation.mjs');
|
|
35
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
36
|
+
|
|
37
|
+
await copy(join(__dirname, 'templates', 'instrumentation-template.js'), instrumentationFile);
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
async writePackageJson(outputDirectory: string, dependencies: Map<string, string>) {
|
|
32
41
|
this.logger.debug(`Writing project's package.json`);
|
|
33
42
|
await ensureDir(outputDirectory);
|
|
@@ -97,13 +106,15 @@ export abstract class Bundler extends MastraBundler {
|
|
|
97
106
|
this.logger,
|
|
98
107
|
);
|
|
99
108
|
|
|
100
|
-
await this.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
await writeTelemetryConfig(mastraEntryFile, join(outputDirectory, this.outputDir));
|
|
110
|
+
|
|
111
|
+
const dependenciesToInstall = Array.from(analyzedBundleInfo.externalDependencies).reduce((acc, dep) => {
|
|
112
|
+
acc.set(dep, 'latest');
|
|
113
|
+
return acc;
|
|
114
|
+
}, new Map<string, string>());
|
|
115
|
+
|
|
116
|
+
await this.writePackageJson(join(outputDirectory, this.outputDir), dependenciesToInstall);
|
|
117
|
+
await this.writeInstrumentationFile(join(outputDirectory, this.outputDir));
|
|
107
118
|
|
|
108
119
|
this.logger.info('Bundling Mastra application');
|
|
109
120
|
const inputOptions: InputOptions = await getInputOptions(mastraEntryFile, analyzedBundleInfo, 'node');
|
|
File without changes
|