diff --git a/REFERENCE.md b/REFERENCE.md index 54be0c05c..5ea7650ac 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -126,7 +126,7 @@ const appmap = createAppmap( ); // NB: An appmap can create multiple (concurrent) tracks const track = "my-identifier"; -appmap.start(track, { +appmap.startTrack(track, { app: "my-app-name", name: "my-appmap-name", pruning: true, @@ -139,13 +139,112 @@ appmap.recordScript( "(function main () { return 123; } ());", "path/to/main.js", ); -const trace = appmap.stop(track, { +const trace = appmap.stopTrack(track, { status: 0, - errors: [] + errors: [] }); console.log(JSON.stringify(trace, null, 2)); ``` +### `createAppmap(home, configuration, base)` + +* `home ` The file url of the project. Default: file url of the current working directory. +* `configuration ` Root configuration. Default: `{}`. +* `base ` The file url of the directory to resolve the relative paths of the configuration argument. +* Returns `` an appmap instance and start recording. + +### `appmap.terminate()` + +Stop recording. Subsequent method invocations will throw exception. + +### `appmap.startTrack(track, configuration, base)` + +* `track | null` An identifier for the track. Default: `null`, a random string will be used +* `configuration ` Configuration for extending the configuration of the appmap instance. Default: `{}`. +* `base | null`: The file url of the directory to resolve the relative paths of the configuration argument. Default: `null`, the presence of relative paths will throw an error. +* Returns `` the identifier for the track. This is useful when providing `null` for the `track` argument. + +### `appmap.stopTrack(track, status, errors)` + +* `track ` +* `status ` Exit status code. Default: `[]`. +* `errors ` List of errors that happened during the track lifetime. Default: `[]`. +* Returns `` the recorded trace in the appmap format -- ie: a JSON object. + +### `appmap.recordScript(content, url)` + +* `content ` Script content. +* `url ` Script location. +* Returns `` the completion value of the script. + +### `appmap.instrumentScript(content, url)` + +* `content ` Script content. +* `url ` Script location. +* Returns `` the instrumented code to run as a module. + +### `appmap.instrumentModule(content, url)` + +* `content ` Script content. +* `url ` Script location. +* Returns `` the instrumented code to run as a script. + +### `appmap.recordBeginBundle()` + +* Returns `recordEndBundle()` + * Returns `undefined`. + +This methods record an anonymous bundle. This event does not appear in the generated appmap but is useful to bundle events together. `appmap.recordApply` and `appmap.recordServerRequest` are also bundle operations. + +### `appmap.recordApply(input)` + +* `input ` The input of the application. We are still figuring out a way to manually define the called function. + * `this ` The `this` argument. Default: `undefined`. + * `arguments ` The list of arguments. Default: `[]`. +* Returns `recordReturn(output)` + * `output ` The output of the application. One and only one the two properties must be defined. + * `error: ` The thrown value of application (if present). + * `result: ` The returned value of the application (if present). + * Returns `undefined`. + +### `appmap.recordServerRequest(request)` + +* `request ` The head of the incoming HTTP request + * `protocol ` The HTTP protocol. Default: `"HTTP/1.1"`. + * `method ` The HTTP method. Default: `"GET"`. + * `url ` The requested URL. Default: `"/"`. + * `headers ` The HTTP headers. Default: `{}`. + * `route | null` The normalized requested URL (ie stripped of dynamic data). Default: `"null"`. +* Returns `recordServerResponse(response)` + * `response ` The head of the outgoing HTTP response. + * `status ` The HTTP status code. Default: `200`. + * `message ` The HTTP status message. Default: `"OK"`. + * `headers ` The HTTP headers. Default: `{}`. + * Returns `undefined`. + +### `appmap.recordBeforeJump()` + +* Returns `recordAfterJump()` + * Returns `undefined`. + +This methods record an anonymous jump. This event does not appear in the generated appmap but is useful link events togethers. `appmap.recordQuery` and `appmap.recordClientRequest` are also jump operations. + +### `appmap.recordQuery(query)` + +* `query ` + * `database ` Name of the database service. Default: `"unknown"`. + * `version ` Version of the database service. Default: `"unknown"`. + * `sql ` SQL query string. Default: `"unknown"`. + * `parameters | ` Parameters to replace in placeholders. If placeholders are anonymous, then `parameters` should be an array. If placeholders are named, then `parameters` should be a mapping object. Default: `[]`. +* Returns `recordResult(result)` + * `result ` + * `error ` Potential error while processing the query. + * Returns `undefined`. + +### `appmap.recordClientRequest(request)` + +Same type signature as `appmap.recordServerResponse` but without `route` property. Note that this method records a jump whereas `appmap.recordServerResponse` records a bundle. + ## Configuration The actual format requirements for configuration can be found as a json-schema [here](build/schema/schema.yml). @@ -210,7 +309,7 @@ The agent filter code objects (functions or objects/classes) based on a format c * `` Shorthand, `"test/**/*.mjs"` is the same as `{glob:"test/**/*.mjs", enabled:true}`. * `` * `enabled ` Indicates whether whitelisted files are enabled or not. *Default*: `true`. - * `... ` Extends from any specifier format. + * `... ` Extends from any specifier format. *Default*: `[]` -- ie: the agent will be enabled for every process whose entry script resides in the repository directory. * `scenarios ` An array of child configuration. * `scenario ` A regular expression to whitelist scenarios for execution. If the root configuration contains a command, it will always be executed. *Default*: `"^"` (every scenario will be executed). @@ -228,11 +327,11 @@ The agent filter code objects (functions or objects/classes) based on a format c * ``: Glob shorthand, `"lib/**/*.js"` is the same as `{glob: "lib/**/*.js"}`. * `` * `enabled ` Indicates whether the filtered file should be instrumented or not. *Default*: `true`. - * `shallow ` Indicates whether the filtered file should + * `shallow ` Indicates whether the filtered file should * `exclude ` Additional code object filtering for the matched file. * `... ` Extends from any specifier format. * `exclude ` Code object filtering to apply to every file. -* `source ` Indicates whether to include source code in the appmap file. *Default* `false`. +* `source ` Indicates whether to include source code in the appmap file. *Default* `false`. * `hooks ` Flags controlling what the agent intercepts. * `cjs ` Indicates whether commonjs modules should be instrumented to record function applications. *Default*: `true`. * `esm ` Indicates whether native modules should be instrumented to record function applications. *Default*: `true` for the CLI and `false` for the API. @@ -291,7 +390,7 @@ function main () { name: main children: - type: function - name: "()" + name: "()" - type: class name: Class children: [] diff --git a/components/recorder-api/default/index.mjs b/components/recorder-api/default/index.mjs index c8bae9e0e..e3885845c 100644 --- a/components/recorder-api/default/index.mjs +++ b/components/recorder-api/default/index.mjs @@ -23,12 +23,12 @@ export default (dependencies) => { }, } = dependencies; const { - recordBundle, + recordBeginBundle, recordApply, - recordResponse, - recordJump, + recordServerRequest, + recordBeforeJump, recordQuery, - recordRequest, + recordClientRequest, } = Record(dependencies); let global_running = false; const makeFile = (type, content, url = "file:///") => { @@ -68,7 +68,7 @@ export default (dependencies) => { expectRunning(this.hooking); return runScript(this.instrumentScript(content, url)); } - startTrack(track, initialization) { + startTrack(track, conf = {}, base = null) { expectRunning(this.hooking); if (track === null) { track = getUUID(); @@ -80,13 +80,12 @@ export default (dependencies) => { ); this.tracks.add(track); startTrack(this.agent, track, { - path: null, - data: {}, - ...initialization, + path: base, + data: conf, }); return track; } - stopTrack(track, termination) { + stopTrack(track, status = 0, errors = []) { expectRunning(this.hooking); expect( this.tracks.has(track), @@ -94,7 +93,7 @@ export default (dependencies) => { track, ); this.tracks.delete(track); - stopTrack(this.agent, track, { errors: [], status: 0, ...termination }); + stopTrack(this.agent, track, { errors, status }); return takeLocalAgentTrace(this.agent, track); } terminate() { @@ -110,29 +109,29 @@ export default (dependencies) => { expectRunning(this.hooking); return getSerializationEmptyValue(this.agent); } - recordBundle(data) { + recordBeginBundle(data) { expectRunning(this.hooking); - return recordBundle(this.agent, data); + return recordBeginBundle(this.agent, data); } recordApply(data) { expectRunning(this.hooking); return recordApply(this.agent, data); } - recordResponse(data) { + recordServerRequest(data) { expectRunning(this.hooking); - return recordResponse(this.agent, data); + return recordServerRequest(this.agent, data); } - recordJump(data) { + recordBeforeJump(data) { expectRunning(this.hooking); - return recordJump(this.agent, data); + return recordBeforeJump(this.agent, data); } recordQuery(data) { expectRunning(this.hooking); return recordQuery(this.agent, data); } - recordRequest(data) { + recordClientRequest(data) { expectRunning(this.hooking); - return recordRequest(this.agent, data); + return recordClientRequest(this.agent, data); } /* c8 ignore stop */ } diff --git a/components/recorder-api/default/index.test.mjs b/components/recorder-api/default/index.test.mjs index dfa0a5c04..500af2fc3 100644 --- a/components/recorder-api/default/index.test.mjs +++ b/components/recorder-api/default/index.test.mjs @@ -29,9 +29,9 @@ assertEqual( "string", ); -const track = appmap.startTrack(null, { path: null, data: { name: "name2" } }); +const track = appmap.startTrack(null, { name: "name2" }, null); assertEqual(appmap.recordScript("123;", "file:///base/main.js"), 123); -assertDeepEqual(appmap.stopTrack(track, { status: 123, errors: [] }), { +assertDeepEqual(appmap.stopTrack(track, 123, []), { configuration: { ...configuration, name: "name2", diff --git a/components/recorder-api/default/record.mjs b/components/recorder-api/default/record.mjs index 4acec73fd..2b63f142b 100644 --- a/components/recorder-api/default/record.mjs +++ b/components/recorder-api/default/record.mjs @@ -100,7 +100,7 @@ export default (dependencies) => { }; }; return { - recordBundle: generateRecord( + recordBeginBundle: generateRecord( recordBeginBundle, sanitizeNull, recordEndBundle, @@ -133,13 +133,13 @@ export default (dependencies) => { return data; }, ), - recordResponse: generateRecord( + recordServerRequest: generateRecord( recordBeginResponse, generateSanitizeRequest("BeginResponseEvent"), recordEndResponse, generateSanitizeResponse("EndResponseEvent"), ), - recordJump: generateRecord( + recordBeforeJump: generateRecord( recordBeforeJump, sanitizeNull, recordAfterJump, @@ -168,7 +168,7 @@ export default (dependencies) => { return data; }, ), - recordRequest: generateRecord( + recordClientRequest: generateRecord( recordBeforeRequest, generateSanitizeRequest("BeforeRequestEvent"), recordAfterRequest, diff --git a/components/recorder-api/default/record.test.mjs b/components/recorder-api/default/record.test.mjs index 601e72a70..277f694ba 100644 --- a/components/recorder-api/default/record.test.mjs +++ b/components/recorder-api/default/record.test.mjs @@ -7,12 +7,12 @@ import Record from "./record.mjs"; const dependencies = await buildTestDependenciesAsync(import.meta.url); const { - recordBundle, + recordBeginBundle, recordApply, - recordResponse, - recordJump, + recordServerRequest, + recordBeforeJump, recordQuery, - recordRequest, + recordClientRequest, } = Record(dependencies); const { openAgent, closeAgent, startTrack, stopTrack, takeLocalAgentTrace } = await buildTestComponentAsync("agent"); @@ -48,7 +48,7 @@ const test = ( }; test( - recordBundle, + recordBeginBundle, null, null, "begin", @@ -77,7 +77,7 @@ test( ); test( - recordResponse, + recordServerRequest, null, null, "begin", @@ -94,7 +94,7 @@ test( ); test( - recordJump, + recordBeforeJump, null, null, "before", @@ -122,7 +122,7 @@ test( ); test( - recordRequest, + recordClientRequest, null, null, "before", @@ -139,7 +139,7 @@ test( ); test( - recordRequest, + recordClientRequest, { headers: { key: "value" }, route: "route" }, null, "before", diff --git a/test/system/api/index.mjs b/test/system/api/index.mjs index a52d8e12f..b510314d1 100644 --- a/test/system/api/index.mjs +++ b/test/system/api/index.mjs @@ -58,7 +58,7 @@ const appmap = createAppmap( directory, ); -appmap.startTrack("track", { path: null, data: {} }); +appmap.startTrack("track"); await writeFileAsync( new URL(`${directory}/common.js`),