From 3f3f667952853258413143300ccce4d95ba943e1 Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Fri, 8 Jun 2018 13:30:45 -0700 Subject: [PATCH] fix: update to @google-cloud/common@0.19 (#772) * fix: update to @google-cloud/common@0.19 * chore: update package-lock.json * test: update most of the tests that fail * test: rewrite test-trace-writer * refactor: address comments --- package-lock.json | 1068 +++++++--------------- package.json | 2 +- src/trace-writer.ts | 89 +- src/tracing.ts | 17 +- src/types.d.ts | 54 -- test/logger.ts | 25 +- test/test-agent-stopped.ts | 56 +- test/test-default-ignore-ah-health.ts | 40 +- test/test-env-log-level.ts | 64 +- test/test-index.ts | 34 - test/test-modules-loaded-before-agent.ts | 16 +- test/test-no-self-tracing.ts | 5 +- test/test-plugin-loader.ts | 1 + test/test-trace-uncaught-exception.ts | 136 +-- test/test-trace-writer.ts | 555 ++++++----- test/test-unpatch.ts | 125 --- test/trace.ts | 43 +- tsconfig.json | 4 + 18 files changed, 844 insertions(+), 1490 deletions(-) delete mode 100644 test/test-unpatch.ts diff --git a/package-lock.json b/package-lock.json index e1ec1b958..bb09ef98d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,32 +1,187 @@ { "name": "@google-cloud/trace-agent", - "version": "2.8.1", + "version": "2.10.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.49.tgz", + "integrity": "sha1-vs2AVIJzREDJ0TfkbXc0DmTX9Rs=", + "dev": true, + "requires": { + "@babel/highlight": "7.0.0-beta.49" + } + }, + "@babel/generator": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.49.tgz", + "integrity": "sha1-6c/9qROZaszseTu8JauRvBnQv3o=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.49", + "jsesc": "2.5.1", + "lodash": "4.17.10", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.49.tgz", + "integrity": "sha1-olwRGbnwNSeGcBJuAiXAMEHI3jI=", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.49", + "@babel/template": "7.0.0-beta.49", + "@babel/types": "7.0.0-beta.49" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.49.tgz", + "integrity": "sha1-z1Aj8y0q2S0Ic3STnOwJUby1FEE=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.49" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.49.tgz", + "integrity": "sha1-QNeO2glo0BGxxShm5XRs+yPldUg=", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.49" + } + }, + "@babel/highlight": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.49.tgz", + "integrity": "sha1-lr3GtD4TSCASumaRsQGEktOWIsw=", + "dev": true, + "requires": { + "chalk": "2.4.1", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.0.0-beta.49.tgz", + "integrity": "sha1-lE0MW6KBK7FZ7b0iZ0Ov0mUXm9w=", + "dev": true + }, + "@babel/template": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.49.tgz", + "integrity": "sha1-44q+ghfLl5P0YaUwbXrXRdg+HSc=", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.49", + "@babel/parser": "7.0.0-beta.49", + "@babel/types": "7.0.0-beta.49", + "lodash": "4.17.10" + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.49.tgz", + "integrity": "sha1-TypzaCoYM07WYl0QCo0nMZ98LWg=", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.49", + "@babel/generator": "7.0.0-beta.49", + "@babel/helper-function-name": "7.0.0-beta.49", + "@babel/helper-split-export-declaration": "7.0.0-beta.49", + "@babel/parser": "7.0.0-beta.49", + "@babel/types": "7.0.0-beta.49", + "debug": "3.1.0", + "globals": "11.5.0", + "invariant": "2.2.4", + "lodash": "4.17.10" + } + }, + "@babel/types": { + "version": "7.0.0-beta.49", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.49.tgz", + "integrity": "sha1-t+Oxw/TUz+Eb34yJ8e/V4WF7h6Y=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.10", + "to-fast-properties": "2.0.0" + } + }, "@google-cloud/common": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.17.0.tgz", - "integrity": "sha512-HRZLSU762E6HaKoGfJGa8W95yRjb9rY7LePhjaHK9ILAnFacMuUGVamDbTHu1csZomm1g3tZTtXfX/aAhtie/Q==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.19.1.tgz", + "integrity": "sha512-GVv8PZ/DQwrCkmx0iKJcLrjFc+Eeky1WwyQJQljrNTOJ52sxa7xTEjD3hPphFBJj56ECMl55YV5jJmezBJEFEA==", "requires": { - "array-uniq": "1.0.3", + "@types/duplexify": "3.5.0", + "@types/request": "2.47.0", "arrify": "1.0.1", - "concat-stream": "1.6.2", - "create-error-class": "3.0.2", + "axios": "0.18.0", "duplexify": "3.6.0", "ent": "2.2.0", "extend": "3.0.1", - "google-auto-auth": "0.10.1", + "google-auth-library": "1.5.0", "is": "3.2.1", - "log-driver": "1.2.7", - "methmeth": "1.1.0", - "modelo": "4.2.3", + "pify": "3.0.0", "request": "2.85.0", "retry-request": "3.3.1", - "split-array-stream": "1.0.3", - "stream-events": "1.0.4", - "string-format-obj": "1.1.1", - "through2": "2.0.3" + "split-array-stream": "2.0.0", + "stream-events": "1.0.4" + }, + "dependencies": { + "axios": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "1.4.1", + "is-buffer": "1.1.6" + } + } } }, "@types/builtin-modules": { @@ -38,8 +193,7 @@ "@types/caseless": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.1.tgz", - "integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A==", - "dev": true + "integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A==" }, "@types/continuation-local-storage": { "version": "3.2.1", @@ -47,7 +201,15 @@ "integrity": "sha1-oz4N+dzptCTRyY/E/evYV43O7H4=", "dev": true, "requires": { - "@types/node": "9.6.15" + "@types/node": "10.3.0" + } + }, + "@types/duplexify": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.5.0.tgz", + "integrity": "sha512-+aZCCdxuR/Q6n58CBkXyqGqimIqpYUcFLfBXagXv7e9TdJUevqkKhzopBuRz3RB064sQxnJnhttHOkK/O93Ouw==", + "requires": { + "@types/node": "10.3.0" } }, "@types/events": { @@ -66,9 +228,8 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", - "dev": true, "requires": { - "@types/node": "9.6.15" + "@types/node": "10.3.0" } }, "@types/glob": { @@ -79,7 +240,7 @@ "requires": { "@types/events": "1.2.0", "@types/minimatch": "3.0.3", - "@types/node": "9.6.15" + "@types/node": "10.3.0" } }, "@types/is": { @@ -112,7 +273,7 @@ "integrity": "sha512-TeiJ7uvv/92ugSqZ0v9l0eNXzutlki0aK+R1K5bfA5SYUil46ITlxLW4iNTCf55P4L5weCmaOdtxGeGWvudwPg==", "dev": true, "requires": { - "@types/node": "9.6.15" + "@types/node": "10.3.0" } }, "@types/nock": { @@ -121,14 +282,13 @@ "integrity": "sha512-S8rJ+SaW82ICX87pZP62UcMifrMfjEdqNzSp+llx4YcvKw6bO650Ye6HwTqER1Dar3S40GIZECQisOrAICDCjA==", "dev": true, "requires": { - "@types/node": "9.6.15" + "@types/node": "10.3.0" } }, "@types/node": { - "version": "9.6.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.15.tgz", - "integrity": "sha512-16zIiQkIZBc1ZpfrOZZZ/6LKDixPiAIZq5q1YE1stxG4Ic1VmQlkNNWGBydqBFcX8eS+m/Dd4z5HzDa+q0b2Xg==", - "dev": true + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.0.tgz", + "integrity": "sha512-hWzNviaVFIr1TqcRA8ou49JaSHp+Rfabmnqg2kNvusKqLhPU0rIsGPUj5WJJ7ld4Bb7qdgLmIhLfCD1qS08IVA==" }, "@types/once": { "version": "1.4.0", @@ -152,11 +312,10 @@ "version": "2.47.0", "resolved": "https://registry.npmjs.org/@types/request/-/request-2.47.0.tgz", "integrity": "sha512-/KXM5oev+nNCLIgBjkwbk8VqxmzI56woD4VUxn95O+YeQ8hJzcSmIZ1IN3WexiqBb6srzDo2bdMbsXxgXNkz5Q==", - "dev": true, "requires": { "@types/caseless": "0.12.1", "@types/form-data": "2.2.1", - "@types/node": "9.6.15", + "@types/node": "10.3.0", "@types/tough-cookie": "2.3.3" } }, @@ -181,8 +340,7 @@ "@types/tough-cookie": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha512-MDQLxNFRLasqS4UlkWMSACMKeSm1x4Q3TxzUC7KQUsh6RK1ZrQ0VEyE3yzXcBu+K8ejVj4wuX32eUG02yNp+YQ==", - "dev": true + "integrity": "sha512-MDQLxNFRLasqS4UlkWMSACMKeSm1x4Q3TxzUC7KQUsh6RK1ZrQ0VEyE3yzXcBu+K8ejVj4wuX32eUG02yNp+YQ==" }, "@types/uuid": { "version": "3.4.3", @@ -190,7 +348,7 @@ "integrity": "sha512-5fRLCYhLtDb3hMWqQyH10qtF+Ud2JnNCXTCZ+9ktNdCcgslcuXkDTkFcJNk++MT29yDntDnlF1+jD+uVGumsbw==", "dev": true, "requires": { - "@types/node": "9.6.15" + "@types/node": "10.3.0" } }, "JSONStream": { @@ -317,11 +475,6 @@ "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", "dev": true }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -347,6 +500,7 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, "requires": { "lodash": "4.17.10" } @@ -402,11 +556,6 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "base64url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", - "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" - }, "bcrypt-pbkdf": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", @@ -539,7 +688,8 @@ "buffer-from": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==" + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true }, "builtin-modules": { "version": "2.0.0", @@ -578,7 +728,8 @@ "capture-stack-trace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true }, "caseless": { "version": "0.12.0", @@ -824,6 +975,7 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, "requires": { "buffer-from": "1.0.0", "inherits": "2.0.3", @@ -1337,6 +1489,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, "requires": { "capture-stack-trace": "1.0.0" } @@ -1620,11 +1773,10 @@ } }, "ecdsa-sig-formatter": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", - "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", + "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", "requires": { - "base64url": "2.0.0", "safe-buffer": "5.1.2" } }, @@ -2332,15 +2484,21 @@ "ini": "1.3.5" } }, + "globals": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.5.0.tgz", + "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", + "dev": true + }, "google-auth-library": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-1.4.0.tgz", - "integrity": "sha512-vWRx6pJulK7Y5V/Xyr7MPMlx2mWfmrUVbcffZ7hpq8ElFg5S8WY6PvjMovdcr6JfuAwwpAX4R0I1XOcyWuBcUw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-1.5.0.tgz", + "integrity": "sha512-xpibA/hkq4waBcpIkSJg4GiDAqcBWjJee3c47zj7xP3RQ0A9mc8MP3Vc9sc8SGRoDYA0OszZxTjW7SbcC4pJIA==", "requires": { "axios": "0.18.0", "gcp-metadata": "0.6.3", "gtoken": "2.3.0", - "jws": "3.1.4", + "jws": "3.1.5", "lodash.isstring": "4.0.1", "lru-cache": "4.1.3", "retry-axios": "0.3.2" @@ -2357,17 +2515,6 @@ } } }, - "google-auto-auth": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/google-auto-auth/-/google-auto-auth-0.10.1.tgz", - "integrity": "sha512-iIqSbY7Ypd32mnHGbYctp80vZzXoDlvI9gEfvtl3kmyy5HzOcrZCIGCBdSlIzRsg7nHpQiHE3Zl6Ycur6TSodQ==", - "requires": { - "async": "2.6.0", - "gcp-metadata": "0.6.3", - "google-auth-library": "1.4.0", - "request": "2.85.0" - } - }, "google-p12-pem": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-1.0.2.tgz", @@ -2415,7 +2562,7 @@ "requires": { "axios": "0.18.0", "google-p12-pem": "1.0.2", - "jws": "3.1.4", + "jws": "3.1.5", "mime": "2.3.1", "pify": "3.0.0" }, @@ -2785,6 +2932,15 @@ } } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", @@ -2962,6 +3118,27 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-2.1.0.tgz", + "integrity": "sha512-3ly7GAJiPKqgbGKh2s01ysk3jd/egpE1i84PYu3BvPkssqrKMXZY9KRGX0mfZ+cmCfTR1IFVnnn/tDHxTer4nA==", + "dev": true, + "requires": { + "@babel/generator": "7.0.0-beta.49", + "@babel/parser": "7.0.0-beta.49", + "@babel/template": "7.0.0-beta.49", + "@babel/traverse": "7.0.0-beta.49", + "@babel/types": "7.0.0-beta.49", + "istanbul-lib-coverage": "1.2.0", + "semver": "5.5.0" + } + }, "js-green-licenses": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/js-green-licenses/-/js-green-licenses-0.5.0.tgz", @@ -3012,6 +3189,12 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + }, "jshint": { "version": "2.9.5", "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", @@ -3146,23 +3329,21 @@ } }, "jwa": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", - "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", + "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", "requires": { - "base64url": "2.0.0", "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.9", + "ecdsa-sig-formatter": "1.0.10", "safe-buffer": "5.1.2" } }, "jws": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", - "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", + "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", "requires": { - "base64url": "2.0.0", - "jwa": "1.1.5", + "jwa": "1.1.6", "safe-buffer": "5.1.2" } }, @@ -3263,7 +3444,8 @@ "lodash": { "version": "4.17.10", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true }, "lodash._reinterpolate": { "version": "3.0.0", @@ -3305,17 +3487,21 @@ "lodash._reinterpolate": "3.0.0" } }, - "log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" - }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", "dev": true }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -3400,11 +3586,6 @@ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, - "methmeth": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/methmeth/-/methmeth-1.1.0.tgz", - "integrity": "sha1-6AomYY5S9cQiKGG7dIUQvRDikIk=" - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -3518,11 +3699,6 @@ } } }, - "modelo": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/modelo/-/modelo-4.2.3.tgz", - "integrity": "sha512-9DITV2YEMcw7XojdfvGl3gDD8J9QjZTJ7ZOUuSAkP+F3T6rDbzMJuPktxptsdHYEvZcmXrCD3LMOhdSAEq6zKA==" - }, "modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", @@ -3625,9 +3801,9 @@ "dev": true }, "nyc": { - "version": "11.7.3", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.7.3.tgz", - "integrity": "sha512-40EtXYqklVP8nFtXtw6tziHV/FBfP2e0HENZc2kivMyzmOdkrp7ljKqpdjS8ubYWdzUMWlMnPDkbNMQeVd2Q5A==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-12.0.2.tgz", + "integrity": "sha1-ikpO1pCWbBHsWH/4fuoMEsl0upk=", "dev": true, "requires": { "archy": "1.0.0", @@ -3642,10 +3818,10 @@ "glob": "7.1.2", "istanbul-lib-coverage": "1.2.0", "istanbul-lib-hook": "1.1.0", - "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-instrument": "2.1.0", "istanbul-lib-report": "1.1.3", - "istanbul-lib-source-maps": "1.2.3", - "istanbul-reports": "1.4.0", + "istanbul-lib-source-maps": "1.2.5", + "istanbul-reports": "1.4.1", "md5-hex": "1.3.0", "merge-source-map": "1.1.0", "micromatch": "3.1.10", @@ -3675,12 +3851,7 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", + "version": "3.0.0", "bundled": true, "dev": true }, @@ -3737,92 +3908,6 @@ "bundled": true, "dev": true }, - "babel-code-frame": { - "version": "6.26.0", - "bundled": true, - "dev": true, - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "babel-generator": { - "version": "6.26.1", - "bundled": true, - "dev": true, - "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.10", - "source-map": "0.5.7", - "trim-right": "1.0.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "bundled": true, - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "bundled": true, - "dev": true, - "requires": { - "core-js": "2.5.6", - "regenerator-runtime": "0.11.1" - } - }, - "babel-template": { - "version": "6.26.0", - "bundled": true, - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.10" - } - }, - "babel-traverse": { - "version": "6.26.0", - "bundled": true, - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.4", - "lodash": "4.17.10" - } - }, - "babel-types": { - "version": "6.26.0", - "bundled": true, - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.10", - "to-fast-properties": "1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "bundled": true, - "dev": true - }, "balanced-match": { "version": "1.0.0", "bundled": true, @@ -3876,11 +3961,6 @@ "kind-of": "6.0.2" } }, - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, "kind-of": { "version": "6.0.2", "bundled": true, @@ -3943,13 +4023,6 @@ "to-object-path": "0.3.0", "union-value": "1.0.0", "unset-value": "1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - } } }, "caching-transform": { @@ -3978,18 +4051,6 @@ "lazy-cache": "1.0.4" } }, - "chalk": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, "class-utils": { "version": "0.3.6", "bundled": true, @@ -4008,11 +4069,6 @@ "requires": { "is-descriptor": "0.1.6" } - }, - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true } } }, @@ -4074,22 +4130,17 @@ "bundled": true, "dev": true }, - "core-js": { - "version": "2.5.6", - "bundled": true, - "dev": true - }, "cross-spawn": { "version": "4.0.2", "bundled": true, "dev": true, "requires": { "lru-cache": "4.1.3", - "which": "1.3.0" + "which": "1.3.1" } }, "debug": { - "version": "2.6.9", + "version": "3.1.0", "bundled": true, "dev": true, "requires": { @@ -4154,11 +4205,6 @@ "kind-of": "6.0.2" } }, - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, "kind-of": { "version": "6.0.2", "bundled": true, @@ -4166,14 +4212,6 @@ } } }, - "detect-indent": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "repeating": "2.0.1" - } - }, "error-ex": { "version": "1.3.1", "bundled": true, @@ -4182,16 +4220,6 @@ "is-arrayish": "0.2.1" } }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true, - "dev": true - }, - "esutils": { - "version": "2.0.2", - "bundled": true, - "dev": true - }, "execa": { "version": "0.7.0", "bundled": true, @@ -4213,7 +4241,7 @@ "requires": { "lru-cache": "4.1.3", "shebang-command": "1.2.0", - "which": "1.3.0" + "which": "1.3.1" } } } @@ -4232,8 +4260,16 @@ "to-regex": "3.0.2" }, "dependencies": { - "define-property": { - "version": "0.2.5", + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", "bundled": true, "dev": true, "requires": { @@ -4427,11 +4463,6 @@ "path-is-absolute": "1.0.1" } }, - "globals": { - "version": "9.18.0", - "bundled": true, - "dev": true - }, "graceful-fs": { "version": "4.1.11", "bundled": true, @@ -4458,19 +4489,6 @@ } } }, - "has-ansi": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, "has-value": { "version": "1.0.0", "bundled": true, @@ -4479,13 +4497,6 @@ "get-value": "2.0.6", "has-values": "1.0.0", "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - } } }, "has-values": { @@ -4497,24 +4508,6 @@ "kind-of": "4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "bundled": true, - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, "kind-of": { "version": "4.0.0", "bundled": true, @@ -4549,14 +4542,6 @@ "bundled": true, "dev": true }, - "invariant": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "loose-envify": "1.3.1" - } - }, "invert-kv": { "version": "1.0.0", "bundled": true, @@ -4618,14 +4603,6 @@ "bundled": true, "dev": true }, - "is-finite": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, "is-fullwidth-code-point": { "version": "2.0.0", "bundled": true, @@ -4660,13 +4637,6 @@ "dev": true, "requires": { "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - } } }, "is-stream": { @@ -4712,20 +4682,6 @@ "append-transform": "0.4.0" } }, - "istanbul-lib-instrument": { - "version": "1.10.1", - "bundled": true, - "dev": true, - "requires": { - "babel-generator": "6.26.1", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "istanbul-lib-coverage": "1.2.0", - "semver": "5.5.0" - } - }, "istanbul-lib-report": { "version": "1.1.3", "bundled": true, @@ -4737,6 +4693,11 @@ "supports-color": "3.2.3" }, "dependencies": { + "has-flag": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, "supports-color": { "version": "3.2.3", "bundled": true, @@ -4748,7 +4709,7 @@ } }, "istanbul-lib-source-maps": { - "version": "1.2.3", + "version": "1.2.5", "bundled": true, "dev": true, "requires": { @@ -4757,36 +4718,16 @@ "mkdirp": "0.5.1", "rimraf": "2.6.2", "source-map": "0.5.7" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "bundled": true, - "dev": true, - "requires": { - "ms": "2.0.0" - } - } } }, "istanbul-reports": { - "version": "1.4.0", + "version": "1.4.1", "bundled": true, "dev": true, "requires": { "handlebars": "4.0.11" } }, - "js-tokens": { - "version": "3.0.2", - "bundled": true, - "dev": true - }, - "jsesc": { - "version": "1.3.0", - "bundled": true, - "dev": true - }, "kind-of": { "version": "3.2.2", "bundled": true, @@ -4837,24 +4778,11 @@ } } }, - "lodash": { - "version": "4.17.10", - "bundled": true, - "dev": true - }, "longest": { "version": "1.0.1", "bundled": true, "dev": true }, - "loose-envify": { - "version": "1.3.1", - "bundled": true, - "dev": true, - "requires": { - "js-tokens": "3.0.2" - } - }, "lru-cache": { "version": "4.1.3", "bundled": true, @@ -5009,16 +4937,6 @@ "to-regex": "3.0.2" }, "dependencies": { - "arr-diff": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "bundled": true, - "dev": true - }, "kind-of": { "version": "6.0.2", "bundled": true, @@ -5081,13 +4999,6 @@ "dev": true, "requires": { "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - } } }, "object.pick": { @@ -5096,13 +5007,6 @@ "dev": true, "requires": { "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - } } }, "once": { @@ -5286,11 +5190,6 @@ } } }, - "regenerator-runtime": { - "version": "0.11.1", - "bundled": true, - "dev": true - }, "regex-not": { "version": "1.0.2", "bundled": true, @@ -5310,14 +5209,6 @@ "bundled": true, "dev": true }, - "repeating": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "is-finite": "1.0.2" - } - }, "require-directory": { "version": "2.1.1", "bundled": true, @@ -5433,10 +5324,18 @@ "extend-shallow": "2.0.1", "map-cache": "0.2.2", "source-map": "0.5.7", - "source-map-resolve": "0.5.1", + "source-map-resolve": "0.5.2", "use": "3.1.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "define-property": { "version": "0.2.5", "bundled": true, @@ -5499,11 +5398,6 @@ "kind-of": "6.0.2" } }, - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, "kind-of": { "version": "6.0.2", "bundled": true, @@ -5525,7 +5419,7 @@ "dev": true }, "source-map-resolve": { - "version": "0.5.1", + "version": "0.5.2", "bundled": true, "dev": true, "requires": { @@ -5551,7 +5445,7 @@ "os-homedir": "1.0.2", "rimraf": "2.6.2", "signal-exit": "3.0.2", - "which": "1.3.0" + "which": "1.3.1" } }, "spdx-correct": { @@ -5616,29 +5510,14 @@ "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } } }, "strip-ansi": { - "version": "3.0.1", + "version": "4.0.0", "bundled": true, "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "3.0.0" } }, "strip-bom": { @@ -5654,11 +5533,6 @@ "bundled": true, "dev": true }, - "supports-color": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, "test-exclude": { "version": "4.2.1", "bundled": true, @@ -5669,263 +5543,8 @@ "object-assign": "4.1.1", "read-pkg-up": "1.0.1", "require-main-filename": "1.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "bundled": true, - "dev": true - }, - "braces": { - "version": "2.3.2", - "bundled": true, - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.2", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "bundled": true, - "dev": true, - "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "bundled": true, - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "bundled": true, - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "bundled": true, - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "bundled": true, - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "bundled": true, - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "bundled": true, - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - } - }, - "kind-of": { - "version": "5.1.0", - "bundled": true, - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "extend-shallow": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "bundled": true, - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "bundled": true, - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "bundled": true, - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.9", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - } } }, - "to-fast-properties": { - "version": "1.0.3", - "bundled": true, - "dev": true - }, "to-object-path": { "version": "0.3.0", "bundled": true, @@ -5952,23 +5571,8 @@ "requires": { "is-number": "3.0.0", "repeat-string": "1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "bundled": true, - "dev": true, - "requires": { - "kind-of": "3.2.2" - } - } } }, - "trim-right": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, "uglify-js": { "version": "2.8.29", "bundled": true, @@ -6065,11 +5669,6 @@ "version": "0.1.4", "bundled": true, "dev": true - }, - "isobject": { - "version": "3.0.1", - "bundled": true, - "dev": true } } }, @@ -6103,7 +5702,7 @@ } }, "which": { - "version": "1.3.0", + "version": "1.3.1", "bundled": true, "dev": true, "requires": { @@ -6135,6 +5734,11 @@ "strip-ansi": "3.0.1" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, @@ -6152,6 +5756,14 @@ "is-fullwidth-code-point": "1.0.0", "strip-ansi": "3.0.1" } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } } } }, @@ -6199,11 +5811,6 @@ "yargs-parser": "9.0.2" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, "camelcase": { "version": "4.1.0", "bundled": true, @@ -6219,14 +5826,6 @@ "wrap-ansi": "2.1.0" } }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, "yargs-parser": { "version": "9.0.2", "bundled": true, @@ -7017,11 +6616,10 @@ } }, "split-array-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/split-array-stream/-/split-array-stream-1.0.3.tgz", - "integrity": "sha1-0rdajl4Ngk1S/eyLgiWDncLjXfo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/split-array-stream/-/split-array-stream-2.0.0.tgz", + "integrity": "sha512-hmMswlVY91WvGMxs0k8MRgq8zb2mSen4FmDNc5AFiTWtrBpdZN6nwD6kROVe4vNL+ywrvbCKsWVCnEd4riELIg==", "requires": { - "async": "2.6.0", "is-stream-ended": "0.1.4" } }, @@ -7102,11 +6700,6 @@ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" }, - "string-format-obj": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string-format-obj/-/string-format-obj-1.1.1.tgz", - "integrity": "sha512-Mm+sROy+pHJmx0P/0Bs1uxIX6UhGJGj6xDGQZ5zh9v/SZRmLGevp+p0VJxV7lirrkAmQ2mvva/gHKpnF/pTb+Q==" - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -7242,6 +6835,12 @@ "os-tmpdir": "1.0.2" } }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", @@ -7262,6 +6861,12 @@ "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", "dev": true }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, "ts-node": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-6.0.3.tgz", @@ -7414,7 +7019,8 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true }, "typescript": { "version": "2.7.2", diff --git a/package.json b/package.json index 5a79478a5..f31dde483 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "typescript": "~2.7.2" }, "dependencies": { - "@google-cloud/common": "^0.17.0", + "@google-cloud/common": "^0.19.1", "builtin-modules": "^2.0.0", "continuation-local-storage": "^3.2.1", "extend": "^3.0.0", diff --git a/src/trace-writer.ts b/src/trace-writer.ts index 844177680..8d331204e 100644 --- a/src/trace-writer.ts +++ b/src/trace-writer.ts @@ -36,7 +36,7 @@ headers[Constants.TRACE_AGENT_REQUEST_HEADER] = 1; /* A list of scopes needed to operate with the trace API */ const SCOPES: string[] = ['https://www.googleapis.com/auth/trace.append']; -export interface TraceWriterConfig extends common.ServiceAuthenticationConfig { +export interface TraceWriterConfig extends common.GoogleAuthOptions { projectId?: string; onUncaughtException: string; bufferSize: number; @@ -82,7 +82,9 @@ export class TraceWriter extends common.Service { config); this.logger = logger; - this.config = config; + // Clone the config object + this.config = {...config}; + this.config.serviceContext = {...this.config.serviceContext}; this.buffer = []; this.defaultLabels = {}; @@ -121,22 +123,21 @@ export class TraceWriter extends common.Service { // Schedule periodic flushing of the buffer, but only if we are able to get // the project number (potentially from the network.) - this.getProjectId((err: Error|null, project?: string) => { - if (err) { - this.logger.error( - 'TraceWriter#initialize: Unable to acquire the project number', - 'automatically from the GCP metadata service. Please provide a', - 'valid project ID as environmental variable GCLOUD_PROJECT, or as', - `config.projectId passed to start. Original error: ${err}`); - cb(err); - } else { - this.config.projectId = project; - this.scheduleFlush(); - if (--pendingOperations === 0) { - cb(); - } - } - }); + this.getProjectId().then( + () => { + this.scheduleFlush(); + if (--pendingOperations === 0) { + cb(); + } + }, + (err: Error) => { + this.logger.error( + 'TraceWriter#initialize: Unable to acquire the project number', + 'automatically from the GCP metadata service. Please provide a', + 'valid project ID as environmental variable GCLOUD_PROJECT, or as', + `config.projectId passed to start. Original error: ${err}`); + cb(err); + }); this.getHostname((hostname) => { this.getInstanceId((instanceId) => { @@ -212,27 +213,14 @@ export class TraceWriter extends common.Service { }); } - /** - * Returns the project ID if it has been cached and attempts to load - * it from the enviroment or network otherwise. - */ - getProjectId(cb: (err: Error|null, projectId?: string) => void) { + getProjectId() { if (this.config.projectId) { - cb(null, this.config.projectId); - return; + return Promise.resolve(this.config.projectId); } - - gcpMetadata.project({property: 'project-id', headers}) - .then((res) => { - cb(null, res.data); // project ID - }) - .catch((err: AxiosError) => { - if (err.response && err.response.status === 503) { - err.message += - ' This may be due to a temporary server error; please try again later.'; - } - cb(err); - }); + return super.getProjectId().then((projectId) => { + this.config.projectId = projectId; + return projectId; + }); } /** @@ -264,14 +252,7 @@ export class TraceWriter extends common.Service { * @param trace The trace to be queued. */ queueTrace(trace: Trace) { - this.getProjectId((err, projectId?) => { - if (err || !projectId) { - this.logger.info( - 'TraceWriter#queueTrace: No project ID, dropping trace.'); - return; // if we even reach this point, disabling traces is already - // imminent. - } - + const afterProjectId = (projectId: string) => { trace.projectId = projectId; this.buffer.push(JSON.stringify(trace)); this.logger.info( @@ -283,7 +264,23 @@ export class TraceWriter extends common.Service { 'TraceWriter#queueTrace: Trace buffer full, flushing.'); setImmediate(() => this.flushBuffer()); } - }); + }; + // TODO(kjin): We should always be following the 'else' path. + // Any test that doesn't mock the Trace Writer will assume that traces get + // buffered synchronously. We need to refactor those tests to remove that + // assumption before we can make this fix. + if (this.config.projectId) { + afterProjectId(this.config.projectId); + } else { + this.getProjectId().then(afterProjectId, (err: Error) => { + // Because failing to get a project ID means that the trace agent will + // get disabled, there is a very small window for this code path to be + // taken. For this reason we don't do anything more complex than just + // notifying that we are dropping the current trace. + this.logger.info( + 'TraceWriter#queueTrace: No project ID, dropping trace.'); + }); + } } /** diff --git a/src/tracing.ts b/src/tracing.ts index 343b0bc65..dfe7a54d3 100644 --- a/src/tracing.ts +++ b/src/tracing.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import * as common from '@google-cloud/common'; +import {Logger, logger} from '@google-cloud/common'; import * as path from 'path'; import * as semver from 'semver'; @@ -42,7 +42,7 @@ export type NormalizedConfig = */ export class Tracing implements Component { /** A logger. */ - private readonly logger: common.Logger; + private readonly logger: Logger; /** The configuration object for this instance. */ private readonly config: Forceable; @@ -56,15 +56,16 @@ export class Tracing implements Component { this.config = config; let logLevel = config.enabled ? config.logLevel : 0; // Clamp the logger level. + // TODO(kjin): When @google-cloud/common@0.19.2 is released, use + // Logger.LEVELS instead. + const defaultLevels = logger.LEVELS; if (logLevel < 0) { logLevel = 0; - } else if (logLevel >= common.logger.LEVELS.length) { - logLevel = common.logger.LEVELS.length - 1; + } else if (logLevel >= defaultLevels.length) { + logLevel = defaultLevels.length - 1; } - this.logger = common.logger({ - level: common.logger.LEVELS[logLevel], - tag: '@google-cloud/trace-agent' - }); + this.logger = new Logger( + {level: defaultLevels[logLevel], tag: '@google-cloud/trace-agent'}); } diff --git a/src/types.d.ts b/src/types.d.ts index 50f6b0fe1..4ea61622a 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,5 +1,3 @@ -// TODO(kjin): Unify these definitions with those of the Debugger Agent. - declare namespace NodeJS { export interface Global { _google_trace_agent: any; @@ -18,58 +16,6 @@ declare namespace NodeJS { } } -declare module '@google-cloud/common' { - import * as request from 'request'; - - type LogFunction = (message: any, ...args: any[]) => void; - - export interface Logger { - error: LogFunction; - warn: LogFunction; - info: LogFunction; - debug: LogFunction; - silly: LogFunction; - } - - export interface LoggerOptions { - level?: string; - levels?: string[]; - tag?: string; - } - - export const logger: { - (options?: LoggerOptions | string): Logger; - LEVELS: string[]; - }; - - export class Service { - constructor(config: ServiceConfig, options: ServiceAuthenticationConfig); - request(options: request.Options, - cb: ( - err: Error | null, - body: any, - response: request.RequestResponse - ) => void): void; - } - - export interface ServiceConfig { - packageJson?: any; - projectIdRequired?: boolean; - baseUrl?: string; - scopes?: string[]; - } - - export interface ServiceAuthenticationConfig { - projectId?: string; - keyFilename?: string; - email?: string; - credentials?: { - client_email?: string; - private_key?: string; - }; - } -} - declare module 'require-in-the-middle' { namespace hook { type Options = { diff --git a/test/logger.ts b/test/logger.ts index b7ce4c178..17977d9c8 100644 --- a/test/logger.ts +++ b/test/logger.ts @@ -14,26 +14,35 @@ * limitations under the License. */ -import {Logger, logger} from '@google-cloud/common'; +import {Logger, logger, LoggerConfig} from '@google-cloud/common'; const PASS_THROUGH_LOG_LEVEL = Number(process.env.GCLOUD_TEST_LOG_LEVEL || 0); +// Capture the value of common.Logger so that we don't enter an infinite loop +// if common.Logger is wrapped elsewhere. +// tslint:disable-next-line:variable-name +const OriginalLogger = Logger; // tslint:disable-next-line:no-any -type LoggerFunction = (message: any, ...args: any[]) => void; +type LoggerFunction = (message: any, ...args: any[]) => R; -export class TestLogger implements Logger { - private logs: - {[k in keyof Logger]: - string[]} = {error: [], warn: [], info: [], debug: [], silly: []}; - private innerLogger = logger({level: logger.LEVELS[PASS_THROUGH_LOG_LEVEL]}); +export class TestLogger extends Logger { + private logs: {[k in keyof Logger]: string[]} = + {silent: [], error: [], warn: [], info: [], debug: [], silly: []}; + private innerLogger = + new OriginalLogger({level: logger.LEVELS[PASS_THROUGH_LOG_LEVEL]}); - private makeLoggerFn(logLevel: keyof Logger): LoggerFunction { + constructor(options?: Partial) { + super(options); + } + + private makeLoggerFn(logLevel: keyof Logger): LoggerFunction { // TODO(kjin): When we drop support for Node 4, use spread args. const that = this; return function(this: null) { const args = Array.prototype.slice.call(arguments, 0); that.logs[logLevel].push(args.join(' ')); that.innerLogger[logLevel].apply(this, args); + return that; }; } diff --git a/test/test-agent-stopped.ts b/test/test-agent-stopped.ts index b8facefe0..b9b8171ad 100644 --- a/test/test-agent-stopped.ts +++ b/test/test-agent-stopped.ts @@ -14,39 +14,34 @@ * limitations under the License. */ -'use strict'; +import * as assert from 'assert'; +import * as http from 'http'; +import * as traceTestModule from './trace'; +import { pluginLoader, PluginLoaderState } from '../src/trace-plugin-loader'; +import { TraceWriter } from '../src/trace-writer'; +import { TraceAgent } from '../src/trace-api'; -import './override-gcp-metadata'; +describe('test-agent-stopped', () => { + class InitErrorTraceWriter extends TraceWriter { + getProjectId() { + return Promise.reject(new Error('foo')); + } + } -var assert = require('assert'); -var http = require('http'); -var nock = require('nock'); -var trace = require('../..'); -var pluginLoader = require('../src/trace-plugin-loader').pluginLoader; -var PluginLoaderState = require('../src/trace-plugin-loader').PluginLoaderState; - -describe('test-agent-stopped', function() { - var agent; - var savedProject; - - before(function(done) { - savedProject = process.env.GCLOUD_PROJECT; - - var scope = nock('http://metadata.google.internal') - .get('/computeMetadata/v1/project/project-id') - .reply(404); - delete process.env.GCLOUD_PROJECT; - agent = trace.start(); - // Wait 200ms for agent to fail getting remote project id. - setTimeout(function() { - assert.ok(!agent.isActive()); - scope.done(); + before((done) => { + traceTestModule.setPluginLoaderForTest(); + traceTestModule.setTraceWriterForTest(InitErrorTraceWriter); + traceTestModule.start(); + // Wait for agent to fail getting remote project id. + setImmediate(() => { + assert.ok(!(traceTestModule.get() as TraceAgent).isActive()); done(); - }, 200); + }); }); - after(function() { - process.env.GCLOUD_PROJECT = savedProject; + after(() => { + traceTestModule.setPluginLoaderForTest(traceTestModule.TestPluginLoader); + traceTestModule.setTraceWriterForTest(traceTestModule.TestTraceWriter); }); it('deactivates the plugin loader', () => { @@ -55,7 +50,6 @@ describe('test-agent-stopped', function() { describe('express', function() { it('should not break if no project number is found', function(done) { - assert.ok(!agent.isActive()); var app = require('./plugins/fixtures/express4')(); app.get('/', function (req, res) { res.send('hi'); @@ -76,7 +70,6 @@ describe('test-agent-stopped', function() { describe('hapi', function() { it('should not break if no project number is found', function(done) { - assert.ok(!agent.isActive()); var hapi = require('./plugins/fixtures/hapi8'); var server = new hapi.Server(); server.connection({ port: 8081 }); @@ -103,7 +96,6 @@ describe('test-agent-stopped', function() { describe('restify', function() { it('should not break if no project number is found', function(done) { - assert.ok(!agent.isActive()); var restify = require('./plugins/fixtures/restify4'); var server = restify.createServer(); server.get('/', function (req, res, next) { @@ -128,5 +120,3 @@ describe('test-agent-stopped', function() { }); }); }); - -export default {}; diff --git a/test/test-default-ignore-ah-health.ts b/test/test-default-ignore-ah-health.ts index 59342b980..4c88bfc03 100644 --- a/test/test-default-ignore-ah-health.ts +++ b/test/test-default-ignore-ah-health.ts @@ -13,42 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use strict'; -var assert = require('assert'); -var http = require('http'); +import * as assert from 'assert'; -var common = require('./plugins/common'/*.js*/); +import * as trace from './trace'; -describe('test-default-ignore-ah-health', function() { - var agent; - var express; - before(function() { - agent = require('../..').start({ - projectId: '0', - samplingRate: 0 - }); - express = require('express'); - }); - - it('should ignore /_ah/health traces by default', function(done) { - var app = express(); - app.get('/_ah/health', function (req, res) { - res.send('🏥'); - }); - var server = app.listen(9042, function() { - http.get({port: 9042, path: '/_ah/health'}, function(res) { - var result = ''; - res.on('data', function(data) { result += data; }); - res.on('end', function() { - assert.equal(result, '🏥'); - assert.equal(common.getTraces().length, 0); - server.close(); - done(); - }); - }); +describe('Trace API', () => { + it('should ignore /_ah/health traces by default', () => { + const traceApi = trace.start(); + traceApi.runInRootSpan({name: 'root', url: '/_ah/health'}, (rootSpan) => { + assert.strictEqual(rootSpan.type, traceApi.spanTypes.UNTRACED); }); }); }); - -export default {}; diff --git a/test/test-env-log-level.ts b/test/test-env-log-level.ts index 88f6f004c..f596674cb 100644 --- a/test/test-env-log-level.ts +++ b/test/test-env-log-level.ts @@ -14,58 +14,60 @@ * limitations under the License. */ -'use strict'; +import * as common from '@google-cloud/common'; +import * as assert from 'assert'; +import * as shimmer from 'shimmer'; import {FORCE_NEW} from '../src/util'; -var assert = require('assert'); -var gcloudCommon = require('@google-cloud/common'); -var shimmer = require('shimmer'); -var trace = require('../..'); +import {TestLogger} from './logger'; +import * as traceTestModule from './trace'; -describe('should respect environment variables', function() { - var logLevel; +describe('should respect environment variables', () => { + let logLevel: string|null = null; - before(function() { + class CaptureLogLevelTestLogger extends TestLogger { + constructor(opts: {level: string|false}) { + super(opts); + if (opts.level === false) { + throw new Error('Unexpected value for opts.level'); + } + logLevel = opts.level; + } + } + + before(() => { process.env.GCLOUD_TRACE_LOGLEVEL = '4'; // Wrap logger constructor so that the log level (string) is saved // in logLevel - shimmer.wrap(gcloudCommon, 'logger', function(original) { - var wrapped = Object.assign(function(options) { - logLevel = options.level; - return original.apply(this, arguments); - }, original); - return wrapped; - }); + shimmer.wrap(common, 'Logger', () => CaptureLogLevelTestLogger); }); - after(function() { + after(() => { delete process.env.GCLOUD_TRACE_LOGLEVEL; - shimmer.unwrap(gcloudCommon, 'logger'); + shimmer.unwrap(common, 'logger'); }); - afterEach(function() { + afterEach(() => { logLevel = null; }); - it('should respect GCLOUD_TRACE_LOGLEVEL', function() { - trace.start({[FORCE_NEW]: true}); - assert.strictEqual(logLevel, gcloudCommon.logger.LEVELS[4]); + it('should respect GCLOUD_TRACE_LOGLEVEL', () => { + traceTestModule.start(); + assert.strictEqual(logLevel, common.logger.LEVELS[4]); }); - it('should prefer env to config', function() { - trace.start({logLevel: 2, [FORCE_NEW]: true}); - assert.strictEqual(logLevel, gcloudCommon.logger.LEVELS[4]); + it('should prefer env to config', () => { + traceTestModule.start({logLevel: 2}); + assert.strictEqual(logLevel, common.logger.LEVELS[4]); }); - it('should fix out of bounds log level', function() { + it('should fix out of bounds log level', () => { process.env.GCLOUD_TRACE_LOGLEVEL = '-5'; - trace.start({[FORCE_NEW]: true}); - assert.strictEqual(logLevel, gcloudCommon.logger.LEVELS[0]); + traceTestModule.start(); + assert.strictEqual(logLevel, common.logger.LEVELS[0]); process.env.GCLOUD_TRACE_LOGLEVEL = '300'; - trace.start({[FORCE_NEW]: true}); - assert.strictEqual(logLevel, gcloudCommon.logger.LEVELS[5]); + traceTestModule.start(); + assert.strictEqual(logLevel, common.logger.LEVELS[5]); }); }); - -export default {}; diff --git a/test/test-index.ts b/test/test-index.ts index dade99d1f..d9d434208 100644 --- a/test/test-index.ts +++ b/test/test-index.ts @@ -66,40 +66,6 @@ describe('index.js', function() { assert.equal(global._google_trace_agent, agent); }); }); - - it('should stop if TraceWriter fails to initialize', function(done) { - var envProjectId = process.env.GCLOUD_PROJECT; - delete process.env.GCLOUD_PROJECT; - nock.disableNetConnect(); - var scope = nock('http://metadata.google.internal') - .get('/computeMetadata/v1/project/project-id') - .times(1) - .reply(404, 'foo'); - var agent = trace.start({logLevel: 0, [FORCE_NEW]: true}); - setTimeout(function() { - assert.ok(!agent.isActive()); - scope.done(); - process.env.GCLOUD_PROJECT = envProjectId; - done(); - }, 500); - }); - - it('should allow project ID to be read after discovery', function(done) { - var envProjectId = process.env.GCLOUD_PROJECT; - delete process.env.GCLOUD_PROJECT; - - nocks.projectId(function() { return 'project1'; }); - nocks.hostname(function() { return 'host1'; }); - nocks.instanceId(function() { return 'instance1'; }); - - var agent = trace.start({logLevel: 0, [FORCE_NEW]: true}); - - setTimeout(function() { - assert.strictEqual(agent.getWriterProjectId(), 'project1'); - process.env.GCLOUD_PROJECT = envProjectId; - done(); - }, 500); - }); }); export default {}; diff --git a/test/test-modules-loaded-before-agent.ts b/test/test-modules-loaded-before-agent.ts index 3a9a7ceaf..5ade8767d 100644 --- a/test/test-modules-loaded-before-agent.ts +++ b/test/test-modules-loaded-before-agent.ts @@ -22,17 +22,21 @@ import {TestLogger} from './logger'; import * as testTraceModule from './trace'; describe('modules loaded before agent', () => { - const logger = new TestLogger(); + let logger: CaptureTestLogger; + + class CaptureTestLogger extends TestLogger { + constructor() { + super(); + logger = this; + } + } before(() => { - const LEVELS = common.logger.LEVELS; - shimmer.wrap(common, 'logger', () => { - return Object.assign(() => logger, {LEVELS}); - }); + shimmer.wrap(common, 'Logger', () => CaptureTestLogger); }); after(() => { - shimmer.unwrap(common, 'logger'); + shimmer.unwrap(common, 'Logger'); }); it('should log if modules were loaded before agent', () => { diff --git a/test/test-no-self-tracing.ts b/test/test-no-self-tracing.ts index 1a8509564..05df84950 100644 --- a/test/test-no-self-tracing.ts +++ b/test/test-no-self-tracing.ts @@ -32,11 +32,9 @@ nock.disableNetConnect(); describe('test-no-self-tracing', function() { it('should not trace metadata queries', function(done) { - delete process.env.GCLOUD_PROJECT; var scope = nock('http://metadata.google.internal') .get('/computeMetadata/v1/instance/hostname').reply(200) - .get('/computeMetadata/v1/instance/id').reply(200) - .get('/computeMetadata/v1/project/project-id').reply(200); + .get('/computeMetadata/v1/instance/id').reply(200); require('../..').start({[FORCE_NEW]: true}); require('http'); // Must require http to force patching of the module var oldWarn = common.replaceWarnLogger(newWarn); @@ -53,6 +51,7 @@ describe('test-no-self-tracing', function() { .get('/computeMetadata/v1/instance/id').reply(200); var apiScope = nock('https://cloudtrace.googleapis.com') .patch('/v1/projects/0/traces').reply(200); + delete process.env.GCLOUD_PROJECT; require('../..').start({ projectId: '0', bufferSize: 1, diff --git a/test/test-plugin-loader.ts b/test/test-plugin-loader.ts index 5d8d612c5..e1fdd706c 100644 --- a/test/test-plugin-loader.ts +++ b/test/test-plugin-loader.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import {Logger} from '@google-cloud/common'; import * as assert from 'assert'; import * as path from 'path'; import * as hook from 'require-in-the-middle'; diff --git a/test/test-trace-uncaught-exception.ts b/test/test-trace-uncaught-exception.ts index 8080b972e..1a595ae59 100644 --- a/test/test-trace-uncaught-exception.ts +++ b/test/test-trace-uncaught-exception.ts @@ -14,82 +14,92 @@ * limitations under the License. */ -'use strict'; +import {Logger} from '@google-cloud/common'; +import * as assert from 'assert'; -import { cls, TraceCLS } from '../src/cls'; +import {TraceWriterConfig} from '../src/trace-writer'; -var assert = require('assert'); -var nock = require('nock'); -var common = require('./plugins/common'/*.js*/); -var trace = require('../..'); +import {TestLogger} from './logger'; +import * as trace from './trace'; -nock.disableNetConnect(); +/** + * Removes all global uncaught exception listeners, returning a function that, + * when run, undoes this removal. + */ +function removeAllUncaughtExceptionListeners() { + const listeners = process.listeners('uncaughtException'); + process.removeAllListeners('uncaughtException'); + return () => { + listeners.forEach( + listener => process.addListener('uncaughtException', listener)); + }; +} -var uri = 'https://cloudtrace.googleapis.com'; -var path = '/v1/projects/0/traces'; +describe('Trace Writer', () => { + const autoQueuedTrace = {traceId: '0', spans: [], projectId: '0'}; + let capturedPublishedTraces: string; + let capturedLogger: CaptureInstanceTestLogger; -var queueSpans = function(n, agent) { - for (var i = 0; i < n; i++) { - common.runInTransaction(function(end) { - end(); - }); + class CaptureInstanceTestLogger extends TestLogger { + constructor() { + super(); + capturedLogger = this; + } } -}; -describe('tracewriter publishing', function() { - var savedProject; + class CapturePublishedTracesTestTraceWriter extends trace.TestTraceWriter { + constructor(config: TraceWriterConfig, logger: Logger) { + super(config, logger); + // Don't run the risk of auto-flushing + this.getConfig().bufferSize = Infinity; + this.queueTrace(autoQueuedTrace); + } + + publish(json: string) { + capturedPublishedTraces = json; + } + } - before(function() { - savedProject = process.env.GCLOUD_PROJECT; - process.env.GCLOUD_PROJECT = '0'; + before(() => { + trace.setTraceWriterForTest(CapturePublishedTracesTestTraceWriter); + trace.setLoggerForTest(CaptureInstanceTestLogger); }); - after(function() { - process.env.GCLOUD_PROJECT = savedProject; + after(() => { + trace.setTraceWriterForTest(trace.TestTraceWriter); + trace.setLoggerForTest(TestLogger); }); - it('should publish on unhandled exception', function(done) { - var agent; - var buf; - var listeners = process.listeners('uncaughtException'); - process.removeAllListeners('uncaughtException'); - var scope = nock(uri) - .intercept(path, 'PATCH', function(body) { - assert.equal(JSON.stringify(body.traces), JSON.stringify(buf)); - return true; - }).reply(200); - process.once('uncaughtException', function() { - setTimeout(function() { - process.removeAllListeners('uncaughtException'); - listeners.forEach(function (l) { - process.addListener('uncaughtException', l) - }); - scope.done(); - done(); - }, 200); - }); - process.nextTick(function() { - agent = trace.start({ - bufferSize: 1000, - samplingRate: 0, - onUncaughtException: 'flush' - }); - common.avoidTraceWriterAuth(); - cls.get().runWithContext(function() { - queueSpans(2, agent); - buf = common.getTraces(); - throw new Error(':('); - }, TraceCLS.UNCORRELATED); - }); + it(`should publish on unhandled exception for 'flush' config option`, + (done) => { + const restoreOriginalUncaughtExceptionListeners = + removeAllUncaughtExceptionListeners(); + const traceApi = trace.start({onUncaughtException: 'flush'}); + setImmediate(() => { + setImmediate(() => { + removeAllUncaughtExceptionListeners(); + restoreOriginalUncaughtExceptionListeners(); + assert.strictEqual( + capturedPublishedTraces, + JSON.stringify({traces: [autoQueuedTrace]})); + done(); + }); + throw new Error(); + }); + }); + + it(`should not assign an oUE listener for 'ignore' config option`, () => { + const restoreOriginalUncaughtExceptionListeners = + removeAllUncaughtExceptionListeners(); + trace.start({onUncaughtException: 'ignore'}); + assert.strictEqual(process.listenerCount('onHandledException'), 0); + restoreOriginalUncaughtExceptionListeners(); }); - it('should error on invalid config values', function() { - assert.throws(function() { - trace.start({ - onUncaughtException: 'invalidValue' - }); - }); + it('should log and disable on invalid config values', () => { + trace.start({onUncaughtException: 'invalidValue'}); + assert.ok(capturedLogger); + assert.strictEqual( + capturedLogger.getNumLogsWith('error', 'Disabling the Trace Agent'), 1); }); }); - -export default {}; diff --git a/test/test-trace-writer.ts b/test/test-trace-writer.ts index 6b8a212de..dfb5852cf 100644 --- a/test/test-trace-writer.ts +++ b/test/test-trace-writer.ts @@ -14,329 +14,318 @@ * limitations under the License. */ -'use strict'; +import {Service} from '@google-cloud/common'; +import * as assert from 'assert'; +import {OutgoingHttpHeaders} from 'http'; +import * as nock from 'nock'; +import * as os from 'os'; +import {Response} from 'request'; +import * as shimmer from 'shimmer'; -// Loading this file patches gcpMetadata so requests don't time out. -import './override-gcp-metadata'; -import {FORCE_NEW} from '../src/util'; -import { Trace, SpanKind } from '../src/trace'; -import { TraceLabels } from '../src/trace-labels'; -import { traceWriter, TraceWriter, TraceWriterConfig } from '../src/trace-writer'; +import {SpanKind, Trace} from '../src/trace'; +import {TraceLabels} from '../src/trace-labels'; +import {TraceWriter, TraceWriterConfig} from '../src/trace-writer'; -var assert = require('assert'); -var fakeCredentials = require('./fixtures/gcloud-credentials.json'); -var nock = require('nock'); -var nocks = require('./nocks'/*.js*/); -var os = require('os'); -var Service = require('@google-cloud/common').Service; +import {TestLogger} from './logger'; +import {hostname, instanceId, oauth2} from './nocks'; +import {wait} from './utils'; -type createTraceWriterOptions = TraceWriterConfig & { [FORCE_NEW]: boolean }; - -interface TestCase { - description: string, - config: any, - metadata: { - projectId?: string, - hostname?: string, - instanceId?: string - }, - assertResults: (err?: Error | null, tw?: any) => void +interface DecorateRequestOptions { + method: string; + uri: string; + body: string; + headers: OutgoingHttpHeaders; } -nock.disableNetConnect(); - -var PROJECT = 'fake-project'; -var DEFAULT_DELAY = 200; - -var fakeLogger = { - warn: () => {}, - info: () => {}, - error: () => {}, - debug: () => {}, - silly: () => {} -}; +/** + * Set up nocks to simulate no metadata server. + * Returns an object where calling done() can assert that endpoints were hit, + * unless cancel() was called first. + */ +function mockNoMetadata() { + const scopes = [instanceId, hostname].map(f => f(404)); + let cancelled = false; + return { + done: () => cancelled || scopes.forEach(s => s.done()), + cancel: () => cancelled = true + }; +} -function createFakeTrace(name): Trace { - // creates a fake span. +function createDummyTrace(): Trace { return { - spans: [ - { - labels: {}, - name: name, - startTime: (new Date()).toISOString(), - endTime: '', - kind: SpanKind.RPC_SERVER, - spanId: '', - parentSpanId: '' - } - ], projectId: '', - traceId: '' + traceId: '', + spans: [{ + labels: {}, + startTime: '', + endTime: '', + kind: SpanKind.RPC_SERVER, + name: '', + spanId: '' + }] }; } -describe('TraceWriter', function() { - it('should be a Service instance', function() { - var writer = traceWriter.create({ - projectId: 'fake project', - serviceContext: {}, - onUncaughtException: 'ignore', - [FORCE_NEW]: true - } as createTraceWriterOptions, fakeLogger); - assert.ok(writer instanceof Service); +describe('Trace Writer', () => { + const pjson = require('../../package.json'); + const DEFAULT_CONFIG: TraceWriterConfig = { + onUncaughtException: 'ignore', + bufferSize: Infinity, + flushDelaySeconds: 3600, + stackTraceLimit: 10, + maximumLabelValueSize: 1 << 16, + serviceContext: {} + }; + const logger = new TestLogger(); + // By default, this is always assigned so that a project ID of '0' is yielded. + // We override this when we want a different value. + let getProjectIdOverride: () => Promise; + // Currently, each individual test always both constructs and initializes + // a new TraceWriter instance. For that reason we always keep the oauth2 + // endpoint nocked... + let oauth2Scope: nock.Scope; + // ...and allow one query to each of the two metadata endpoints per test. + let metadataScopes: {done: () => void, cancel: () => void}; + + before(() => { + nock.disableNetConnect(); + oauth2Scope = oauth2().persist(); + shimmer.wrap( + Service.prototype, 'getProjectId', () => () => getProjectIdOverride()); }); - - it('should not attach exception handler with ignore option', function() { - // In Node 9+, this should be 1. - // Otherwise, it should be 0. - const numListenersBeforeTraceWriter = process.listeners('uncaughtException').length; - traceWriter.create({ - projectId: '0', - serviceContext: {}, - onUncaughtException: 'ignore', - [FORCE_NEW]: true - } as createTraceWriterOptions, fakeLogger); - // Mocha attaches 1 exception handler - assert.equal(process.listeners('uncaughtException').length, numListenersBeforeTraceWriter); + + after(() => { + shimmer.unwrap(Service.prototype, 'getProjectId'); + oauth2Scope.done(); // It will likely be called at least once + nock.enableNetConnect(); }); - describe('writeSpan', function() { - it('should close spans, add defaultLabels and queue', function(done) { - var writer = traceWriter.create({ - projectId: PROJECT, - bufferSize: 4, - serviceContext: {}, - onUncaughtException: 'ignore', - [FORCE_NEW]: true - } as createTraceWriterOptions, fakeLogger); - writer.initialize(function() { - var spanData = createFakeTrace('fake span'); - writer.defaultLabels = { - fakeKey: 'value' - }; - writer.queueTrace = function(trace) { - assert.ok(trace && trace.spans && trace.spans[0]); - var span = trace.spans[0]; - assert.strictEqual(span.name, 'fake span'); - assert.ok(span.endTime); - assert.strictEqual(span.labels.fakeKey, 'value'); - // TODO(ofrobots): check serviceContext labels as well. - done(); - }; - writer.writeSpan(spanData); - }); - }); + beforeEach(() => { + getProjectIdOverride = () => Promise.resolve('0'); + metadataScopes = mockNoMetadata(); + logger.clearLogs(); }); - describe('publish', function() { - it('should submit a PATCH request to the API', function(done) { - nocks.oauth2(); - var scope = nocks.patchTraces(PROJECT); + afterEach(() => { + metadataScopes.done(); + nock.cleanAll(); + }); - var writer = traceWriter.create({ - projectId: PROJECT, - credentials: fakeCredentials, - serviceContext: {}, - onUncaughtException: 'ignore', - [FORCE_NEW]: true - } as createTraceWriterOptions, fakeLogger); - writer.publish('{"valid": "json"}'); - setTimeout(function() { - assert.ok(scope.isDone()); + describe('initialization process', () => { + it('gets the project ID when none is passed in', (done) => { + const writer = new TraceWriter(DEFAULT_CONFIG, logger); + getProjectIdOverride = () => Promise.resolve('my-project'); + writer.initialize(err => { + assert.ifError(err); + assert.strictEqual(writer.getConfig().projectId, 'my-project'); + writer.stop(); done(); - }, DEFAULT_DELAY); + }); }); - it('should drop on server error', function(done) { - var MESSAGE = {valid: 'json'}; - nocks.oauth2(); - var scope = nocks.patchTraces(PROJECT, null, 'Simulated Network Error', - true /* withError */); - - var writer = traceWriter.create({ - projectId: PROJECT, - credentials: fakeCredentials, - serviceContext: {}, - onUncaughtException: 'ignore', - [FORCE_NEW]: true - } as createTraceWriterOptions, fakeLogger); - writer.publish(JSON.stringify(MESSAGE)); - setTimeout(function() { - assert.ok(scope.isDone()); - assert.equal(writer.buffer.length, 0); + it(`doesn't call Service#getProjectId if project ID is passed`, (done) => { + const writer = new TraceWriter( + Object.assign({projectId: 'my-project'}, DEFAULT_CONFIG), logger); + getProjectIdOverride = () => Promise.resolve('my-different-project'); + writer.initialize(err => { + assert.ifError(err); + assert.strictEqual(writer.getConfig().projectId, 'my-project'); + writer.stop(); done(); - }, DEFAULT_DELAY); + }); }); - }); - describe('publishing', function() { - it('should publish when the queue fills', function(done) { - var writer = traceWriter.create({ - projectId: PROJECT, - bufferSize: 4, - flushDelaySeconds: 3600, - serviceContext: {}, - onUncaughtException: 'ignore', - [FORCE_NEW]: true - } as createTraceWriterOptions, fakeLogger); - writer.publish = function() { done(); }; - for (var i = 0; i < 4; i++) { - writer.writeSpan(createFakeTrace(i)); - } + it(`errors when a project ID can't be determined`, (done) => { + const writer = new TraceWriter(DEFAULT_CONFIG, logger); + getProjectIdOverride = () => Promise.reject(new Error()); + writer.initialize(err => { + assert.ok(err); + // We can't know whether the metadata endpoints are called, so don't + // check them. + metadataScopes.cancel(); + writer.stop(); + done(); + }); }); - it('should publish after timeout', function(done) { - var published = false; - var writer = traceWriter.create({ - projectId: PROJECT, - flushDelaySeconds: 0.01, - serviceContext: {}, - onUncaughtException: 'ignore', - [FORCE_NEW]: true - } as createTraceWriterOptions, fakeLogger); - writer.publish = function() { published = true; }; - writer.initialize(function() { - writer.writeSpan(createFakeTrace('fake span')); - setTimeout(function() { - assert.ok(published); + it('assigns default labels based on metadata', (done) => { + const writer = new TraceWriter(DEFAULT_CONFIG, logger); + // Just for this scenario, use real metadata endpoints + metadataScopes.cancel(); + nock.cleanAll(); + // Flakes suggest that nock.cleanAll works asynchronously, so continue + // the test on a separate tick. + setImmediate(() => { + const gotInstanceId = instanceId(200, () => 'my-instance-id'); + const gotHostname = hostname(200, () => 'my-hostname'); + writer.initialize(err => { + assert.ifError(err); + assert.strictEqual( + writer.defaultLabels[TraceLabels.GCE_INSTANCE_ID], + 'my-instance-id'); + assert.strictEqual( + writer.defaultLabels[TraceLabels.GCE_HOSTNAME], 'my-hostname'); + assert.strictEqual( + writer.defaultLabels[TraceLabels.GAE_MODULE_NAME], 'my-hostname'); + gotInstanceId.done(); + gotHostname.done(); + writer.stop(); done(); - }, DEFAULT_DELAY); + }); + }); + }); + + it('assigns values for default labels in lieu of metadata', (done) => { + const writer = new TraceWriter(DEFAULT_CONFIG, logger); + writer.initialize(err => { + assert.ifError(err); + assert.ok(!writer.defaultLabels[TraceLabels.GCE_INSTANCE_ID]); + assert.strictEqual( + writer.defaultLabels[TraceLabels.GCE_HOSTNAME], os.hostname()); + assert.strictEqual( + writer.defaultLabels[TraceLabels.GAE_MODULE_NAME], os.hostname()); + writer.stop(); + done(); + }); + }); + + it('assigns other well-known labels', (done) => { + const writer = new TraceWriter( + Object.assign({}, DEFAULT_CONFIG, { + serviceContext: + {service: 'foo', version: 'bar', minorVersion: 'baz'} + }), + logger); + writer.initialize(err => { + assert.ifError(err); + assert.strictEqual( + writer.defaultLabels[TraceLabels.AGENT_DATA], + `node ${pjson.name} v${pjson.version}`); + assert.strictEqual( + writer.defaultLabels[TraceLabels.GAE_MODULE_NAME], 'foo'); + assert.strictEqual( + writer.defaultLabels[TraceLabels.GAE_MODULE_VERSION], 'bar'); + assert.strictEqual( + writer.defaultLabels[TraceLabels.GAE_VERSION], 'foo:bar.baz'); + writer.stop(); + done(); }); }); }); - describe('initialize', function() { - var testCases: TestCase[] = [ - { - description: 'yield error if no projectId is available', - config: {}, - metadata: {}, - assertResults: function(err, tw) { - assert.ok(err); - assert.strictEqual(tw.config.projectId, undefined); - } - }, - { - description: 'not get projectId if it\'s locally available', - config: { projectId: 'foo' }, - metadata: {}, - assertResults: function(err, tw) { - assert.ok(!err); - assert.strictEqual(tw.config.projectId, 'foo'); - } - }, - { - description: 'get projectId if it\'s not locally available', - config: {}, - metadata: { projectId: 'foo' }, - assertResults: function(err, tw) { - assert.ok(!err); - assert.strictEqual(tw.config.projectId, 'foo'); - } - }, - { - description: 'get hostname even if instanceId isn\'t available', - config: {}, - metadata: { - projectId: 'foo', - hostname: 'bar' - }, - assertResults: function(err, tw) { - assert.ok(!err); - // Having a hostname is reflected in whether these labels are set - assert.strictEqual(tw.defaultLabels[TraceLabels.GCE_HOSTNAME], 'bar'); - assert.strictEqual(tw.defaultLabels[TraceLabels.GAE_MODULE_NAME], 'bar'); - // Having an instanceId is reflected in whether this label is set - assert.strictEqual(tw.defaultLabels[TraceLabels.GCE_INSTANCE_ID], undefined); - } - }, - { - description: 'get instanceId even if hostname isn\'t available', - config: {}, - metadata: { - projectId: 'foo', - instanceId: 'baz' - }, - assertResults: function(err, tw) { - assert.ok(!err); - // Having a hostname is reflected in whether these labels are set - assert.strictEqual(tw.defaultLabels[TraceLabels.GCE_HOSTNAME], os.hostname()); - assert.strictEqual(tw.defaultLabels[TraceLabels.GAE_MODULE_NAME], os.hostname()); - // Having an instanceId is reflected in whether this label is set - assert.strictEqual(tw.defaultLabels[TraceLabels.GCE_INSTANCE_ID], 'baz'); - } - }, - { - description: 'get all fields if they exist', - config: {}, - metadata: { - projectId: 'foo', - hostname: 'bar', - instanceId: 'baz' - }, - assertResults: function(err, tw) { - assert.ok(!err); - assert.strictEqual(tw.defaultLabels[TraceLabels.GCE_HOSTNAME], 'bar'); - assert.strictEqual(tw.defaultLabels[TraceLabels.GAE_MODULE_NAME], 'bar'); - assert.strictEqual(tw.defaultLabels[TraceLabels.GCE_INSTANCE_ID], 'baz'); - } - }, - { - description: 'prioritize config-provided information when setting labels', - config: { - serviceContext: { - service: 'barz', - version: '1', - minorVersion: '2' - } - }, - metadata: { - projectId: 'foo', - hostname: 'bar', - instanceId: 'baz' - }, - assertResults: function(err, tw) { - assert.ok(!err); - assert.strictEqual(tw.defaultLabels[TraceLabels.GCE_HOSTNAME], 'bar'); - assert.strictEqual(tw.defaultLabels[TraceLabels.GAE_MODULE_NAME], 'barz'); - assert.strictEqual(tw.defaultLabels[TraceLabels.GCE_INSTANCE_ID], 'baz'); - assert.strictEqual(tw.defaultLabels[TraceLabels.GAE_MODULE_VERSION], '1'); - assert.strictEqual(tw.defaultLabels[TraceLabels.GAE_VERSION], 'barz:1.2'); - } + describe('writing and publishing', () => { + // When MockedRequestTraceWriter is used, this function dictates the + // status code returned when Service#request is called. + // By default, a 200 status code is always returned. + let overrideRequestResponse: () => Promise<{statusCode: number}>; + let capturedRequestOptions: DecorateRequestOptions|null = null; + // We use this class to mock Service#request. Testing this function is the + // responsibility of @google-cloud/common. + // It also allows us to capture arguments upon trace publish. + class MockedRequestTraceWriter extends TraceWriter { + request( + options: DecorateRequestOptions, + cb?: (err: Error|null, _?: null, response?: Response) => void): + Promise { + capturedRequestOptions = options; + return overrideRequestResponse().then( + (response) => { + if (cb) cb(null, null, response as Response); + return response; + }, + (err) => { + if (cb) cb(err); + throw err; + }) as Promise; } - ]; + } - before(function() { - nock.disableNetConnect(); + beforeEach(() => { + overrideRequestResponse = () => Promise.resolve({statusCode: 200}); + capturedRequestOptions = null; }); - after(function() { - nock.enableNetConnect(); + it('appends project ID and default labels to written traces', (done) => { + const writer = new MockedRequestTraceWriter( + Object.assign({}, DEFAULT_CONFIG, {bufferSize: 1}), logger); + writer.initialize(async err => { + assert.ifError(err); + writer.writeSpan(createDummyTrace()); + // TraceWriter#publish should be called soon + // (Promise task queue drain + immediate). + await wait(200); + const publishedTraces: Trace[] = + JSON.parse(capturedRequestOptions!.body).traces; + assert.strictEqual(publishedTraces.length, 1); + assert.strictEqual(publishedTraces[0].projectId, '0'); + assert.ok(publishedTraces[0].spans[0].endTime); + Object.keys(writer.defaultLabels).forEach(key => { + assert.strictEqual( + publishedTraces[0].spans[0].labels[key], + writer.defaultLabels[key]); + }); + writer.stop(); + done(); + }); }); - testCases.forEach(function(testCase) { - it('should ' + testCase.description, function(done) { - if (testCase.metadata.projectId) { - nocks.projectId(function() { return testCase.metadata.projectId; }); - } - if (testCase.metadata.hostname) { - nocks.hostname(function() { return testCase.metadata.hostname; }); - } - if (testCase.metadata.instanceId) { - nocks.instanceId(function() { return testCase.metadata.instanceId; }); - } + describe('condition for publishing traces', () => { + it('is satisfied when the buffer is full', (done) => { + const NUM_SPANS = 5; + const writer = new MockedRequestTraceWriter( + Object.assign({}, DEFAULT_CONFIG, {bufferSize: NUM_SPANS}), logger); + writer.initialize(async err => { + assert.ifError(err); + writer.writeSpan(createDummyTrace()); + await wait(200); + // Didn't publish yet + assert.ok(!capturedRequestOptions); + for (let i = 1; i < NUM_SPANS; i++) { + writer.writeSpan(createDummyTrace()); + } + await wait(200); + const publishedTraces: Trace[] = + JSON.parse(capturedRequestOptions!.body).traces; + assert.strictEqual(publishedTraces.length, NUM_SPANS); + writer.stop(); + done(); + }); + }); - traceWriter.create(Object.assign({ - [FORCE_NEW]: true, - onUncaughtException: 'ignore', - serviceContext: {} - }, testCase.config), fakeLogger).initialize(function(err) { - testCase.assertResults(err, traceWriter.get()); + it('is satisfied periodically', (done) => { + const writer = new MockedRequestTraceWriter( + Object.assign({}, DEFAULT_CONFIG, {flushDelaySeconds: 1}), logger); + writer.initialize(async err => { + assert.ifError(err); + // Two rounds to ensure that it's periodical + for (let round = 0; round < 2; round++) { + writer.writeSpan(createDummyTrace()); + await wait(500); + // Didn't publish yet + assert.ok(!capturedRequestOptions); + await wait(600); + assert.ok(capturedRequestOptions); + capturedRequestOptions = null; + } + writer.stop(); done(); }); }); }); + + it('emits an error if there was an error publishing', (done) => { + overrideRequestResponse = () => Promise.reject(new Error()); + const writer = new MockedRequestTraceWriter( + Object.assign({}, DEFAULT_CONFIG, {bufferSize: 1}), logger); + writer.initialize(async err => { + assert.ifError(err); + writer.writeSpan(createDummyTrace()); + await wait(200); + assert.strictEqual( + logger.getNumLogsWith('error', 'TraceWriter#publish'), 1); + writer.stop(); + done(); + }); + }); }); }); - -export default {}; diff --git a/test/test-unpatch.ts b/test/test-unpatch.ts deleted file mode 100644 index fe54a0119..000000000 --- a/test/test-unpatch.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright 2017 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -import './override-gcp-metadata'; -import {FORCE_NEW} from '../src/util'; - -var assert = require('assert'); -var nock = require('nock'); -var nocks = require('./nocks'/*.js*/); -var trace = require('../..'); - -nock.disableNetConnect(); - -describe('index.js', function() { - var agent; - var scope; - var checkUnpatches: any[] = []; - var envGcloudProject = process.env.GCLOUD_PROJECT; - - before(function() { - delete process.env.GCLOUD_PROJECT; - }); - - after(function() { - process.env.GCLOUD_PROJECT = envGcloudProject; - }); - - beforeEach(function() { - // Set things up so that the trace agent won't be able to get a project id, - // and stop. - scope = nocks.projectId(404); - agent = trace.start({ [FORCE_NEW]: true }); - }); - - afterEach(function(done) { - // Trace agent will automatically stop. - setTimeout(function() { - assert(!agent.isActive()); - scope.done(); - checkUnpatches.forEach(function(f) { f(); }); - checkUnpatches = []; - done(); - }, 100); - }); - - function wrapTest(nodule, property) { - assert(nodule[property].__unwrap, - property + ' should get wrapped on start'); - checkUnpatches.push(function() { - assert(!nodule[property].__unwrap, - property + ' should get unwrapped on stop'); - }); - } - - it('should wrap/unwrap http on start/stop', function() { - var http = require('http'); - wrapTest(http, 'request'); - }); - - it('should wrap/unwrap express on start/stop', function() { - var express = require('./plugins/fixtures/express4'); - var patchedMethods = require('methods'); - patchedMethods.push('use', 'route', 'param', 'all'); - patchedMethods.forEach(function(method) { - wrapTest(express.application, method); - }); - }); - - it('should wrap/unwrap hapi on start/stop', function() { - var hapi = require('./plugins/fixtures/hapi8'); - wrapTest(hapi.Server.prototype, 'connection'); - }); - - it('should wrap/unwrap mongodb-core on start/stop', function() { - var mongo = require('./plugins/fixtures/mongodb-core1'); - wrapTest(mongo.Server.prototype, 'command'); - wrapTest(mongo.Server.prototype, 'insert'); - wrapTest(mongo.Server.prototype, 'update'); - wrapTest(mongo.Server.prototype, 'remove'); - wrapTest(mongo.Cursor.prototype, 'next'); - }); - - it('should wrap/unwrap redis0.12 on start/stop', function() { - var redis = require('./plugins/fixtures/redis0.12'); - wrapTest(redis.RedisClient.prototype, 'send_command'); - wrapTest(redis.RedisClient.prototype, 'install_stream_listeners'); - wrapTest(redis, 'createClient'); - }); - - it('should wrap/unwrap redis2.4 on start/stop', function() { - var redis = require('./plugins/fixtures/redis2.4'); - wrapTest(redis.RedisClient.prototype, 'send_command'); - wrapTest(redis.RedisClient.prototype, 'create_stream'); - wrapTest(redis, 'createClient'); - }); - - it('should wrap/unwrap redis2.x on start/stop', function() { - var redis = require('./plugins/fixtures/redis2.x'); - wrapTest(redis.RedisClient.prototype, 'create_stream'); - wrapTest(redis.RedisClient.prototype, 'internal_send_command'); - wrapTest(redis, 'createClient'); - }); - - it('should wrap/unwrap restify on start/stop', function() { - var restify = require('./plugins/fixtures/restify4'); - wrapTest(restify, 'createServer'); - }); -}); - -export default {}; diff --git a/test/trace.ts b/test/trace.ts index 5ce37fba9..8501d5dc2 100644 --- a/test/trace.ts +++ b/test/trace.ts @@ -34,21 +34,16 @@ * Most tests should include this file instead of the main module root. */ -// This is required for @google-cloud/common types. -// tslint:disable-next-line:no-reference -/// - import * as common from '@google-cloud/common'; import * as assert from 'assert'; import * as shimmer from 'shimmer'; import * as trace from '../src'; import {Config, PluginTypes} from '../src'; -import {cls, TraceCLS, TraceCLSConfig, TraceCLSMechanism} from '../src/cls'; -import {RootSpanData} from '../src/span-data'; +import {cls, TraceCLS, TraceCLSMechanism} from '../src/cls'; import {Trace, TraceSpan} from '../src/trace'; -import {PluginLoader, pluginLoader, PluginLoaderConfig} from '../src/trace-plugin-loader'; -import {LabelObject, TraceWriter, traceWriter, TraceWriterConfig} from '../src/trace-writer'; +import {PluginLoader, pluginLoader} from '../src/trace-plugin-loader'; +import {TraceWriter, traceWriter, TraceWriterConfig} from '../src/trace-writer'; import {FORCE_NEW} from '../src/util'; import {TestLogger} from './logger'; @@ -65,8 +60,12 @@ export class TestCLS extends TraceCLS { } export class TestTraceWriter extends TraceWriter { - initialize(cb: (err?: Error) => void): void { + constructor(config: TraceWriterConfig, logger: common.Logger) { + super(config, logger); this.getConfig().projectId = '0'; + } + + initialize(cb: (err?: Error) => void): void { cb(); } writeSpan(trace: Trace): void { @@ -103,30 +102,12 @@ export function get(): PluginTypes.TraceAgent { return trace.get(); } -export type LoggerConstructor = new (logLevel?: keyof common.Logger) => - common.Logger; -export function setLoggerForTest(impl?: LoggerConstructor) { - if (common.logger.__wrapped) { - shimmer.unwrap(common, 'logger'); +export function setLoggerForTest(impl?: typeof common.Logger) { + if (common.Logger.__wrapped) { + shimmer.unwrap(common, 'Logger'); } if (impl) { - const wrap = () => shimmer.wrap( - common, 'logger', - () => Object.assign((options?: common.LoggerOptions|string) => { - // sort of ugly, but needed to prevent possible circular constructor - // calls - shimmer.unwrap(common, 'logger'); - let result; - if (typeof options === 'string') { - result = new impl(options as keyof common.Logger); - } else if (typeof options === 'object') { - result = new impl(options.level as keyof common.Logger); - } else { - result = new impl(); - } - wrap(); - return result; - }, {LEVELS: common.logger.LEVELS})); + const wrap = () => shimmer.wrap(common, 'Logger', () => impl); wrap(); } } diff --git a/tsconfig.json b/tsconfig.json index d96026903..fefe0fd23 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,13 +28,17 @@ "test/test-config-cls.ts", "test/test-config-credentials.ts", "test/test-config-plugins.ts", + "test/test-default-ignore-ah-health.ts", + "test/test-env-log-level.ts", "test/test-modules-loaded-before-agent.ts", "test/test-plugin-loader.ts", "test/test-span-data.ts", "test/test-trace-api.ts", "test/test-trace-api-none-cls.ts", "test/test-trace-cluster.ts", + "test/test-trace-uncaught-exception.ts", "test/test-trace-web-frameworks.ts", + "test/test-trace-writer.ts", "test/test-util.ts", "test/trace.ts", "test/utils.ts",