{"id":13453956,"url":"https://github.com/immobiliare/dats","last_synced_at":"2025-04-09T18:21:10.092Z","repository":{"id":37090537,"uuid":"419644992","full_name":"immobiliare/dats","owner":"immobiliare","description":"📈 Minimalistic zero-dependencies statsd client for Node.js ","archived":false,"fork":false,"pushed_at":"2024-06-11T12:28:10.000Z","size":4952,"stargazers_count":102,"open_issues_count":13,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-24T22:34:12.407Z","etag":null,"topics":["apn","client","github","hacktoberfest","ipv6-support","javascript","metrics","nodejs","npm","statsd","tcp","typescript","udp"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/immobiliare.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-21T08:39:30.000Z","updated_at":"2025-02-15T04:10:03.000Z","dependencies_parsed_at":"2024-01-10T09:32:12.303Z","dependency_job_id":"b141cc89-d4ef-4ad9-8b78-37dd2eed97e1","html_url":"https://github.com/immobiliare/dats","commit_stats":{"total_commits":482,"total_committers":10,"mean_commits":48.2,"dds":0.2863070539419087,"last_synced_commit":"a8f6af861ee788e5a09a8744b65743bf54de1bdf"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immobiliare%2Fdats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immobiliare%2Fdats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immobiliare%2Fdats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immobiliare%2Fdats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/immobiliare","download_url":"https://codeload.github.com/immobiliare/dats/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247828986,"owners_count":21002977,"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":["apn","client","github","hacktoberfest","ipv6-support","javascript","metrics","nodejs","npm","statsd","tcp","typescript","udp"],"created_at":"2024-07-31T08:00:49.728Z","updated_at":"2025-04-09T18:21:10.065Z","avatar_url":"https://github.com/immobiliare.png","language":"TypeScript","funding_links":[],"categories":["Packages","TypeScript","包"],"sub_categories":["Debugging / Profiling","调试"],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"./logo.svg?sanitize=true\" alt=\"logo\" width=\"200px\" /\u003e\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003edats\u003c/h1\u003e\n\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier?style=flat-square)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](https://github.com/semantic-release/semantic-release)\n![npm (scoped)](https://img.shields.io/npm/v/@immobiliarelabs/dats?style=flat-square)\n![license](https://img.shields.io/github/license/immobiliare/dats)\n\n\u003e Minimalistic zero-dependencies UDP/TCP [statsd](https://github.com/statsd/statsd) client for Node.js\n\nThere are times when you have to gather metrics and you want something simple without writing too much boilerplate, `dats` to your aid!\n\nThis client aims to have a simple [statsd](https://github.com/statsd/statsd) compliant API with some optional flavour for advanced usage, like: buffered metrics and either UDP/TCP transports!\n\nSupports Node.js `\u003e=14.0.0`, if you are a Node.js `v12` user refer to `dats@2.x.x`.\n\n## Table of Content\n\n\u003c!-- toc --\u003e\n\n- [Installation](#installation)\n- [Usage](#usage)\n  * [Generic](#generic)\n  * [Namespacing with Hostname/PID](#namespacing-with-hostnamepid)\n  * [TCP Client](#tcp-client)\n- [API](#api)\n  * [`Client`](#client)\n    + [`new Client(options)`](#new-clientoptions)\n    + [`Client.close([cb])`](#clientclosecb)\n    + [`Client.connect()`](#clientconnect)\n    + [`Client.counter(string[, value, sampling])`](#clientcounterstring-value-sampling)\n    + [`Client.timing(string, value[, sampling])`](#clienttimingstring-value-sampling)\n    + [`Client.gauge(string, value)`](#clientgaugestring-value)\n    + [`Client.set(string, value)`](#clientsetstring-value)\n- [Dats Mock](#dats-mock)\n- [CLI Interface](#cli-interface)\n  * [CLI Usage](#cli-usage)\n  * [datsrc](#datsrc)\n  * [Pre-compiled binary](#pre-compiled-binary)\n- [Benchmarks](#benchmarks)\n- [Powered Apps](#powered-apps)\n- [Support \u0026 Contribute](#support--contribute)\n- [License](#license)\n\n\u003c!-- tocstop --\u003e\n\n## Installation\n\nThe package is available at [npm](https://www.npmjs.com/package/@immobiliarelabs/dats).\n\nYou can install it with `npm`\n\n```bash\n# lastest stable version\n$ npm i -S @immobiliarelabs/dats\n# latest development version\n$ npm i -S @immobiliarelabs/dats@next\n```\n\nor `yarn`\n\n```bash\n# lastest stable version\n$ yarn add @immobiliarelabs/dats\n# latest development version\n$ yarn @immobiliarelabs/dats@next\n```\n\n## Usage\n\n### Generic\n\n```ts\nimport Client from '@immobiliarelabs/dats';\n\nconst stats = new Client({\n    host: 'udp://someip:someport',\n    namespace: 'myGrafanaNamespace',\n    // Optionally register a global handler to track errors.\n    onError: (error) =\u003e {\n        processError(error);\n    },\n});\n\n// Send counter (myGrafanaNamespace.some.toCount)\nstats.counter('some.toCount', 3);\nstats.counter('some.toCount'); // defaults to 1\nstats.counter('some.toCount', 1, 10); // set sampling to 10\n// Send timing (myGrafanaNamespace.some.toTime)\nstats.timing('some.toTime', 10);\nstats.timing('some.toTime', 10, 0.1); // set sampling to 0.1\n\n// Send gauge (myGrafanaNamespace.some.toGauge)\nstats.gauge('some.toGauge', 23);\n\n// Send set (myGrafanaNamespace.some.set)\nstats.set('some.set', 765);\n```\n\n### Namespacing with Hostname/PID\n\n```ts\n// Scope your stats per hostname and/or pid\nimport Client from '@immobiliarelabs/dats';\n\nconst stats = new Client({\n    host: 'udp://someip:someport',\n    namespace: 'myGrafanaNamespace.${hostname}.${pid}',\n});\n\n// Send counter (myGrafanaNamespace.myMachine.123.some.toCount)\nstats.counter('some.toCount', 3);\n```\n\nIf the hostname contains any `.`, the client will replace them with `_`.\n\n### TCP Client\n\n```ts\nimport Client from '@immobiliarelabs/dats';\n\n// TCP usage\nconst stats = new Client({\n    host: 'tcp://someip:someport',\n    namespace: 'myGrafanaNamespace.${hostname}.${pid}',\n});\n\n// Calling connect is required in TCP environment\nawait stats.connect();\n\n// Send counter (myGrafanaNamespace.myMachine.123.some.toCount)\nstats.counter('some.toCount', 3);\n```\n\n## API\n\nThis module exports:\n\n-   [`Client`](#client)\n\n### `Client`\n\n\u003e The statsd client\n\n#### `new Client(options)`\n\n-   `options`: configuration object.\n    -   `host`: statsd host (`udp://{ip}:{port}` or `tcp://{ip}:{port}`), you can use also ipv6. If you want to force udp6 usage use: `udp6://{host}:{port}`, when using TCP, you have to call the [`Client.connect`](#clientconnect) method.\n    -   `namespace`: Optional. Prefix to use for the metrics. The metric will be sent as `namespace.` + the metric string. Optionally you can use `${hostname}` and `${pid}` placeholders in the namespace and have them substituted with the machine hostname and the process id.\n    -   `bufferSize`: Optional. Default is `0`. Setting this value to a number greather than zero will activate buffered mode, which instead of sending metrics on each call, it will buffer them and send them when one of this conditions occurs: the buffer is full, or the `bufferFlushTimeout` has expired. Using this approach is more performant, but you must be careful to use a value compatible to the MTU available on your network, otherwise your packets might get dropped silently. See [multi-metric-packets](https://github.com/statsd/statsd/blob/v0.8.6/docs/metric_types.md#multi-metric-packets).\n    -   `bufferFlushTimeout`: Optional. Default is `100`. Timeout in milliseconds to wait before flushing the metrics buffer.\n    -   `debug`: Optional. Default `debuglog('dats')`. The logger function.\n    -   `udpDnsCache`: Optional. Default true. Activate the cache DNS lookup for udp.\n    -   `udpDnsCacheTTL`: Optional. Default `120`. Dns cache Time to live in seconds.\n    -   `onError`: Optional. Default `(err) =\u003e void`. Called when there is an error. Allows you to check also send errors.\n    -   `customSocket`: Optional. Default `null`. Custom socket used by the client, this is a feature for mocking we do not recommend using it in production.\n    -   `tags`: Optional Default `null`. If provided, metrics will include tags in the form `#key1:value1,key2:value2`.\n\n#### `Client.close([cb])`\n\n\u003e close the client socket\n\n-   `cb`: optional. A callback function to call when the socket is closed. If no `cb` is provided a `Promise` is returned.\n\n**Returns**: a `Promise` if no `cb` is passed.\n\n#### `Client.connect()`\n\n\u003e connect the TCP socket. Calling this function is required only on TCP.\n\n**Returns**: a `Promise`.\n\n#### `Client.counter(string[, value, sampling])`\n\n\u003e send a metric of type counter\n\n-   `string`: The metric string\n-   `value`: Optional. The metric value (`Number`). Defaults to `1`.\n-   `sampling`: Optional. The metric sampling.\n\nAll sending errors are handled by the `onError` callback.\n\n#### `Client.timing(string, value[, sampling])`\n\n\u003e send a metric of type timing\n\n-   `string`: The metric string\n-   `value`: The metric value (`Number`).\n-   `sampling`: Optional. The metric sampling.\n\nAll sending errors are handled by the `onError` callback.\n\n#### `Client.gauge(string, value)`\n\n\u003e send a metric of type gauge\n\n-   `string`: The metric string\n-   `value`: The metric value (`Number`).\n\nAll sending errors are handled by the `onError` callback.\n\n#### `Client.set(string, value)`\n\n\u003e send a metric of type set\n\n-   `string`: The metric string\n-   `value`: The metric value (`Number`).\n\nAll sending errors are handled by the `onError` callback.\n\n## Dats Mock\n\nDats exports his mock, you can use it as follow:\n\n```ts\nimport ClientMock from '@immobiliarelabs/dats/dist/mock';\n\nconst host = new URL(`udp://127.0.0.1:8232`);\nconst namespace = 'ns1';\nconst client = new ClientMock({ host, namespace });\n\nclient.gauge('some.metric', 100);\nclient.set('some.metric', 100);\n// metrics is an array with all metrics sent\nconsole.log(client.metrics);\n/* stdout:\n    [\n        'ns1.some.metric:100|g',\n        'ns1.some.metric:100|s',\n    ]\n*/\n// Check if a metric is in the metrics array\nclient.hasSent('ns1.some.metric:100|s'); // -\u003e true\nclient.hasSent('ns1.some.metric:10|s'); // -\u003e false\nclient.hasSent(/ns1\\.some\\.metric:\\d+\\|s/); // -\u003e true\nclient.hasSent(/ns1\\.some\\.test:\\d+\\|s/); // -\u003e false\n\n// Clean the metrics array with\nclient.cleanMetrics();\nconsole.log(client.metrics);\n/* stdout:\n    []\n*/\n```\n\n## CLI Interface\n\ndats is also exposed as a CLI that can both be installed as a npm global package or a precompiled binary.\n\nThe precompile binary can be found in the [release section](https://github.com/immobiliare/dats/releases) for Linux, MacOS or Windows.\n\n### CLI Usage\n\n```sh\n$ npm i -g @immobiliarelabs/dats\ndats --help\n# ℹ️  The following are required input flags:\n#\n#         --host {string} []\n#         --port {string} []\n#         --type {string} [Metric type can be one of: counter, timing, gauge, set]\n#         --prefix {string} [Metric prefix]\n#         --namespace {string} [Metric full namespace, use dots `.` to separate metrics]\n#         --value {string} [Metric value]\n#         --quiet {boolean} [Suppress all console output]\n#         --dryRun {boolean} [Metric wont be sent, use for debug]\n#\n# If unsure of output run the command prepended with `DRY_RUN=1`\n```\n\n### datsrc\n\nEvery command flag can also be specified in JSON format in the file `.datsrc`, the process at runtime will search it in the current working directory and merge both file config and flags before running!\n\n```json\n{\n    \"host\": \"123.123.123.123\",\n    \"port\": \"1234\",\n    \"prefix\": \"my_metric_prefix\"\n}\n```\n\n### Pre-compiled binary\n\nIf you want to use the precompiled binary get the correct link for your OS in the [release section](https://github.com/immobiliare/dats/releases) and do the following:\n\n```bash\ncurl https://github.com/immobiliare/dats/releases/download/v{{VERSION_TAG}}/dats-cli-{{VERSION_OS}} -L -o dats-cli\nchmod +x dats-cli\n./dats-cli\n```\n\n## Benchmarks\n\nThe automatic benchmarking for every commit can be found at the following links: [next](https://immobiliare.github.io/dats/next/bench/index.html) and\n[main](https://immobiliare.github.io/dats/main/bench/index.html).\n\nThe tests were done using [autocannon](https://github.com/mcollina/autocannon) pointing to an HTTP node.js Server that sends at each request a count metric.\nWith this kind of test, we evaluate how much the library influences the application performance.\n\nBelow are reported the benchmarks with the most famous node.js statsd clients:\n\n| LIBRARY                                                      | Req/Sec (97.5th) | Req/Sec (avg) |\n| ------------------------------------------------------------ | ---------------- | ------------- |\n| [dats](https://github.com/immobiliare/dats)                  | 45503            | 43174.4       |\n| [hot-shots](https://github.com/brightcove/hot-shots)         | 46975            | 43319.47      |\n| [node-statsd](https://github.com/sivy/node-statsd)           | 14935            | 11632.34      |\n| [statsd-client](https://www.npmjs.com/package/statsd-client) | 42463            | 35790.67      |\n|                                                              |                  |               |\n| Base                                                         | 50271            | 43312.54      |\n\n**Base** is the HTTP server without metrics.\n\n## Powered Apps\n\ndats was created by the amazing Node.js team at ImmobiliareLabs, the Tech dept of [Immobiliare.it](https://www.immobiliare.it), the #1 real estate company in Italy.\n\nWe are currently using dats in our products as well as our internal toolings.\n\n**If you are using dats in production [drop us a message](mailto:opensource@immobiliare.it)**.\n\n## Support \u0026 Contribute\n\nMade with ❤️ by [ImmobiliareLabs](https://github.com/immobiliare) \u0026 [Contributors](./CONTRIBUTING.md#contributors)\n\nWe'd love for you to contribute to dats!\nIf you have any questions on how to use dats, bugs and enhancement please feel free to reach out by opening a [GitHub Issue](https://github.com/immobiliare/dats/issues).\n\n## License\n\ndats is licensed under the MIT license.\nSee the [LICENSE](./LICENSE) file for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimmobiliare%2Fdats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimmobiliare%2Fdats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimmobiliare%2Fdats/lists"}