{"id":13549132,"url":"https://github.com/jstrace/jstrace","last_synced_at":"2025-04-02T22:31:25.520Z","repository":{"id":14517962,"uuid":"17231859","full_name":"jstrace/jstrace","owner":"jstrace","description":"Dynamic tracing for javascript, in javascript (similar dtrace, ktap etc)","archived":false,"fork":false,"pushed_at":"2018-10-02T03:35:13.000Z","size":948,"stargazers_count":383,"open_issues_count":13,"forks_count":23,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-04-27T00:07:36.951Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"seaskymonster/web-help-reference-app","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jstrace.png","metadata":{"files":{"readme":"Readme.md","changelog":"History.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-02-27T01:07:08.000Z","updated_at":"2024-04-27T00:07:36.951Z","dependencies_parsed_at":"2022-09-18T23:41:27.694Z","dependency_job_id":null,"html_url":"https://github.com/jstrace/jstrace","commit_stats":null,"previous_names":["segmentio/jstrace"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jstrace%2Fjstrace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jstrace%2Fjstrace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jstrace%2Fjstrace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jstrace%2Fjstrace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jstrace","download_url":"https://codeload.github.com/jstrace/jstrace/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246905105,"owners_count":20852812,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T12:01:18.599Z","updated_at":"2025-04-02T22:31:25.065Z","avatar_url":"https://github.com/jstrace.png","language":"JavaScript","readme":"# jstrace\n\n  Dynamic tracing for JavaScript, written in JavaScript, providing you insight into your live nodejs applications, at the process, machine, or cluster level.\n\n  Similar to systems like [dtrace](http://dtrace.org/) or [ktap](http://www.ktap.org/), the goal of dynamic tracing is to enable a rich set of debugging information in live processes, often in production in order to help discover the root of an issue. These\n  libraries have very minimal overhead when disabled, and may be enabled\n  externally when needed.\n\n  View the [wiki](https://github.com/jstrace/jstrace/wiki) for additional information and libraries which may be helpful.\n\n## Installation\n\n Library:\n\n```\n$ npm install jstrace\n```\n\n  Client:\n\n```\n$ npm install -g jstrace\n```\n\n## Features\n\n - dynamic tracing :)\n - local / remote execution support\n - minimal overhead when idle\n - flexible scripting capabilities\n - probe name filtering\n - pid, process title, and hostname filtering\n - remote messaging for map/reduce style reporting\n - multi-process support, inspect your cluster in realtime\n - binds to `0.0.0.0:4322` (may need this for firewalls)\n\n## Usage\n\n```\n\n  Usage: jstrace [options] \u003cscript\u003e\n\n  Options:\n\n    -h, --help             output usage information\n    -V, --version          output the version number\n    -p, --pid \u003cpid\u003e        trace with the given \u003cpid\u003e\n    -t, --title \u003cpattern\u003e  trace with title matching \u003cpattern\u003e\n    -H, --host \u003cpattern\u003e   trace with hostname matching \u003cpattern\u003e\n\n```\n\n## Example\n\n### Instrumentation\n\n Suppose for example you have probes set up to mark the\n start and end of an http request, you may want to quickly\n tap into the process and see which part of the request/response\n cycle is hindering latency.\n\n This contrived example isn't very exciting, and only has two\n probes, but it illustrates the capabilites. We simply mark the start and\n end of the request, as well as providing the request id.\n\n```js\nvar trace = require('jstrace');\nvar http = require('http');\n\nvar ids = 0;\n\nvar server = http.createServer(function(req, res){\n  var id = ++ids;\n\n  trace('request:start', { id: id });\n  setTimeout(function(){\n\n    res.end('hello world');\n    trace('request:end', { id: id });\n  }, Math.random() * 250 | 0);\n});\n\nserver.listen(3000);\n```\n\n### Local analysis\n\n jstrace-local analysis is performed by exporting a `.local` function; When you invoke `.on()` jstrace internally broadcasts this information to the remotes when they connect and filters probes accordingly. The data is transmitted as-is from the remote for analysis.\n\n```js\nexports.local = function(traces){\n  traces.on('request:*', function(trace){\n    console.log(trace);\n  });\n};\n```\n\n Local analysis can be expensive since entire objects are transferred, if you need less information or would prefer to distribute the load you can use the remote analysis feature.\n\n### Remote analysis\n\n Remote analysis serializes the `.remote` function to the target processes for remote execution. This can be great for reporting on data that would be too expensive to transfer over the wire to `jstrace(1)`. For example suppose you just want to know the lengths of BLOBs sent to your API:\n\n```js\nexports.remote = function(traces){\n  traces.on('api:buffer', function(trace){\n    console.log(trace.buffer.length);\n  });\n};\n```\n\nNote the use of `console.log()`, jstrace provides custom `console.log()`, `console.error()`, and `console.dir()` methods which report back to `jstrace(1)`. You'll now receive something like the following:\n\n```\n12323\n232\n32423\n2321\n```\n\nWhen analysing a machine or cluster it's useful to know which machine did what, so the `console.dir()` method prefixes with the hostname, process title, and pid:\n\n```\napi-1/api/1234 \u003e\u003e 123132\napi-1/api/1234 \u003e\u003e 3212\napi-2/api/1200 \u003e\u003e 4324\n```\n\n Note that unlike `.local` you need to `require()` your modules from within the `.remote` function.\n\n### Remote cleanup\n\n When you perform evented operations in your remote function, like `setInterval()` or listening for events on emitters other than `traces`, listen for the `\"cleanup\"` event in order to finish the trace script completely once the cli exits:\n\n```js\nexports.remote = function(traces){\n  traces.on('api:buffer', function(trace){\n    // will automatically be cleaned up\n  });\n\n  var id = setInterval(function(){\n    console.log(Date.now());\n  });\n\n  traces.on('cleanup', function(){\n    clearInterval(id);\n  });\n};\n```\n\n### Local \u0026 remote analysis\n\n  Local and remote methods may be used in tandem for map/reduce style reporting. Using `traces.emit()` in the `.remote` function you can transmit custom information back to `jstrace` for display or further analysis.\n\n```js\nvar bytes = require('bytes');\n\nexports.remote = function(traces){\n  traces.on('api:buffer', function(trace){\n    traces.emit('buffer size', trace.buffer.length);\n  });\n};\n\nexports.local = function(traces){\n  traces.on('buffer size', function(n){\n    console.log('buffer %s', bytes(n));\n  });\n};\n```\n\n It's worth noting that `.on()` in `.local` is used for both remote probe subscription, _and_ events emitted by the `.remote`. Since they share this space you wouldn't want to emit similar names, for example `traces.emit('api:buffer', ...)` would be bad, since local would actually end up subscribing to the original trace _instead_ of the data emitted. This is rarely an issue but something to be aware of.\n\n### Full analysis example\n\n The `jstrace(1)` executable accepts a script which exports functions with trace patterns\n to match. These function names tell jstrace which traces to subscribe to. The `trace` object passed contains the information given to the in-processe `trace()` call, along with additional metadata such as `.timestamp`, `.hostname`, `.pid`, and `.title`.\n\n We can use this data to add anything we like, here we're simply mapping the requset ids to output deltas between the two. Note that we export the function named `.local`, there are two functions supported by jstrace, however `.local` means that the trace objects are sent over the wire and analysis is performed local to `jstrace(1)`.\n\n```js\nvar m = {};\n\nexports.local = function(traces){\n  traces.on('request:start', function(trace){\n    m[trace.id] = trace.timestamp;\n  });\n\n  traces.on('request:end', function(trace){\n    var d = Date.now() - m[trace.id];\n    console.log('%s -\u003e %sms', trace.id, d);\n  });\n};\n```\n\n To run the script just pass it to `jstrace(1)` and watch the output flow!\n\n```\n$ jstrace response-duration.js\n\n298 -\u003e 50ms\n302 -\u003e 34ms\n299 -\u003e 112ms\n287 -\u003e 184ms\n289 -\u003e 188ms\n297 -\u003e 124ms\n286 -\u003e 218ms\n295 -\u003e 195ms\n300 -\u003e 167ms\n304 -\u003e 161ms\n307 -\u003e 116ms\n301 -\u003e 206ms\n305 -\u003e 136ms\n314 -\u003e 19ms\n```\n\n### Plotting distribution\n\n  Using node modules such as [bars](https://github.com/jstrace/bars) can aid in analysis, for exmaple plotting the distribution of response status codes over time.\n\n```js\nvar clear = require('clear');\nvar bars = require('bars');\n\nvar m = {};\n\nexports.local = function(traces){\n  traces.on('request:end', function(trace){\n    m[trace.status] = m[trace.status] || 0;\n    m[trace.status]++;\n  });\n};\n\nsetInterval(function(){\n  clear();\n  console.log();\n  console.log(bars(m, { bar: '=', width: 30 }));\n}, 1000);\n```\n\n```\n  200 | ============================== | 6\n  404 | ====================           | 4\n  500 | ====================           | 4\n  505 | ===============                | 3\n  400 | ==========                     | 2\n  201 | =====                          | 1\n\n\n  201 | ============================== | 19\n  500 | ===========================    | 17\n  505 | =====================          | 13\n  200 | ===================            | 12\n  404 | ===================            | 12\n  400 | =================              | 11\n\n\n  500 | ============================== | 19\n  201 | ========================       | 15\n  200 | ===================            | 12\n  404 | ===================            | 12\n  505 | =================              | 11\n  400 | ===========                    | 7\n\n...\n```\n\n To reset the data per-interval tick all you'd have to do is add `m = {};` at the end of the `setInterval()` callback to refresh the data!\n\n### Charting\n\n  Create realtime charts using [chart](https://github.com/jstrace/chart) to monitor changes over time:\n\n ![](https://dl.dropboxusercontent.com/u/6396913/misc/Screen%20Shot%202014-02-27%20at%209.16.12%20AM.png)\n\n```js\nvar chart = require('chart');\nvar clear = require('clear');\n\nvar data = [];\nvar n = 0;\n\nexports.local = function(traces){\n  traces.on('request:end', function(trace){ n++ });\n};\n\nsetInterval(function(){\n  data.push(n);\n  n = 0;\n  clear();\n  console.log(chart(data));\n}, 1000);\n\n```\n\n## Conventions\n\n### Naming probes\n\n In general you should use \":\" as a separator for pattern matching, and prefix with something relevant for your module, such as the module's name. Here are some examples:\n\n - `express:request:start`\n - `express:socket:error`\n - `koa:request:start`\n - `koa:request:end`\n - `myapp:login`\n - `myapp:logout`\n\nYou should also consider listing probe names with descriptions in your library or application readme file.\n\n### Dependency injection\n\n If your library supports tracing, it's best that you do _not_\n add jstrace as a dependency, instead you should provide a `trace` option\n to let the user pass in jstrace if they wish. Some people call this \"dependency injection\". For example:\n\n```js\nfunction MyLib(opts) {\n  opts = opts || {};\n  this.trace = opts.trace || function(){};\n  this.trace('something', { some: 'data' });\n}\n```\n\n  The premise here is that the community should start instrumenting libraries with this functionality so that node becomes easier to profile, monitor, and debug. This is especially important for detecting latency issues across async boundaries, as they not necessarily CPU-bound and may not show up in profiles at all.\n\n## Trace object\n\n The trace object sent to both local and remote subscription handlers.\n\n - `timestamp` timestamp at the time of invocation\n - `hostname` machine hostname\n - `title` process title\n - `pid` process id\n - `name` trace name\n - `*` all other properties given\n\n## Authors\n\n - TJ Holowaychuk\n - Julian Gruber\n\n# License\n\n  MIT\n","funding_links":[],"categories":["JavaScript","Packages","包"],"sub_categories":["Debugging / Profiling"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjstrace%2Fjstrace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjstrace%2Fjstrace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjstrace%2Fjstrace/lists"}