diff --git a/.gitignore b/.gitignore index 54cfd51..b022b50 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ npm-debug.log .DS_Store *.swp *~ +.idea +.npmrc \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..d30d396 --- /dev/null +++ b/.npmignore @@ -0,0 +1,4 @@ +Dockerfile +Jenkinsfile +publish.sh +.idea diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ef34edf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM node:20-slim +RUN apt-get update && apt-get install -y git + +WORKDIR /app + +ADD package.json yarn.lock .npmrc ./ +RUN yarn install + +ADD . . + +WORKDIR /app + +RUN git config user.name 'Jenkins' +RUN git config user.email 'jenkins@acuris.com' + +ENTRYPOINT ["sh", "/app/publish.sh"] diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..8f78829 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,57 @@ +library 'jenkins-shared-library' + +pipeline { + options{ + ansiColor('xterm') + disableConcurrentBuilds() + } + + agent { + node { + label "swarm2" + } + } + + environment { + GITHUB_TOKEN = credentials("github-credentials-token") + GITHUB_CREDS = credentials("github-credentials") + GIT_USERNAME = "${env.GITHUB_CREDS_USR}" + GIT_PASSWORD = "${env.GITHUB_CREDS_PSW}" + } + + parameters { + choice(name: 'NEW_VERSION', choices: ['patch', 'minor', 'major'], description: 'The new version to be published') + } + + + stages { + stage ("Publish") { + steps { + writeNpmConfig() + sh "docker build . -t connect-datadog-publish && docker run -e GITHUB_TOKEN -e GIT_USERNAME -e GIT_PASSWORD -e NEW_VERSION=${params.NEW_VERSION} connect-datadog-publish" + } + } + } + + post { + fixed { + script { + shared.notifyTeams('SUCCESS', 'https://outlook.office.com/webhook/5e7df867-fb74-47ec-ad49-0f69e9067f72@94d278d4-98ce-45e5-98f5-8a7297697dc1/JenkinsCI/f47e4d5b144f42688223d459750b8084/ad74ba70-f060-4706-97c3-22f342f4f121') + } + } + failure { + script { + shared.notifyTeams('FAILED', 'https://outlook.office.com/webhook/5e7df867-fb74-47ec-ad49-0f69e9067f72@94d278d4-98ce-45e5-98f5-8a7297697dc1/JenkinsCI/f47e4d5b144f42688223d459750b8084/ad74ba70-f060-4706-97c3-22f342f4f121') + } + } + } + +} + + +def writeNpmConfig() { + sh """ + echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" > .npmrc + echo "@mergermarket:registry=https://npm.pkg.github.com" >> .npmrc + """ +} diff --git a/README.md b/README.md index 1c3d42c..51787d3 100644 --- a/README.md +++ b/README.md @@ -7,22 +7,28 @@ Datadog middleware for Connect JS / Express Add middleware immediately before your router. - app.use(require("connect-datadog")({})); + app.use(require("@mergermarket/connect-datadog")({})); app.use(app.router); ## Options All options are optional. -* `dogstatsd` node-dogstatsd client. `default = new (require("node-dogstatsd")).StatsD()` +* `dogstatsd` node-dogstatsd client. `default = new (require("hot-shot")).StatsD()` * `stat` *string* name for the stat. `default = "node.express.router"` -* `tags` *array* of tags to be added to the histogram. `default = []` +* `tags` either: + * *array* of tags to be added to the histogram + * *function* that takes `req` and `res`, returning an array of tags + * `default = []` +* `route_tag`: *function* `(req, res) => string` - generates `route` tag value if set * `path` *boolean* include path tag. `default = false` * `method` *boolean* include http method tag. `default = false` * `protocol` *boolean* include protocol tag. `default = false` * `response_code` *boolean* include http response codes. `default = false` +* `response_code_grouped` *boolean* include http response codes grouped by 100, e.g. 5xx. `default = false` +* `response_code_tag` *boolean* include http response codes as tags. `default = false` ## License -View the [LICENSE](https://github.com/AppPress/node-connect-datadog/blob/master/LICENSE) file. +View the [LICENSE](https://github.com/mergermarket/node-connect-datadog/blob/master/LICENSE) file. diff --git a/lib/index.js b/lib/index.js index dd47dbf..c33e96f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,4 +1,4 @@ -var DD = require("node-dogstatsd").StatsD; +var DD = require("hot-shots").StatsD; module.exports = function (options) { var datadog = options.dogstatsd || new DD(); @@ -7,6 +7,9 @@ module.exports = function (options) { var path = options.path || false; var base_url = options.base_url || false; var response_code = options.response_code || false; + var response_code_grouped = options.response_code_grouped || false; + var response_code_tag = options.response_code_tag || false; + var route_tag = typeof options.route_tag === 'function' ? options.route_tag : null; return function (req, res, next) { if (!req._startTime) { @@ -23,9 +26,13 @@ module.exports = function (options) { } var baseUrl = (base_url !== false) ? req.baseUrl : ''; + var routeTag = 'route:' + baseUrl + req.route.path; + if (route_tag !== null) { + routeTag = 'route:' + route_tag(req, res); + } var statTags = [ - "route:" + baseUrl + req.route.path - ].concat(tags); + routeTag + ].concat(typeof tags === 'function' ? tags(req, res) : tags); if (options.method) { statTags.push("method:" + req.method.toLowerCase()); @@ -39,12 +46,20 @@ module.exports = function (options) { statTags.push("path:" + baseUrl + req.path); } - if (response_code) { + if (response_code || response_code_grouped || response_code_tag) { statTags.push("response_code:" + res.statusCode); + } + + if (response_code) { datadog.increment(stat + '.response_code.' + res.statusCode , 1, statTags); datadog.increment(stat + '.response_code.all' , 1, statTags); } + if (response_code_grouped) { + var groupedStatusCode = Math.floor(res.statusCode / 100) + 'xx' + datadog.increment(stat + '.response_code.' + groupedStatusCode , 1, statTags); + } + datadog.histogram(stat + '.response_time', (new Date() - req._startTime), 1, statTags); }; diff --git a/package.json b/package.json index 34d32f3..c1de2d5 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,14 @@ { - "name": "connect-datadog", - "version": "0.0.6", + "name": "@mergermarket/connect-datadog", + "version": "1.0.0", "description": "Datadog middleware for Connect JS / Express", "main": "index.js", "repository": { "type": "git", - "url": "git://github.com/AppPress/node-connect-datadog.git" + "url": "git://github.com/mergermarket/node-connect-datadog.git" + }, + "publishConfig": { + "registry": "https://npm.pkg.github.com/" }, "keywords": [ "datadog", @@ -15,6 +18,6 @@ "license": "MIT", "readmeFilename": "README.md", "dependencies": { - "node-dogstatsd": "0.0.6" + "hot-shots": "^7.4.2" } } diff --git a/publish.sh b/publish.sh new file mode 100644 index 0000000..da73b37 --- /dev/null +++ b/publish.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -x + +publish () { + npm version ${NEW_VERSION} --commit-hooks=false + echo "//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}" > .npmrc + echo "registry=https://npm.pkg.github.com/mergermarket" >> .npmrc + npm publish + [ $? -eq 0 ] || exit 1 +} + +publish "connect-datadog" + +git add . && git commit -m 'Publishing new versions' +git pull "https://${GIT_USERNAME}:${GIT_PASSWORD}@github.com/mergermarket/node-connect-datadog.git" HEAD:master -r +git push "https://${GIT_USERNAME}:${GIT_PASSWORD}@github.com/mergermarket/node-connect-datadog.git" HEAD:master --no-verify diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..f0d33b6 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,35 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +bindings@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +hot-shots@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/hot-shots/-/hot-shots-7.4.2.tgz#45e98fd4e86b71def59b4b17b25f5f9badf46c51" + integrity sha512-oy+ZkKq+jwsuA2FXnSAXCTqdONC8hbqOTwRwRze2ALZedPUpJIs5fvSzxIola3uSIiw488fZiz7gr5PyAtjOow== + optionalDependencies: + unix-dgram "2.0.x" + +nan@^2.13.2: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + +unix-dgram@2.0.x: + version "2.0.4" + resolved "https://registry.yarnpkg.com/unix-dgram/-/unix-dgram-2.0.4.tgz#14d4fc21e539742b8fb027de16eccd4e5503a344" + integrity sha512-7tpK6x7ls7J7pDrrAU63h93R0dVhRbPwiRRCawR10cl+2e1VOvF3bHlVJc6WI1dl/8qk5He673QU+Ogv7bPNaw== + dependencies: + bindings "^1.3.0" + nan "^2.13.2"