Skip to content

Commit c14bc19

Browse files
authored
docs: README and TypeScript docs (#40)
1 parent 79f0641 commit c14bc19

File tree

4 files changed

+188
-10
lines changed

4 files changed

+188
-10
lines changed

README.md

Lines changed: 170 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,183 @@
11
# `@apm-js-collab/code-transformer`
22

3-
This is a temporary fork of [`DataDog/orchestrion-js`](https://github.com/DataDog/orchestrion-js/). We intend all changes to be upstreamed to the original repository,
3+
This is a fork of
4+
[`DataDog/orchestrion-js`](https://github.com/DataDog/orchestrion-js/).
45

5-
This is a library for instrumenting Node.js libraries at build or load time.
6+
This is a library to aid in instrumenting Node.js libraries at build or load
7+
time.
68

7-
It provides `VisitMut` implementations for SWC's AST nodes, which can be used to insert tracing code into matching functions.
8-
It can be used in SWC plugins, or anything else that mutates JavaScript ASTs using SWC.
9+
It uses SWC's Rust AST walker to inject code that calls Node.js
10+
[`TracingChannel`](https://nodejs.org/api/diagnostics_channel.html#class-tracingchannel).
911

10-
`@apm-js-collab/code-transformer` is built as a JavaScript module, which can be used from Node.js.
12+
You likely don't want to use this library directly; instead, consider using:
13+
14+
- [`@apm-js-collab/tracing-hooks/`](https://github.com/apm-js-collab/tracing-hooks/)
15+
- ESM and `require` hooks to instrument modules as they are loaded.
16+
- [`apm-js-collab/code-transformer-bundler-plugins`](https://github.com/apm-js-collab/code-transformer-bundler-plugins)
17+
- Bundler plugins for webpack, Vite, Rollup and esbuild to instrument modules
18+
at build time.
19+
20+
## JavaScript
21+
22+
`@apm-js-collab/code-transformer` exposes the Rust library as a WebAssembly
23+
module.
24+
25+
### Building
1126

1227
To build the JavaScript module:
28+
1329
- Ensure you have [Rust installed](https://www.rust-lang.org/tools/install)
14-
- Install the wasm toolchain `rustup target add wasm32-unknown-unknown --toolchain stable`
15-
- Install dependencies and build the module `npm install && npm run build`
30+
- Install the wasm toolchain\
31+
`rustup target add wasm32-unknown-unknown --toolchain stable`
32+
- Install dependencies and build the module\
33+
`npm install && npm run build`
34+
35+
### Usage
36+
37+
```javascript
38+
import * as codeTransformer from "@apm-js-collab/code-transformer";
39+
40+
// The full instrumentation config
41+
const instrumentation = {
42+
// The name of the diagnostics channel
43+
channelName: "my-channel",
44+
// Define the module you'd like to inject tracing channels into
45+
module: {
46+
name: "my-module",
47+
versionRange: ">=1.0.0",
48+
filePath: "./dist/index.js",
49+
},
50+
// Define the function you'd like to instrument
51+
// (e.g., match a method named 'foo' that returns a Promise)
52+
functionQuery: {
53+
methodName: "fetch",
54+
kind: "Async",
55+
},
56+
};
57+
58+
// Create an InstrumentationMatcher with an array of instrumentation configs
59+
const matcher = codeTransformer.create([instrumentation]);
60+
61+
// Get a transformer for a specific module
62+
const transformer = matcher.getTransformer(
63+
"my-module",
64+
"1.2.3",
65+
"./dist/index.js",
66+
);
67+
68+
if (transformer === undefined) {
69+
throw new Error("No transformer found for module");
70+
}
71+
72+
// Transform code
73+
const inputCode = "async function fetch() { return 42; }";
74+
const result = transformer.transform(inputCode, "unknown");
75+
console.log(result.code);
76+
77+
// Both the matcher and transformer should be freed after use!
78+
matcher.free();
79+
transformer.free();
80+
```
81+
82+
### API Reference
83+
84+
```ts
85+
type ModuleType = "esm" | "cjs" | "unknown";
86+
type FunctionKind = "Sync" | "Async";
87+
```
88+
89+
#### **`FunctionQuery` Variants**
90+
91+
```ts
92+
type FunctionQuery =
93+
| // Match class constructor
94+
{ className: string; index?: number }
95+
| // Match class method
96+
{
97+
className: string;
98+
methodName: string;
99+
kind: FunctionKind;
100+
index?: number;
101+
}
102+
| // Match method on objects
103+
{ methodName: string; kind: FunctionKind; index?: number }
104+
| // Match standalone function
105+
{ functionName: string; kind: FunctionKind; index?: number }
106+
| // Match arrow function or function expression
107+
{ expressionName: string; kind: FunctionKind; index?: number };
108+
```
109+
110+
#### **`ModuleMatcher`**
111+
112+
```ts
113+
type ModuleMatcher = {
114+
name: string; // Module name
115+
versionRange: string; // Matching semver range
116+
filePath: string; // Path to the file from the module root
117+
};
118+
```
119+
120+
#### **`InstrumentationConfig`**
121+
122+
```ts
123+
type InstrumentationConfig = {
124+
channelName: string; // Name of the diagnostics channel
125+
module: ModuleMatcher;
126+
functionQuery: FunctionQuery;
127+
};
128+
```
129+
130+
### Functions
131+
132+
```ts
133+
create(configs: InstrumentationConfig[], dc_module?: string | null): InstrumentationMatcher;
134+
```
135+
136+
Create a matcher for one or more instrumentation configurations.
137+
138+
- `configs` - Array of instrumentation configurations.
139+
- `dc_module` - Optional module to import `diagnostics_channel` API from.
140+
141+
#### **`InstrumentationMatcher`**
142+
143+
```ts
144+
getTransformer(module_name: string, version: string, file_path: string): Transformer | undefined;
145+
```
146+
147+
Gets a transformer for a specific module and file.
148+
149+
Returns a `Transformer` for the given module, or `undefined` if there were no
150+
matching instrumentation configurations.
151+
152+
- `module_name` - Name of the module.
153+
- `version` - Version of the module.
154+
- `file_path` - Path to the file from the module root.
155+
156+
```ts
157+
free(): void;
158+
```
159+
160+
Free the matcher memory when it's no longer needed.
161+
162+
#### **`Transformer`**
163+
164+
```ts
165+
transform(code: string, module_type: ModuleType, sourcemap?: string | undefined): TransformOutput;
166+
```
167+
168+
Transforms the code, injecting tracing as configured.
169+
170+
Returns `{ code, map }`. `map` will be undefined if no sourcemap was supplied.
171+
172+
- `code` - The JavaScript/TypeScript code to transform.
173+
- `module_type` - The type of module being transformed.
174+
- `sourcemap` - Optional existing source map for the code.
16175

17-
## Contributing
176+
```ts
177+
free(): void;
178+
```
18179

19-
See CONTRIBUTING.md
180+
Free the transformer memory when it's no longer needed.
20181

21182
## License
22183

src/config.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@ use std::path::PathBuf;
1313
serde(rename_all = "camelCase")
1414
)]
1515
#[derive(Debug, Clone)]
16+
/// Describes the module and file path you would like to match
1617
pub struct ModuleMatcher {
18+
/// The name of the module you want to match
1719
pub name: String,
20+
/// The semver range that you want to match
1821
#[tsify(type = "string")]
1922
pub version_range: Range,
23+
/// The path of the file you want to match from the module root
2024
pub file_path: PathBuf,
2125
}
2226

@@ -59,9 +63,13 @@ impl ModuleMatcher {
5963
tsify(into_wasm_abi, from_wasm_abi)
6064
)]
6165
#[derive(Debug, Clone)]
66+
/// Configuration for injecting instrumentation code
6267
pub struct InstrumentationConfig {
68+
/// The name of the diagnostics channel to publish to
6369
pub channel_name: String,
70+
/// The module matcher to identify the module and file to instrument
6471
pub module: ModuleMatcher,
72+
/// The function query to identify the function to instrument
6573
pub function_query: FunctionQuery,
6674
}
6775

src/function_query.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub(crate) enum FunctionType {
1111
Method,
1212
}
1313

14+
/// The kind of function - Sync or returns a promise
1415
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
1516
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1617
#[derive(Debug, Clone)]
@@ -40,6 +41,7 @@ impl FunctionKind {
4041
derive(serde::Serialize, serde::Deserialize),
4142
serde(untagged, rename_all_fields = "camelCase")
4243
)]
44+
/// Describes which function to instrument
4345
#[derive(Debug, Clone)]
4446
pub enum FunctionQuery {
4547
// The order here matters because this enum is untagged, serde will try

src/wasm.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use wasm_bindgen::prelude::*;
1313
derive(tsify::Tsify),
1414
tsify(into_wasm_abi, from_wasm_abi)
1515
)]
16+
/// The type of module being passed - ESM, CJS or unknown
1617
pub enum ModuleType {
1718
ESM,
1819
CJS,
@@ -30,11 +31,14 @@ impl From<ModuleType> for IsModule {
3031
}
3132

3233
#[wasm_bindgen]
34+
/// The InstrumentationMatcher is responsible for matching specific modules
3335
pub struct InstrumentationMatcher(Instrumentor);
3436

3537
#[wasm_bindgen]
3638
impl InstrumentationMatcher {
3739
#[wasm_bindgen(js_name = "getTransformer")]
40+
/// Get a transformer for the given module name, version and file path.
41+
/// Returns `undefined` if no matching instrumentations are found.
3842
pub fn get_transformer(
3943
&mut self,
4044
module_name: &str,
@@ -54,11 +58,13 @@ impl InstrumentationMatcher {
5458
}
5559

5660
#[wasm_bindgen]
61+
/// The Transformer is responsible for transforming JavaScript code.
5762
pub struct Transformer(InstrumentationVisitor);
5863

5964
#[wasm_bindgen]
6065
impl Transformer {
61-
/// Transform the given JavaScript code with optional sourcemap support.
66+
/// Transform JavaScript code and optionally sourcemap.
67+
///
6268
/// # Errors
6369
/// Returns an error if the transformation fails to find injection points.
6470
#[wasm_bindgen]
@@ -75,6 +81,7 @@ impl Transformer {
7581
}
7682
}
7783

84+
/// Create a new instrumentation matcher from an array of instrumentation configs.
7885
#[wasm_bindgen]
7986
#[must_use]
8087
pub fn create(

0 commit comments

Comments
 (0)