@use-tusk/drift-node-sdk 0.1.11 → 0.1.12
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/README.md +1 -0
- package/dist/index.cjs +276 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +276 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -256,7 +256,7 @@ var TdInstrumentationAbstract = class {
|
|
|
256
256
|
|
|
257
257
|
//#endregion
|
|
258
258
|
//#region package.json
|
|
259
|
-
var version = "0.1.
|
|
259
|
+
var version = "0.1.12";
|
|
260
260
|
|
|
261
261
|
//#endregion
|
|
262
262
|
//#region src/version.ts
|
|
@@ -2038,7 +2038,7 @@ var HttpReplayHooks = class {
|
|
|
2038
2038
|
auth: requestOptions.auth || void 0,
|
|
2039
2039
|
agent: requestOptions.agent || void 0,
|
|
2040
2040
|
protocol,
|
|
2041
|
-
hostname: requestOptions.hostname || void 0,
|
|
2041
|
+
hostname: requestOptions.hostname || requestOptions.host || void 0,
|
|
2042
2042
|
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
2043
2043
|
method
|
|
2044
2044
|
};
|
|
@@ -3007,13 +3007,29 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
3007
3007
|
readable: res.readable
|
|
3008
3008
|
};
|
|
3009
3009
|
const responseChunks = [];
|
|
3010
|
-
|
|
3010
|
+
let streamConsumptionMode = "NOT_CONSUMING";
|
|
3011
|
+
const originalRead = res.read?.bind(res);
|
|
3012
|
+
if (originalRead) res.read = function read(size) {
|
|
3013
|
+
const chunk = originalRead(size);
|
|
3014
|
+
if (chunk && (streamConsumptionMode === "READ" || streamConsumptionMode === "NOT_CONSUMING")) {
|
|
3015
|
+
streamConsumptionMode = "READ";
|
|
3016
|
+
responseChunks.push(Buffer.from(chunk));
|
|
3017
|
+
}
|
|
3018
|
+
return chunk;
|
|
3019
|
+
};
|
|
3020
|
+
res.once("resume", () => {
|
|
3011
3021
|
res.on("data", (chunk) => {
|
|
3012
|
-
|
|
3022
|
+
if (chunk && (streamConsumptionMode === "PIPE" || streamConsumptionMode === "NOT_CONSUMING")) {
|
|
3023
|
+
streamConsumptionMode = "PIPE";
|
|
3024
|
+
responseChunks.push(Buffer.from(chunk));
|
|
3025
|
+
}
|
|
3013
3026
|
});
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3027
|
+
});
|
|
3028
|
+
res.on("end", async (chunk) => {
|
|
3029
|
+
if (chunk && typeof chunk !== "function") responseChunks.push(Buffer.from(chunk));
|
|
3030
|
+
try {
|
|
3031
|
+
if (responseChunks.length > 0) {
|
|
3032
|
+
const responseBuffer = Buffer.concat(responseChunks);
|
|
3017
3033
|
const rawHeaders = this._captureHeadersFromRawHeaders(res.rawHeaders);
|
|
3018
3034
|
outputValue.headers = rawHeaders;
|
|
3019
3035
|
const contentEncoding = rawHeaders["content-encoding"];
|
|
@@ -3022,40 +3038,24 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
3022
3038
|
contentEncoding
|
|
3023
3039
|
});
|
|
3024
3040
|
outputValue.bodySize = responseBuffer.length;
|
|
3025
|
-
this._addOutputAttributesToSpan({
|
|
3026
|
-
spanInfo,
|
|
3027
|
-
outputValue,
|
|
3028
|
-
statusCode: res.statusCode || 1,
|
|
3029
|
-
outputSchemaMerges: {
|
|
3030
|
-
body: {
|
|
3031
|
-
encoding: EncodingType.BASE64,
|
|
3032
|
-
decodedType: getDecodedType(outputValue.headers["content-type"] || "")
|
|
3033
|
-
},
|
|
3034
|
-
headers: { matchImportance: 0 }
|
|
3035
|
-
},
|
|
3036
|
-
inputValue: completeInputValue
|
|
3037
|
-
});
|
|
3038
|
-
} catch (error) {
|
|
3039
|
-
logger.error(`[HttpInstrumentation] Error processing response body:`, error);
|
|
3040
3041
|
}
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3042
|
+
this._addOutputAttributesToSpan({
|
|
3043
|
+
spanInfo,
|
|
3044
|
+
outputValue,
|
|
3045
|
+
statusCode: res.statusCode || 1,
|
|
3046
|
+
outputSchemaMerges: {
|
|
3047
|
+
body: {
|
|
3048
|
+
encoding: EncodingType.BASE64,
|
|
3049
|
+
decodedType: getDecodedType(outputValue.headers["content-type"] || "")
|
|
3050
|
+
},
|
|
3051
|
+
headers: { matchImportance: 0 }
|
|
3051
3052
|
},
|
|
3052
|
-
|
|
3053
|
-
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
}
|
|
3053
|
+
inputValue: completeInputValue
|
|
3054
|
+
});
|
|
3055
|
+
} catch (error) {
|
|
3056
|
+
logger.error(`[HttpInstrumentation] Error processing response body:`, error);
|
|
3057
|
+
}
|
|
3058
|
+
});
|
|
3059
3059
|
});
|
|
3060
3060
|
req.on("error", (error) => {
|
|
3061
3061
|
try {
|
|
@@ -9918,6 +9918,239 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
|
|
|
9918
9918
|
}
|
|
9919
9919
|
};
|
|
9920
9920
|
|
|
9921
|
+
//#endregion
|
|
9922
|
+
//#region src/instrumentation/libraries/prisma/types.ts
|
|
9923
|
+
/**
|
|
9924
|
+
* Prisma error class names for proper error handling
|
|
9925
|
+
*/
|
|
9926
|
+
let PrismaErrorClassName = /* @__PURE__ */ function(PrismaErrorClassName$1) {
|
|
9927
|
+
PrismaErrorClassName$1["PrismaClientKnownRequestError"] = "PrismaClientKnownRequestError";
|
|
9928
|
+
PrismaErrorClassName$1["PrismaClientUnknownRequestError"] = "PrismaClientUnknownRequestError";
|
|
9929
|
+
PrismaErrorClassName$1["PrismaClientInitializationError"] = "PrismaClientInitializationError";
|
|
9930
|
+
PrismaErrorClassName$1["PrismaClientValidationError"] = "PrismaClientValidationError";
|
|
9931
|
+
PrismaErrorClassName$1["PrismaClientRustPanicError"] = "PrismaClientRustPanicError";
|
|
9932
|
+
PrismaErrorClassName$1["NotFoundError"] = "NotFoundError";
|
|
9933
|
+
return PrismaErrorClassName$1;
|
|
9934
|
+
}({});
|
|
9935
|
+
|
|
9936
|
+
//#endregion
|
|
9937
|
+
//#region src/instrumentation/libraries/prisma/Instrumentation.ts
|
|
9938
|
+
var PrismaInstrumentation = class extends TdInstrumentationBase {
|
|
9939
|
+
constructor(config = {}) {
|
|
9940
|
+
super("@prisma/client", config);
|
|
9941
|
+
this.INSTRUMENTATION_NAME = "PrismaInstrumentation";
|
|
9942
|
+
this.prismaErrorClasses = [];
|
|
9943
|
+
this.mode = config.mode || TuskDriftMode.DISABLED;
|
|
9944
|
+
this.tuskDrift = TuskDriftCore.getInstance();
|
|
9945
|
+
}
|
|
9946
|
+
init() {
|
|
9947
|
+
return [new TdInstrumentationNodeModule({
|
|
9948
|
+
name: "@prisma/client",
|
|
9949
|
+
supportedVersions: ["5.*", "6.*"],
|
|
9950
|
+
patch: (moduleExports) => this._patchPrismaModule(moduleExports)
|
|
9951
|
+
})];
|
|
9952
|
+
}
|
|
9953
|
+
_patchPrismaModule(prismaModule) {
|
|
9954
|
+
if (this.isModulePatched(prismaModule)) {
|
|
9955
|
+
logger.debug(`[PrismaInstrumentation] Prisma module already patched, skipping`);
|
|
9956
|
+
return prismaModule;
|
|
9957
|
+
}
|
|
9958
|
+
this._storePrismaErrorClasses(prismaModule);
|
|
9959
|
+
logger.debug(`[PrismaInstrumentation] Wrapping PrismaClient constructor`);
|
|
9960
|
+
this._wrap(prismaModule, "PrismaClient", (OriginalPrismaClient) => {
|
|
9961
|
+
const self = this;
|
|
9962
|
+
logger.debug(`[PrismaInstrumentation] PrismaClient wrapper called`);
|
|
9963
|
+
return class TdPrismaClient {
|
|
9964
|
+
constructor(...args) {
|
|
9965
|
+
logger.debug(`[PrismaInstrumentation] Creating patched PrismaClient instance`);
|
|
9966
|
+
return new OriginalPrismaClient(...args).$extends({ query: { async $allOperations({ model, operation, args: operationArgs, query }) {
|
|
9967
|
+
logger.debug(`[PrismaInstrumentation] $allOperations intercepted: ${model}.${operation}`);
|
|
9968
|
+
return self._handlePrismaOperation({
|
|
9969
|
+
model,
|
|
9970
|
+
operation,
|
|
9971
|
+
args: operationArgs,
|
|
9972
|
+
query
|
|
9973
|
+
});
|
|
9974
|
+
} } });
|
|
9975
|
+
}
|
|
9976
|
+
};
|
|
9977
|
+
});
|
|
9978
|
+
this.markModuleAsPatched(prismaModule);
|
|
9979
|
+
logger.debug(`[PrismaInstrumentation] Prisma module patching complete`);
|
|
9980
|
+
return prismaModule;
|
|
9981
|
+
}
|
|
9982
|
+
_storePrismaErrorClasses(moduleExports) {
|
|
9983
|
+
const prismaNamespace = moduleExports.Prisma || {};
|
|
9984
|
+
this.prismaErrorClasses = [
|
|
9985
|
+
{
|
|
9986
|
+
name: PrismaErrorClassName.PrismaClientKnownRequestError,
|
|
9987
|
+
errorClass: moduleExports.PrismaClientKnownRequestError || prismaNamespace.PrismaClientKnownRequestError
|
|
9988
|
+
},
|
|
9989
|
+
{
|
|
9990
|
+
name: PrismaErrorClassName.PrismaClientUnknownRequestError,
|
|
9991
|
+
errorClass: moduleExports.PrismaClientUnknownRequestError || prismaNamespace.PrismaClientUnknownRequestError
|
|
9992
|
+
},
|
|
9993
|
+
{
|
|
9994
|
+
name: PrismaErrorClassName.PrismaClientInitializationError,
|
|
9995
|
+
errorClass: moduleExports.PrismaClientInitializationError || prismaNamespace.PrismaClientInitializationError
|
|
9996
|
+
},
|
|
9997
|
+
{
|
|
9998
|
+
name: PrismaErrorClassName.PrismaClientValidationError,
|
|
9999
|
+
errorClass: moduleExports.PrismaClientValidationError || prismaNamespace.PrismaClientValidationError
|
|
10000
|
+
},
|
|
10001
|
+
{
|
|
10002
|
+
name: PrismaErrorClassName.PrismaClientRustPanicError,
|
|
10003
|
+
errorClass: moduleExports.PrismaClientRustPanicError || prismaNamespace.PrismaClientRustPanicError
|
|
10004
|
+
},
|
|
10005
|
+
{
|
|
10006
|
+
name: PrismaErrorClassName.NotFoundError,
|
|
10007
|
+
errorClass: moduleExports.NotFoundError || prismaNamespace.NotFoundError
|
|
10008
|
+
}
|
|
10009
|
+
];
|
|
10010
|
+
}
|
|
10011
|
+
_handlePrismaOperation({ model, operation, args, query }) {
|
|
10012
|
+
const inputValue = {
|
|
10013
|
+
model,
|
|
10014
|
+
operation,
|
|
10015
|
+
args
|
|
10016
|
+
};
|
|
10017
|
+
logger.debug(`[PrismaInstrumentation] Intercepted Prisma operation: ${model}.${operation} in ${this.mode} mode`);
|
|
10018
|
+
if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
10019
|
+
originalFunctionCall: () => query(args),
|
|
10020
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
10021
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => query(args), {
|
|
10022
|
+
name: `prisma.${operation}`,
|
|
10023
|
+
kind: SpanKind.CLIENT,
|
|
10024
|
+
submodule: model,
|
|
10025
|
+
packageType: PackageType.UNSPECIFIED,
|
|
10026
|
+
packageName: "@prisma/client",
|
|
10027
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
10028
|
+
inputValue,
|
|
10029
|
+
isPreAppStart
|
|
10030
|
+
}, (spanInfo) => {
|
|
10031
|
+
return this._handleRecordPrismaOperation(spanInfo, query, args);
|
|
10032
|
+
});
|
|
10033
|
+
},
|
|
10034
|
+
spanKind: SpanKind.CLIENT
|
|
10035
|
+
});
|
|
10036
|
+
else if (this.mode === TuskDriftMode.REPLAY) {
|
|
10037
|
+
const stackTrace = captureStackTrace(["PrismaInstrumentation"]);
|
|
10038
|
+
return handleReplayMode({
|
|
10039
|
+
noOpRequestHandler: () => query(args),
|
|
10040
|
+
isServerRequest: false,
|
|
10041
|
+
replayModeHandler: () => {
|
|
10042
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => query(args), {
|
|
10043
|
+
name: `prisma.${operation}`,
|
|
10044
|
+
kind: SpanKind.CLIENT,
|
|
10045
|
+
submodule: model,
|
|
10046
|
+
packageType: PackageType.UNSPECIFIED,
|
|
10047
|
+
packageName: "@prisma/client",
|
|
10048
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
10049
|
+
inputValue,
|
|
10050
|
+
isPreAppStart: false
|
|
10051
|
+
}, (spanInfo) => {
|
|
10052
|
+
return this._handleReplayPrismaOperation(spanInfo, inputValue, stackTrace);
|
|
10053
|
+
});
|
|
10054
|
+
}
|
|
10055
|
+
});
|
|
10056
|
+
} else return query(args);
|
|
10057
|
+
}
|
|
10058
|
+
async _handleRecordPrismaOperation(spanInfo, query, args) {
|
|
10059
|
+
try {
|
|
10060
|
+
logger.debug(`[PrismaInstrumentation] Recording Prisma operation`);
|
|
10061
|
+
const result = await query(args);
|
|
10062
|
+
const outputValue = {
|
|
10063
|
+
prismaResult: result,
|
|
10064
|
+
_tdOriginalFormat: "result"
|
|
10065
|
+
};
|
|
10066
|
+
try {
|
|
10067
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
|
|
10068
|
+
SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK });
|
|
10069
|
+
} catch (spanError) {
|
|
10070
|
+
logger.error(`[PrismaInstrumentation] error adding span attributes:`, spanError);
|
|
10071
|
+
}
|
|
10072
|
+
return result;
|
|
10073
|
+
} catch (error) {
|
|
10074
|
+
logger.debug(`[PrismaInstrumentation] Prisma operation error: ${error.message}`);
|
|
10075
|
+
try {
|
|
10076
|
+
const errorClassName = this._getPrismaErrorClassName(error);
|
|
10077
|
+
const errorWithClassName = this._cloneError(error);
|
|
10078
|
+
if (errorClassName) errorWithClassName.customTdName = errorClassName;
|
|
10079
|
+
const outputValue = {
|
|
10080
|
+
prismaResult: errorWithClassName,
|
|
10081
|
+
_tdOriginalFormat: "error"
|
|
10082
|
+
};
|
|
10083
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
|
|
10084
|
+
SpanUtils.endSpan(spanInfo.span, {
|
|
10085
|
+
code: SpanStatusCode.ERROR,
|
|
10086
|
+
message: error.message
|
|
10087
|
+
});
|
|
10088
|
+
} catch (spanError) {
|
|
10089
|
+
logger.error(`[PrismaInstrumentation] error extracting error and adding span attributes:`, spanError);
|
|
10090
|
+
}
|
|
10091
|
+
throw error;
|
|
10092
|
+
}
|
|
10093
|
+
}
|
|
10094
|
+
async _handleReplayPrismaOperation(spanInfo, inputValue, stackTrace) {
|
|
10095
|
+
const mockData = await findMockResponseAsync({
|
|
10096
|
+
mockRequestData: {
|
|
10097
|
+
traceId: spanInfo.traceId,
|
|
10098
|
+
spanId: spanInfo.spanId,
|
|
10099
|
+
name: `prisma.${inputValue.operation}`,
|
|
10100
|
+
inputValue,
|
|
10101
|
+
packageName: "@prisma/client",
|
|
10102
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
10103
|
+
submoduleName: inputValue.model,
|
|
10104
|
+
kind: SpanKind.CLIENT,
|
|
10105
|
+
stackTrace
|
|
10106
|
+
},
|
|
10107
|
+
tuskDrift: this.tuskDrift
|
|
10108
|
+
});
|
|
10109
|
+
if (!mockData) {
|
|
10110
|
+
logger.warn(`[PrismaInstrumentation] No mock data found for Prisma operation: ${inputValue.model}.${inputValue.operation}`);
|
|
10111
|
+
throw new Error(`[PrismaInstrumentation] No matching mock found for Prisma operation: ${inputValue.model}.${inputValue.operation}`);
|
|
10112
|
+
}
|
|
10113
|
+
logger.debug(`[PrismaInstrumentation] Found mock data for Prisma operation: ${inputValue.model}.${inputValue.operation}`);
|
|
10114
|
+
const outputValue = mockData.result;
|
|
10115
|
+
if (outputValue._tdOriginalFormat === "error") {
|
|
10116
|
+
const errorObj = outputValue.prismaResult;
|
|
10117
|
+
if (errorObj.customTdName) {
|
|
10118
|
+
const errorClass = this._getPrismaErrorClassFromName(errorObj.customTdName);
|
|
10119
|
+
if (errorClass) Object.setPrototypeOf(errorObj, errorClass.prototype);
|
|
10120
|
+
}
|
|
10121
|
+
SpanUtils.endSpan(spanInfo.span, {
|
|
10122
|
+
code: SpanStatusCode.ERROR,
|
|
10123
|
+
message: errorObj.message || "Prisma error"
|
|
10124
|
+
});
|
|
10125
|
+
throw errorObj;
|
|
10126
|
+
}
|
|
10127
|
+
SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK });
|
|
10128
|
+
return outputValue.prismaResult;
|
|
10129
|
+
}
|
|
10130
|
+
_getPrismaErrorClassName(error) {
|
|
10131
|
+
for (const errorInfo of this.prismaErrorClasses) if (error instanceof errorInfo.errorClass) return errorInfo.name;
|
|
10132
|
+
}
|
|
10133
|
+
_getPrismaErrorClassFromName(className) {
|
|
10134
|
+
for (const errorInfo of this.prismaErrorClasses) if (errorInfo.name === className) return errorInfo.errorClass;
|
|
10135
|
+
return null;
|
|
10136
|
+
}
|
|
10137
|
+
/**
|
|
10138
|
+
* Deep clone an error object to make it serializable
|
|
10139
|
+
*/
|
|
10140
|
+
_cloneError(error) {
|
|
10141
|
+
const cloned = new Error(error.message);
|
|
10142
|
+
cloned.name = error.name;
|
|
10143
|
+
cloned.stack = error.stack;
|
|
10144
|
+
for (const key in error) if (error.hasOwnProperty(key)) try {
|
|
10145
|
+
cloned[key] = error[key];
|
|
10146
|
+
} catch (e) {}
|
|
10147
|
+
return cloned;
|
|
10148
|
+
}
|
|
10149
|
+
_wrap(target, propertyName, wrapper) {
|
|
10150
|
+
wrap(target, propertyName, wrapper);
|
|
10151
|
+
}
|
|
10152
|
+
};
|
|
10153
|
+
|
|
9921
10154
|
//#endregion
|
|
9922
10155
|
//#region node_modules/@opentelemetry/core/build/src/trace/suppress-tracing.js
|
|
9923
10156
|
var require_suppress_tracing = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/core/build/src/trace/suppress-tracing.js": ((exports) => {
|
|
@@ -13047,6 +13280,10 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
13047
13280
|
enabled: true,
|
|
13048
13281
|
mode: this.mode
|
|
13049
13282
|
});
|
|
13283
|
+
new PrismaInstrumentation({
|
|
13284
|
+
enabled: true,
|
|
13285
|
+
mode: this.mode
|
|
13286
|
+
});
|
|
13050
13287
|
}
|
|
13051
13288
|
initializeTracing({ baseDirectory }) {
|
|
13052
13289
|
const serviceName = this.config.service?.name || "unknown";
|