@descryy/runtime-adapter-python 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +6 -0
- package/dist/outbound-http-instrumentation.d.ts +13 -26
- package/dist/outbound-http-instrumentation.d.ts.map +1 -1
- package/dist/outbound-http-instrumentation.js +13 -26
- package/dist/outbound-http-instrumentation.js.map +1 -1
- package/dist/python-frame-parsing.d.ts +28 -55
- package/dist/python-frame-parsing.d.ts.map +1 -1
- package/dist/python-frame-parsing.js +81 -170
- package/dist/python-frame-parsing.js.map +1 -1
- package/dist/python-log-envelopes.d.ts +35 -84
- package/dist/python-log-envelopes.d.ts.map +1 -1
- package/dist/python-log-envelopes.js +41 -101
- package/dist/python-log-envelopes.js.map +1 -1
- package/dist/python-runtime-adapter.d.ts +25 -50
- package/dist/python-runtime-adapter.d.ts.map +1 -1
- package/dist/python-runtime-adapter.js +15 -38
- package/dist/python-runtime-adapter.js.map +1 -1
- package/dist/python-source-location-resolver.d.ts +12 -25
- package/dist/python-source-location-resolver.d.ts.map +1 -1
- package/dist/python-source-location-resolver.js +13 -29
- package/dist/python-source-location-resolver.js.map +1 -1
- package/dist/python-stack-trace-parser.d.ts +10 -20
- package/dist/python-stack-trace-parser.d.ts.map +1 -1
- package/dist/python-stack-trace-parser.js +18 -45
- package/dist/python-stack-trace-parser.js.map +1 -1
- package/package.json +8 -3
|
@@ -1,39 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Python
|
|
2
|
+
* Python SourceLocationResolver.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Contrast the Node resolver, which must decide between four values because
|
|
9
|
-
* a source map is a second file that can be absent, stale, or wrong.
|
|
4
|
+
* Every location is `self-contained` (a positive claim, not a fallback):
|
|
5
|
+
* CPython captures the path/line of the .py file it's actually executing,
|
|
6
|
+
* no compile step or map to drift. Contrast the Node resolver, which must
|
|
7
|
+
* choose between four values because a source map can be absent/stale/wrong.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* Deliberately does not check the file exists on disk or still matches what
|
|
10
|
+
* ran — `self-contained` is a statement about mechanism, not the working
|
|
11
|
+
* tree, and a stat call per frame buys only latency. Pseudo-files
|
|
12
|
+
* (`<string>`, `<stdin>`, `<frozen importlib._bootstrap>`) pass through verbatim.
|
|
14
13
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* *mechanism*, not about whether the working tree has since been edited —
|
|
19
|
-
* and a stat call per frame would buy nothing but latency. CPython's
|
|
20
|
-
* pseudo-files (`<string>`, `<stdin>`, `<frozen importlib._bootstrap>`) are
|
|
21
|
-
* passed through verbatim for the same reason: they are the honest location,
|
|
22
|
-
* and rewriting them to null would discard real information.
|
|
23
|
-
*
|
|
24
|
-
* `column` is always null. CPython does not print columns; 3.11+ prints a
|
|
25
|
-
* caret line under the failing expression, from which a column *could* be
|
|
26
|
-
* inferred by counting characters. That inference is not made here — it
|
|
27
|
-
* would be a derived guess presented in a field callers read as captured
|
|
28
|
-
* fact, and the caret line is preserved verbatim in `StackFrame.raw`
|
|
29
|
-
* regardless.
|
|
14
|
+
* `column` is always null — CPython doesn't print one. 3.11+'s caret line
|
|
15
|
+
* could be used to infer a column by counting characters, but that would be
|
|
16
|
+
* a derived guess in a field callers read as fact; the caret line stays verbatim in `StackFrame.raw`.
|
|
30
17
|
*/
|
|
31
18
|
export function createPythonSourceLocationResolver() {
|
|
32
19
|
return {
|
|
33
|
-
//
|
|
34
|
-
// (Node reads a source map, a JVM reader would read a LineNumberTable).
|
|
35
|
-
// Python genuinely does not, so this body never awaits — returning a
|
|
36
|
-
// resolved promise rather than inventing work to look symmetrical.
|
|
20
|
+
// Async to satisfy the interface (other languages do real I/O here); Python never awaits.
|
|
37
21
|
resolve(frame) {
|
|
38
22
|
return Promise.resolve({
|
|
39
23
|
file: frame.file,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-source-location-resolver.js","sourceRoot":"","sources":["../src/python-source-location-resolver.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"python-source-location-resolver.js","sourceRoot":"","sources":["../src/python-source-location-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,MAAM,UAAU,kCAAkC;IAChD,OAAO;QACL,0FAA0F;QAC1F,OAAO,CAAC,KAAuB;YAC7B,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,WAAW,EAAE,gBAAgB;gBAC7B,WAAW,EAAE,IAAI;aAClB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Composes the pure CPython line-recognition functions
|
|
3
|
-
*
|
|
4
|
-
* the full async `StackTraceParser` contract.
|
|
2
|
+
* Composes the pure CPython line-recognition functions (python-frame-parsing.ts)
|
|
3
|
+
* with a SourceLocationResolver to implement the async StackTraceParser contract.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* well-formed, with the right frames, the right count, and no error
|
|
12
|
-
* anywhere. Root-cause traversal would point at `main` for every Python
|
|
13
|
-
* failure ever captured.
|
|
5
|
+
* The reversal is the load-bearing line: CPython prints oldest call first
|
|
6
|
+
* ("most recent call last") but StackTrace.frames is contractually
|
|
7
|
+
* most-recent-first. Without it, `frames[0]` would be the process entry
|
|
8
|
+
* point — well-formed-looking but wrong, and root-cause traversal would
|
|
9
|
+
* point at `main` for every Python failure.
|
|
14
10
|
*
|
|
15
|
-
* `fidelity` is always
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* cannot show is the logical caller across an `await` boundary or a thread
|
|
19
|
-
* hand-off, where the chain truthfully ends — the same hard limit V8 stacks
|
|
20
|
-
* have, and the same reason this is not reported as
|
|
21
|
-
* `"concurrency-fragmented"`. Detecting a genuinely lost logical caller
|
|
22
|
-
* would need interpreter-level task correlation, not text parsing; claiming
|
|
23
|
-
* fragmentation without that evidence would be a guess.
|
|
11
|
+
* `fidelity` is always `"synchronous"` — walks real frame objects of the
|
|
12
|
+
* executing thread, but cannot show a logical caller across an await
|
|
13
|
+
* boundary or thread hand-off, same limit V8 stacks have.
|
|
24
14
|
*/
|
|
25
15
|
import type { SourceLocationResolver, StackTraceParser } from "@descryy/runtime-backend-observation";
|
|
26
16
|
export declare function createPythonStackTraceParser(resolver: SourceLocationResolver): StackTraceParser;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-stack-trace-parser.d.ts","sourceRoot":"","sources":["../src/python-stack-trace-parser.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"python-stack-trace-parser.d.ts","sourceRoot":"","sources":["../src/python-stack-trace-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAIrG,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,sBAAsB,GAAG,gBAAgB,CAkC/F"}
|
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Composes the pure CPython line-recognition functions
|
|
3
|
-
*
|
|
4
|
-
* the full async `StackTraceParser` contract.
|
|
2
|
+
* Composes the pure CPython line-recognition functions (python-frame-parsing.ts)
|
|
3
|
+
* with a SourceLocationResolver to implement the async StackTraceParser contract.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* well-formed, with the right frames, the right count, and no error
|
|
12
|
-
* anywhere. Root-cause traversal would point at `main` for every Python
|
|
13
|
-
* failure ever captured.
|
|
5
|
+
* The reversal is the load-bearing line: CPython prints oldest call first
|
|
6
|
+
* ("most recent call last") but StackTrace.frames is contractually
|
|
7
|
+
* most-recent-first. Without it, `frames[0]` would be the process entry
|
|
8
|
+
* point — well-formed-looking but wrong, and root-cause traversal would
|
|
9
|
+
* point at `main` for every Python failure.
|
|
14
10
|
*
|
|
15
|
-
* `fidelity` is always
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* cannot show is the logical caller across an `await` boundary or a thread
|
|
19
|
-
* hand-off, where the chain truthfully ends — the same hard limit V8 stacks
|
|
20
|
-
* have, and the same reason this is not reported as
|
|
21
|
-
* `"concurrency-fragmented"`. Detecting a genuinely lost logical caller
|
|
22
|
-
* would need interpreter-level task correlation, not text parsing; claiming
|
|
23
|
-
* fragmentation without that evidence would be a guess.
|
|
11
|
+
* `fidelity` is always `"synchronous"` — walks real frame objects of the
|
|
12
|
+
* executing thread, but cannot show a logical caller across an await
|
|
13
|
+
* boundary or thread hand-off, same limit V8 stacks have.
|
|
24
14
|
*/
|
|
25
15
|
import { parsePythonFrame } from "./python-frame-parsing.js";
|
|
26
16
|
export function createPythonStackTraceParser(resolver) {
|
|
@@ -30,10 +20,7 @@ export function createPythonStackTraceParser(resolver) {
|
|
|
30
20
|
const frames = [];
|
|
31
21
|
for (const line of lines) {
|
|
32
22
|
const raw = parsePythonFrame(line);
|
|
33
|
-
// Continuation lines
|
|
34
|
-
// banner and trailer parse to null here. They are real parts of the
|
|
35
|
-
// block and are preserved in the raw text the collector keeps; they
|
|
36
|
-
// are simply not frames and none is fabricated into one.
|
|
23
|
+
// Continuation lines, banner, and trailer parse to null — real parts of the block, never fabricated into a frame.
|
|
37
24
|
if (raw === null)
|
|
38
25
|
continue;
|
|
39
26
|
const location = await resolver.resolve({
|
|
@@ -45,29 +32,15 @@ export function createPythonStackTraceParser(resolver) {
|
|
|
45
32
|
frames.push({ location, raw: line });
|
|
46
33
|
}
|
|
47
34
|
if (frames.length === 0) {
|
|
48
|
-
// Nothing frame-shaped
|
|
49
|
-
// traceback, per this interface's contract: null, never an
|
|
50
|
-
// empty-but-structured StackTrace standing in for "couldn't parse".
|
|
35
|
+
// Nothing frame-shaped — null, never an empty StackTrace standing in for "couldn't parse".
|
|
51
36
|
return null;
|
|
52
37
|
}
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
// **Corrected from the value's first draft**, which justified index 0
|
|
61
|
-
// with "CPython prints no frames of its own above the application's".
|
|
62
|
-
// That is measurably false: `json.loads("{not json}")` called from a
|
|
63
|
-
// two-deep application chain prints
|
|
64
|
-
// `File "/usr/lib/python3.12/json/decoder.py", line 353, in raw_decode`
|
|
65
|
-
// as the LAST frame, i.e. the innermost — three stdlib frames sit
|
|
66
|
-
// above the application's own. Index 0 is still correct, but for the
|
|
67
|
-
// other reason: it marks the failure site, not the nearest owned
|
|
68
|
-
// code, and the contract says outright that a path-shaped stdlib
|
|
69
|
-
// filter "would break on any application that legitimately fails
|
|
70
|
-
// inside a library frame."
|
|
38
|
+
// primaryFrameIndex 0, after reversal (RT-083): the last frame CPython
|
|
39
|
+
// prints is the one that raised. Not because CPython prints no frames
|
|
40
|
+
// above the application's own — it can (three stdlib frames can sit
|
|
41
|
+
// above it, e.g. json.loads failures) — but because index 0 marks the
|
|
42
|
+
// failure site, not the nearest owned code; a path-shaped stdlib
|
|
43
|
+
// filter would break on any app that legitimately fails inside a library frame.
|
|
71
44
|
return { fidelity: "synchronous", frames: frames.reverse(), primaryFrameIndex: 0 };
|
|
72
45
|
},
|
|
73
46
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-stack-trace-parser.js","sourceRoot":"","sources":["../src/python-stack-trace-parser.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"python-stack-trace-parser.js","sourceRoot":"","sources":["../src/python-stack-trace-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,MAAM,UAAU,4BAA4B,CAAC,QAAgC;IAC3E,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,OAAe;YACzB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAE1C,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACnC,kHAAkH;gBAClH,IAAI,GAAG,KAAK,IAAI;oBAAE,SAAS;gBAE3B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;oBACtC,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,MAAM,EAAE,IAAI;oBACZ,YAAY,EAAE,GAAG,CAAC,YAAY;iBAC/B,CAAC,CAAC;gBACH,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,2FAA2F;gBAC3F,OAAO,IAAI,CAAC;YACd,CAAC;YAED,uEAAuE;YACvE,sEAAsE;YACtE,oEAAoE;YACpE,sEAAsE;YACtE,iEAAiE;YACjE,gFAAgF;YAChF,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC;QACrF,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@descryy/runtime-adapter-python",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Python runtime adapter: CPython traceback parsing, self-contained source locations, outbound httpx call-site instrumentation, the concrete RuntimeAdapter for Python.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/descryhq-wq/descry-runtime.git",
|
|
10
|
+
"directory": "packages/adapter-python"
|
|
11
|
+
},
|
|
7
12
|
"engines": {
|
|
8
13
|
"node": ">=22.5"
|
|
9
14
|
},
|
|
@@ -25,7 +30,7 @@
|
|
|
25
30
|
"build": "tsc -b"
|
|
26
31
|
},
|
|
27
32
|
"dependencies": {
|
|
28
|
-
"@descryy/runtime-contracts": "0.
|
|
29
|
-
"@descryy/runtime-backend-observation": "0.
|
|
33
|
+
"@descryy/runtime-contracts": "0.3.0",
|
|
34
|
+
"@descryy/runtime-backend-observation": "0.3.0"
|
|
30
35
|
}
|
|
31
36
|
}
|