Repository: immobiliare/fastify-metrics (js)

Issue:
Connect method should be call
 We should call and await the connect method of Dats to allow the working of TCP.

Pull request:
fix(TCP): fixed tcp
close #57 

Patch:
diff --git a/index.js b/index.js
index 3c2653c..f6e1922 100644
--- a/index.js
+++ b/index.js
@@ -86,7 +86,7 @@ const COLLECT = {
 };
 
 module.exports = fp(
-    function (
+    async function (
         fastify,
         {
             host,
@@ -99,14 +99,13 @@ module.exports = fp(
             collect = {},
             customDatsClient = null,
             onError = (error) => void fastify.log.error(error),
-        },
-        next
+        }
     ) {
         const enabledMetrics = Object.assign({}, COLLECT, collect);
 
         for (const key of ['timing', 'hits', 'errors', 'health']) {
             if (typeof enabledMetrics[key] !== 'boolean') {
-                return next(new Error(`"${key}" must be a Boolean.`));
+                throw new Error(`"${key}" must be a Boolean.`);
             }
         }
 
@@ -116,10 +115,8 @@ module.exports = fp(
             for (const method of STATSD_METHODS) {
                 const fn = customDatsClient[method];
                 if (!fn || typeof fn !== 'function')
-                    return next(
-                        new Error(
-                            `customDatsClient does not implement ${method} method.`
-                        )
+                    throw new Error(
+                        `customDatsClient does not implement ${method} method.`
                     );
             }
             stats = customDatsClient;
@@ -136,6 +133,7 @@ module.exports = fp(
                   })
                 : clientMock();
         }
+        await stats.connect();
 
         fastify.decorate('stats', stats);
         fastify.decorate('hrtime2ns', hrtime2ns);
@@ -189,8 +187,6 @@ module.exports = fp(
         if (enabledMetrics.errors) {
             fastify.addHook('onError', errorsCounter);
         }
-
-        next();
     },
     {
         name: '@immobiliarelabs/fastify-metrics',


Test patch:
diff --git a/tests/helpers/statsdTCP.js b/tests/helpers/statsdTCP.js
new file mode 100644
index 0000000..72f991e
--- /dev/null
+++ b/tests/helpers/statsdTCP.js
@@ -0,0 +1,48 @@
+'use strict';
+
+const EventEmitter = require('events');
+const { createServer } = require('net');
+
+module.exports = class StatsdMock extends EventEmitter {
+    constructor() {
+        super();
+        this.server = null;
+        this.sockets = [];
+    }
+    start() {
+        return new Promise((resolve, reject) => {
+            this.server = createServer((socket) => {
+                socket.on('data', (msg) => {
+                    this.emit('metric', msg);
+                });
+                this.sockets.push(socket);
+            });
+
+            const onError = (error) => reject(error);
+
+            const onDone = () => {
+                this.server.removeListener('error', onError);
+                return resolve(this.server.address());
+            };
+            this.server.once('listening', onDone);
+            this.server.once('error', onError);
+            this.server.listen(0);
+        });
+    }
+
+    disconnectSocket() {
+        for (const sock of this.sockets) {
+            sock.destroy();
+        }
+    }
+
+    stop() {
+        return new Promise((resolve) => {
+            // Here, The close method in the old code takes as input the error, but is always undefined
+            this.disconnectSocket();
+            this.server.close(() => {
+                resolve(null);
+            });
+        });
+    }
+};
diff --git a/tests/plugin.test.js b/tests/plugin.test.js
index f2717ac..5bc4d61 100644
--- a/tests/plugin.test.js
+++ b/tests/plugin.test.js
@@ -3,6 +3,7 @@
 const test = require('ava');
 const sinon = require('sinon');
 const { StatsdMock } = require('./helpers/statsd');
+const StatsdMockTCP = require('./helpers/statsdTCP');
 const { hrtime2ms } = require('@dnlup/hrtime-utils');
 
 const PLUGINS_METHODS = [
@@ -43,10 +44,15 @@ test.beforeEach(async (t) => {
     t.context.statsd = new StatsdMock();
     /* eslint require-atomic-updates: 0 */
     t.context.address = await t.context.statsd.start();
+
+    t.context.statsdTCP = new StatsdMockTCP();
+    /* eslint require-atomic-updates: 0 */
+    t.context.addressTCP = await t.context.statsdTCP.start();
 });
 
 test.afterEach(async (t) => {
     await t.context.statsd.stop();
+    await t.context.statsdTCP.stop();
 });
 
 test.serial('configuration without options', configMacro);
@@ -128,6 +134,35 @@ test.serial('sending requests metrics', async (t) => {
     ]);
 });
 
+test.serial('sending requests metrics TCP', async (t) => {
+    t.plan(2);
+    const server = await setup({
+        host: `tcp://127.0.0.1:${t.context.addressTCP.port}`,
+        namespace: 'ns',
+        sampleInterval: 1000,
+    });
+    await Promise.all([
+        server.inject({
+            method: 'GET',
+            url: '/',
+        }),
+        new Promise((resolve) => {
+            const regexes = [
+                /ns\.api\.noId\.requests:1\|c/,
+                /ns\.api\.noId.response_time:\d+(\.\d+)?\|ms/,
+            ];
+            t.context.statsdTCP.on('metric', (buffer) => {
+                let metrics = buffer.toString().split('\n').filter(Boolean);
+
+                for (let [i, regex] of regexes.entries()) {
+                    t.regex(metrics[i], regex, `${metrics[i]} is not listed`);
+                }
+                resolve();
+            });
+        }),
+    ]);
+});
+
 test.serial('sending requests errors metrics', async (t) => {
     const server = await setup({
         host: `udp://127.0.0.1:${t.context.address.port}`,