diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d0cc26a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.github +.run +common/temp +**/node_modules diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..97429e1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM node:14.16.0-alpine3.10 + +WORKDIR /usr/src/app +COPY . ./ +RUN node common/scripts/install-run-rush.js install +RUN node common/scripts/install-run-rush.js build diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 22e052d..a520a6c 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1,10 +1,21 @@ dependencies: + '@aws/otel-aws-xray-id-generator': 0.13.1 + '@aws/otel-aws-xray-propagator': 0.13.0 '@mikro-orm/core': 4.4.2_@mikro-orm+sqlite@4.4.2 '@mikro-orm/nestjs': 4.2.0_1b5398639b57f63400336f42f56eb406 '@mikro-orm/sqlite': 4.4.2_@mikro-orm+core@4.4.2 '@nestjs/core': 7.6.11_6084d9907887ddaa2cd60f6f8e89001f '@nestjs/platform-express': 7.6.11_@nestjs+core@7.6.11 '@nestjs/testing': 7.6.11_5493a482b6326ce7617b54c4270e8fab + '@opentelemetry/api': 1.0.0-rc.0 + '@opentelemetry/context-async-hooks': 0.18.0 + '@opentelemetry/exporter-collector-grpc': 0.18.0 + '@opentelemetry/exporter-zipkin': 0.18.0 + '@opentelemetry/instrumentation': 0.18.0 + '@opentelemetry/node': 0.18.0 + '@opentelemetry/plugin-express': 0.14.0 + '@opentelemetry/plugin-http': 0.18.0 + '@opentelemetry/tracing': 0.18.0 '@rush-temp/eslint-config': file:projects/eslint-config.tgz_eslint@7.20.0 '@rush-temp/monolith-service': file:projects/monolith-service.tgz '@rush-temp/tsconfig': file:projects/tsconfig.tgz @@ -42,6 +53,22 @@ dependencies: zod: 3.0.0-alpha.4 lockfileVersion: 5.2 packages: + /@aws/otel-aws-xray-id-generator/0.13.1: + dependencies: + '@opentelemetry/core': 0.13.0 + dev: false + resolution: + integrity: sha512-ca75WEyWBgYyO6SAj67vVflZGFnE/H+/t+VXEYbrfD2F4e6GoQIcHsV6pN1RyQrykHo8ztOz1JIRMm73b3CsOA== + /@aws/otel-aws-xray-propagator/0.13.0: + dependencies: + '@opentelemetry/api': 0.13.0 + '@opentelemetry/context-base': 0.13.0 + '@opentelemetry/core': 0.13.0 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-TE3eJuRwoXc8ihkoPDw4+AnihmGXm7O8RiQxLVWfNfKoThmRZ+LZ6laUe5NiELdr0MZn9hqUo/sHrSskFRduaA== /@babel/code-frame/7.10.1: dependencies: '@babel/highlight': 7.10.1 @@ -369,6 +396,15 @@ packages: node: ^10.12.0 || >=12.0.0 resolution: integrity: sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== + /@grpc/proto-loader/0.5.6: + dependencies: + lodash.camelcase: 4.3.0 + protobufjs: 6.10.2 + dev: false + engines: + node: '>=6' + resolution: + integrity: sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ== /@hapi/bourne/2.0.0: dev: false resolution: @@ -910,6 +946,232 @@ packages: hasBin: true resolution: integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA== + /@opentelemetry/api-metrics/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-5MGIP1Bb97yiRBLeHdfgDaMnoKE5+IOhUvE3FGRqiTMjun0cDt35gY4k5+w5pmqpcHFkt0/ih25YTKjF0tJLHg== + /@opentelemetry/api/0.13.0: + dependencies: + '@opentelemetry/context-base': 0.13.0 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-3F5zuMBhL1cQIGTFGuuGofS9/2bfhoJxT9sWLfHtx7A/vN6HSA6YiotPjWFK/aTiLjZA4YYnIjeA3di151xJrw== + /@opentelemetry/api/0.18.1: + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-pKNxHe3AJ5T2N5G3AlT9gx6FyF5K2FS9ZNc+FipC+f1CpVF/EY+JHTJ749dnM2kWIgZTbDJFiGMuc0FYjNSCOg== + /@opentelemetry/api/1.0.0-rc.0: + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-iXKByCMfrlO5S6Oh97BuM56tM2cIBB0XsL/vWF/AtJrJEKx4MC/Xdu0xDsGXMGcNWpqF7ujMsjjnp0+UHBwnDQ== + /@opentelemetry/context-async-hooks/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + dev: false + engines: + node: '>=8.1.0' + resolution: + integrity: sha512-PD1aHXyniFtZIXbLuCr+KaZiufrGJPuEZ6eMZggQRi7+AC3alAfAVRz88sLmeR49pd7lRRFiKzymzVqJRMEmjw== + /@opentelemetry/context-base/0.13.0: + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-y4qNA0JA9ab0B0ppnOokAxzJDplBWCLdTVJrH8a8SMiWubkuGOIGJpe3ZoJzPLrg3BWKZ9CIk9vHiyBFYgYgWg== + /@opentelemetry/core/0.13.0: + dependencies: + '@opentelemetry/api': 0.13.0 + '@opentelemetry/context-base': 0.13.0 + semver: 7.3.2 + dev: false + engines: + node: '>=8.5.0' + resolution: + integrity: sha512-SFHr4uRnSSWqTLu1J1hadn92aGoGVb2WrPHvOgNIttSKYkUXNVyABO1pdtUN2AHE4/YBmk9eLwTUqwmFjVfZWQ== + /@opentelemetry/core/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + semver: 7.3.2 + dev: false + engines: + node: '>=8.5.0' + resolution: + integrity: sha512-Kg+LBIAPK70tEtpIAdZomkUmbABK+EwfnjFfvJ1rVZ8e0NApDx14Sq92RbGDIf67TK5mBgIvvY27W+ic354UZQ== + /@opentelemetry/exporter-collector-grpc/0.18.0: + dependencies: + '@grpc/proto-loader': 0.5.6 + '@opentelemetry/api': 0.18.1 + '@opentelemetry/core': 0.18.0 + '@opentelemetry/exporter-collector': 0.18.0 + '@opentelemetry/metrics': 0.18.0 + '@opentelemetry/resources': 0.18.0 + '@opentelemetry/tracing': 0.18.0 + grpc: 1.24.6 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-fmZdlt+Y7nHb9VhfgAT2/+4sVGXIo6dNoAVTqE2orWmpI7bzzFYydmSTOM43XMByEjqJrONHV8l8NtCWHWvc3w== + /@opentelemetry/exporter-collector/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/api-metrics': 0.18.0 + '@opentelemetry/core': 0.18.0 + '@opentelemetry/metrics': 0.18.0 + '@opentelemetry/resources': 0.18.0 + '@opentelemetry/tracing': 0.18.0 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-AMurbTrkhIDy+hCs7Iz3MdhRCUbhzQC3rUOIDwusnUDBOah7zD9OLm/6yS529jrYNfljzxHjeczV0oOsu9AcKQ== + /@opentelemetry/exporter-zipkin/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/core': 0.18.0 + '@opentelemetry/resources': 0.18.0 + '@opentelemetry/tracing': 0.18.0 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-hDP7jPwUXS9i5W0LKW7nLqEEauEeGsphEHXM2ANWk+iR8oIVIlYFPSzF9KuoqTzuZhPQl7mRzmXjzxacr/6SsA== + /@opentelemetry/instrumentation/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/api-metrics': 0.18.0 + require-in-the-middle: 5.1.0 + semver: 7.3.2 + shimmer: 1.2.1 + dev: false + resolution: + integrity: sha512-YFrCnSWS9jJLChg5I8g7EuvpWqPZGa2EXyO8KwRJApuLPCqJSBkcymYieedWNupS0FAXntocpIb/b0SEVaZbEg== + /@opentelemetry/metrics/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/api-metrics': 0.18.0 + '@opentelemetry/core': 0.18.0 + '@opentelemetry/resources': 0.18.0 + lodash.merge: 4.6.2 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-BH1P97bY6ZHBPNlW/0gV+Bc384Gqpu0KOdKWy2ZcntxGemhZ+byguL1AlqqS5ip+AaoCvgAmaY7JzuXq7YKo4A== + /@opentelemetry/node/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/context-async-hooks': 0.18.0 + '@opentelemetry/core': 0.18.0 + '@opentelemetry/tracing': 0.18.0 + semver: 7.3.2 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-KjN6O+BvNmBwjQHKpcIRyxebrRuEMUzyS4Y13ZMH684fBMwRTju45aDz7ILCFndGECvbtl8nDY0US7+HCimpXw== + /@opentelemetry/plugin-express/0.14.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/core': 0.18.0 + shimmer: 1.2.1 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-jVGZvRxMm5wLYhNNHs3pENnLX7TuH466ip+tJD3BsI7D2WdF5FVUG+I1Fl+yP56zqhUjCZB4XWjYPV0mJqqe+Q== + /@opentelemetry/plugin-http/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/core': 0.18.0 + '@opentelemetry/semantic-conventions': 0.18.0 + semver: 7.3.2 + shimmer: 1.2.1 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-+g4H+XKlDAAkNGHQcO2BJ25UtfdYO9te8xq/vILUDYKXXejcsrEjLwLe6xgSX6n936QyJjXi3sJmblBMHVx9ug== + /@opentelemetry/resources/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/core': 0.18.0 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-Mko4HpoI5cCYplhSyiCuMFi0QEG1Nw/YwHFyAK+A67r+sgmo1wVpM6Pengb+XlxJrrO8WgmLsDS3RHqoMWhWNQ== + /@opentelemetry/semantic-conventions/0.18.0: + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-02Wi/zFq+RWfY4llRicMashGhyZvUtMfXu9UlfXMJiDbGOgkdua4AeOCv9lDqv1GIz11xr5qS4tFjLp7WnlU+Q== + /@opentelemetry/tracing/0.18.0: + dependencies: + '@opentelemetry/api': 0.18.1 + '@opentelemetry/core': 0.18.0 + '@opentelemetry/resources': 0.18.0 + '@opentelemetry/semantic-conventions': 0.18.0 + lodash.merge: 4.6.2 + dev: false + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-k7UAebuHBLPafS8rnkpZqNuM8nfwOg6OCmppekCMxdQzkuZS1attgelqyEIlX6NYh46DndyZ7BxBkiXF4S0Xwg== + /@protobufjs/aspromise/1.1.2: + dev: false + resolution: + integrity: sha1-m4sMxmPWaafY9vXQiToU00jzD78= + /@protobufjs/base64/1.1.2: + dev: false + resolution: + integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + /@protobufjs/codegen/2.0.4: + dev: false + resolution: + integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + /@protobufjs/eventemitter/1.1.0: + dev: false + resolution: + integrity: sha1-NVy8mLr61ZePntCV85diHx0Ga3A= + /@protobufjs/fetch/1.1.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + dev: false + resolution: + integrity: sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU= + /@protobufjs/float/1.0.2: + dev: false + resolution: + integrity: sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E= + /@protobufjs/inquire/1.1.0: + dev: false + resolution: + integrity: sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik= + /@protobufjs/path/1.1.2: + dev: false + resolution: + integrity: sha1-bMKyDFya1q0NzP0hynZz2Nf79o0= + /@protobufjs/pool/1.1.0: + dev: false + resolution: + integrity: sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q= + /@protobufjs/utf8/1.1.0: + dev: false + resolution: + integrity: sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= /@rushstack/eslint-patch/1.0.6: dev: false resolution: @@ -966,6 +1228,13 @@ packages: dev: false resolution: integrity: sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== + /@types/bytebuffer/5.0.42: + dependencies: + '@types/long': 4.0.1 + '@types/node': 14.14.25 + dev: false + resolution: + integrity: sha512-lEgKojWUAc/MG2t649oZS5AfYFP2xRNPoDuwDBlBMjHXd8MaGPgFgtCXUK7inZdBOygmVf10qxc1Us8GXC96aw== /@types/color-name/1.1.1: dev: false resolution: @@ -1034,6 +1303,10 @@ packages: dev: false resolution: integrity: sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + /@types/long/4.0.1: + dev: false + resolution: + integrity: sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== /@types/mime/1.3.2: dev: false resolution: @@ -1045,6 +1318,10 @@ packages: dev: false resolution: integrity: sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== + /@types/node/13.13.48: + dev: false + resolution: + integrity: sha512-z8wvSsgWQzkr4sVuMEEOvwMdOQjiRY2Y/ZW4fDfjfe3+TfQrZqFKOthBgk2RnVEmtOKrkwdZ7uTvsxTBLjKGDQ== /@types/node/14.14.25: dev: false resolution: @@ -1460,6 +1737,13 @@ packages: node: '>= 0.4' resolution: integrity: sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== + /ascli/1.0.1: + dependencies: + colour: 0.7.1 + optjs: 3.2.2 + dev: false + resolution: + integrity: sha1-vPpZdKYvGOgcq660lzKrSoj5Brw= /asn1/0.2.4: dependencies: safer-buffer: 2.1.2 @@ -1717,6 +2001,14 @@ packages: node: '>=0.8.0' resolution: integrity: sha1-bCpiLvz0fFe7vh4qnDetNseSVFM= + /bytebuffer/5.0.1: + dependencies: + long: 3.2.0 + dev: false + engines: + node: '>=0.8' + resolution: + integrity: sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0= /bytes/3.1.0: dev: false engines: @@ -1745,6 +2037,12 @@ packages: node: '>=6' resolution: integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + /camelcase/2.1.1: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= /camelcase/5.0.0: dev: false engines: @@ -1823,6 +2121,14 @@ packages: node: '>=0.10.0' resolution: integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + /cliui/3.2.0: + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + wrap-ansi: 2.1.0 + dev: false + resolution: + integrity: sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= /cliui/6.0.0: dependencies: string-width: 4.2.0 @@ -1889,6 +2195,12 @@ packages: dev: false resolution: integrity: sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + /colour/0.7.1: + dev: false + engines: + node: '>=0.8' + resolution: + integrity: sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g= /combined-stream/1.0.8: dependencies: delayed-stream: 1.0.0 @@ -3135,6 +3447,20 @@ packages: optional: true resolution: integrity: sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= + /grpc/1.24.6: + dependencies: + '@types/bytebuffer': 5.0.42 + lodash.camelcase: 4.3.0 + lodash.clone: 4.5.0 + nan: 2.14.2 + node-pre-gyp: 0.16.0 + protobufjs: 5.0.3 + dev: false + engines: + node: '>=4' + requiresBuild: true + resolution: + integrity: sha512-BtifKdClMYU0ZEo0Pdr2WV9ZH54AoEdIcp2BfJkh87g2R3HoNPLYKHRYefw/ByxrCdVDTAy3hkraFISpqsRcrw== /har-schema/2.0.0: dev: false engines: @@ -3357,6 +3683,12 @@ packages: node: '>= 0.10' resolution: integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + /invert-kv/1.0.0: + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-EEqOSqym09jNFXqO+L+rLXo//bY= /ip-regex/2.1.0: dev: false engines: @@ -4337,6 +4669,14 @@ packages: optional: true resolution: integrity: sha512-kAt58lRwjzqwedApKF7luYPa7HsLb0oDiczwKrkZcekIzTmSow5YGK149S2C8HjH63R3NcOBo9+1rjvWnC1Paw== + /lcid/1.0.0: + dependencies: + invert-kv: 1.0.0 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= /leven/2.1.0: dev: false engines: @@ -4414,6 +4754,18 @@ packages: node: '>=8' resolution: integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + /lodash.camelcase/4.3.0: + dev: false + resolution: + integrity: sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + /lodash.clone/4.5.0: + dev: false + resolution: + integrity: sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= + /lodash.merge/4.6.2: + dev: false + resolution: + integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== /lodash.sortby/4.7.0: dev: false resolution: @@ -4422,6 +4774,16 @@ packages: dev: false resolution: integrity: sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + /long/3.2.0: + dev: false + engines: + node: '>=0.6' + resolution: + integrity: sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s= + /long/4.0.0: + dev: false + resolution: + integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== /make-dir/3.1.0: dependencies: semver: 6.3.0 @@ -4597,6 +4959,10 @@ packages: hasBin: true resolution: integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + /module-details-from-path/1.0.3: + dev: false + resolution: + integrity: sha1-EUyUlnPiqKNenTV4hSeqN7Z52is= /mri/1.1.4: dev: false engines: @@ -4630,6 +4996,10 @@ packages: node: '>= 0.10.0' resolution: integrity: sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg== + /nan/2.14.2: + dev: false + resolution: + integrity: sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== /nanomatch/1.2.13: dependencies: arr-diff: 4.0.0 @@ -4766,6 +5136,23 @@ packages: hasBin: true resolution: integrity: sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA== + /node-pre-gyp/0.16.0: + dependencies: + detect-libc: 1.0.3 + mkdirp: 0.5.5 + needle: 2.6.0 + nopt: 4.0.3 + npm-packlist: 1.4.8 + npmlog: 4.1.2 + rc: 1.2.8 + rimraf: 2.6.3 + semver: 5.7.1 + tar: 4.4.13 + deprecated: 'Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future' + dev: false + hasBin: true + resolution: + integrity: sha512-4efGA+X/YXAHLi1hN8KaPrILULaUn2nWecFrn1k2I+99HpoyvcOGEbtcOxpDiUwPF2ZANMJDh32qwOUPenuR1g== /nopt/3.0.6: dependencies: abbrev: 1.1.1 @@ -5004,12 +5391,24 @@ packages: node: '>= 0.8.0' resolution: integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + /optjs/3.2.2: + dev: false + resolution: + integrity: sha1-aabOicRCpEQDFBrS+bNwvVu29O4= /os-homedir/1.0.2: dev: false engines: node: '>=0.10.0' resolution: integrity: sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + /os-locale/1.4.0: + dependencies: + lcid: 1.0.0 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= /os-tmpdir/1.0.2: dev: false engines: @@ -5333,6 +5732,38 @@ packages: node: '>= 6' resolution: integrity: sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ== + /protobufjs/5.0.3: + dependencies: + ascli: 1.0.1 + bytebuffer: 5.0.1 + glob: 7.1.6 + yargs: 3.32.0 + dev: false + engines: + node: '>=0.8' + hasBin: true + resolution: + integrity: sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA== + /protobufjs/6.10.2: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/long': 4.0.1 + '@types/node': 13.13.48 + long: 4.0.0 + dev: false + hasBin: true + requiresBuild: true + resolution: + integrity: sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ== /proxy-addr/2.0.6: dependencies: forwarded: 0.1.2 @@ -5595,6 +6026,14 @@ packages: node: '>=0.10.0' resolution: integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + /require-in-the-middle/5.1.0: + dependencies: + debug: 4.3.1 + module-details-from-path: 1.0.3 + resolve: 1.19.0 + dev: false + resolution: + integrity: sha512-M2rLKVupQfJ5lf9OvqFGIT+9iVLnTmjgbOmpil12hiSQNn5zJTKGPoIisETNjfK+09vP3rpm1zJajmErpr2sEQ== /require-main-filename/2.0.0: dev: false resolution: @@ -5840,6 +6279,10 @@ packages: optional: true resolution: integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + /shimmer/1.2.1: + dev: false + resolution: + integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== /signal-exit/3.0.3: dev: false resolution: @@ -6811,12 +7254,28 @@ packages: dev: false resolution: integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + /window-size/0.1.4: + dev: false + engines: + node: '>= 0.10.0' + hasBin: true + resolution: + integrity: sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= /word-wrap/1.2.3: dev: false engines: node: '>=0.10.0' resolution: integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + /wrap-ansi/2.1.0: + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + dev: false + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= /wrap-ansi/6.2.0: dependencies: ansi-styles: 4.2.1 @@ -6868,6 +7327,10 @@ packages: node: '>=0.4' resolution: integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + /y18n/3.2.2: + dev: false + resolution: + integrity: sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== /y18n/4.0.0: dev: false resolution: @@ -6909,6 +7372,18 @@ packages: node: '>=8' resolution: integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + /yargs/3.32.0: + dependencies: + camelcase: 2.1.1 + cliui: 3.2.0 + decamelize: 1.2.0 + os-locale: 1.4.0 + string-width: 1.0.2 + window-size: 0.1.4 + y18n: 3.2.2 + dev: false + resolution: + integrity: sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= /yn/3.1.1: dev: false engines: @@ -6936,6 +7411,8 @@ packages: version: 0.0.0 file:projects/monolith-service.tgz: dependencies: + '@aws/otel-aws-xray-id-generator': 0.13.1 + '@aws/otel-aws-xray-propagator': 0.13.0 '@mikro-orm/core': 4.4.2_@mikro-orm+sqlite@4.4.2 '@mikro-orm/nestjs': 4.2.0_f16047f1be058b4f78bced1d248b322a '@mikro-orm/sqlite': 4.4.2_@mikro-orm+core@4.4.2 @@ -6944,6 +7421,15 @@ packages: '@nestjs/platform-express': 7.6.11_10f9c32d5705e6d2dea73f1d25c08abc '@nestjs/swagger': 4.7.13_81a1937ed9aace8fb18846d898b8f16a '@nestjs/testing': 7.6.11_ed6e60f1b18d44b976a1a0f51d940b9c + '@opentelemetry/api': 1.0.0-rc.0 + '@opentelemetry/context-async-hooks': 0.18.0 + '@opentelemetry/exporter-collector-grpc': 0.18.0 + '@opentelemetry/exporter-zipkin': 0.18.0 + '@opentelemetry/instrumentation': 0.18.0 + '@opentelemetry/node': 0.18.0 + '@opentelemetry/plugin-express': 0.14.0 + '@opentelemetry/plugin-http': 0.18.0 + '@opentelemetry/tracing': 0.18.0 '@types/bcrypt': 3.0.0 '@types/express': 4.17.11 '@types/jest': 26.0.20 @@ -6975,7 +7461,7 @@ packages: dev: false name: '@rush-temp/monolith-service' resolution: - integrity: sha512-7tLEyXYOIdSmmDx3Yu55jLG7Sq2H6aWRehoaSGzvQRYYI4zVYU6vXsRvw0GdaodZar2f6cHboiPx9r+h51fJGg== + integrity: sha512-Gdf/T9rf3Jh9pPGLtxKVnYZuMYf0yo2aVjrs5X9L8QCbP2xSeDBAN/mEm18rwdmErrXspFn7grV3OsPG1qvSWA== tarball: file:projects/monolith-service.tgz version: 0.0.0 file:projects/tsconfig.tgz: @@ -7011,12 +7497,23 @@ packages: version: 0.0.0 registry: '' specifiers: + '@aws/otel-aws-xray-id-generator': ~0.13.1 + '@aws/otel-aws-xray-propagator': ~0.13.0 '@mikro-orm/core': ~4.4.2 '@mikro-orm/nestjs': ~4.2.0 '@mikro-orm/sqlite': ~4.4.2 '@nestjs/core': ^7.5.1 '@nestjs/platform-express': ^7.5.1 '@nestjs/testing': ~7.6.11 + '@opentelemetry/api': ~1.0.0-rc.0 + '@opentelemetry/context-async-hooks': ~0.18.0 + '@opentelemetry/exporter-collector-grpc': ~0.18.0 + '@opentelemetry/exporter-zipkin': ~0.18.0 + '@opentelemetry/instrumentation': ~0.18.0 + '@opentelemetry/node': ~0.18.0 + '@opentelemetry/plugin-express': ~0.14.0 + '@opentelemetry/plugin-http': ~0.18.0 + '@opentelemetry/tracing': ~0.18.0 '@rush-temp/eslint-config': file:./projects/eslint-config.tgz '@rush-temp/monolith-service': file:./projects/monolith-service.tgz '@rush-temp/tsconfig': file:./projects/tsconfig.tgz diff --git a/services/monolith/Dockerfile b/services/monolith/Dockerfile new file mode 100644 index 0000000..b243261 --- /dev/null +++ b/services/monolith/Dockerfile @@ -0,0 +1,8 @@ +FROM 14.16.0-alpine3.10 as builder + +WORKDIR /usr/src/app +COPY package.json ./ +COPY .babelrc ./ +RUN npm install +COPY ./src ./src +RUN npm run build \ No newline at end of file diff --git a/services/monolith/docker-compose.yaml b/services/monolith/docker-compose.yaml new file mode 100644 index 0000000..ced6f0d --- /dev/null +++ b/services/monolith/docker-compose.yaml @@ -0,0 +1,6 @@ +version: "3.8" +services: + zipkin: + image: openzipkin/zipkin-slim:2.23.2 + ports: + - '9411:9411' diff --git a/services/monolith/package.json b/services/monolith/package.json index d92061c..f5b1cdb 100644 --- a/services/monolith/package.json +++ b/services/monolith/package.json @@ -33,7 +33,18 @@ "swagger-ui-express": "~4.1.6", "jose": "~3.6.2", "dotenv": "~8.2.0", - "pino-std-serializers": "~3.2.0" + "pino-std-serializers": "~3.2.0", + "@opentelemetry/api": "~1.0.0-rc.0", + "@opentelemetry/node": "~0.18.0", + "@opentelemetry/tracing": "~0.18.0", + "@opentelemetry/plugin-http": "~0.18.0", + "@opentelemetry/plugin-express": "~0.14.0", + "@opentelemetry/instrumentation": "~0.18.0", + "@opentelemetry/context-async-hooks": "~0.18.0", + "@opentelemetry/exporter-zipkin": "~0.18.0", + "@opentelemetry/exporter-collector-grpc": "~0.18.0", + "@aws/otel-aws-xray-propagator": "~0.13.0", + "@aws/otel-aws-xray-id-generator": "~0.13.1" }, "devDependencies": { "@abitia/eslint-config": "~1.1.0", diff --git a/services/monolith/src/AccountContext/AccountContextModule.ts b/services/monolith/src/AccountContext/AccountContextModule.ts index ec0bda4..5348829 100644 --- a/services/monolith/src/AccountContext/AccountContextModule.ts +++ b/services/monolith/src/AccountContext/AccountContextModule.ts @@ -1,5 +1,6 @@ import { MikroOrmModule, MikroOrmModuleSyncOptions } from '@mikro-orm/nestjs'; import { DynamicModule, Module } from '@nestjs/common'; +import { APP_INTERCEPTOR } from '@nestjs/core'; import { EVENT_BUS, EventBus, EventBusCompositeCoordinator, nestJsInMemoryEventBusProvider } from '../Core/EventBus'; import { LOGGER, Logger, NestJsLoggerAdapter, nestJsLoggerProvider } from '../Core/Logger'; diff --git a/services/monolith/src/Core/EventBus/InMemoryEventBus.ts b/services/monolith/src/Core/EventBus/InMemoryEventBus.ts index bdce901..fedf1a7 100644 --- a/services/monolith/src/Core/EventBus/InMemoryEventBus.ts +++ b/services/monolith/src/Core/EventBus/InMemoryEventBus.ts @@ -1,4 +1,7 @@ +import { context, SpanKind, SpanStatusCode } from '@opentelemetry/api'; + import { Logger } from '../Logger'; +import { tracer } from '../OpenTracing'; import { Event } from './Event'; import { EventBus, EventBusSubscriber } from './EventBus'; @@ -22,10 +25,18 @@ export class InMemoryEventBus implements EventBus { const eventSubscribers = this.subscribers[event.constructor.name] ?? []; for(const subscriber of eventSubscribers) { + const span = tracer.startSpan('event-handler', { + kind: SpanKind.CONSUMER, + }, context.active()); + span.setAttribute('event.name', event.name); try { await subscriber(event); + span.setStatus({ code: SpanStatusCode.OK }); } catch (error) { this.logger?.error(`Failed to run subscriber for event ${event.name}`, error); + span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message }); + } finally { + span.end(); } } } diff --git a/services/monolith/src/Core/Logger/PinoLogger.ts b/services/monolith/src/Core/Logger/PinoLogger.ts index fabdfbb..bbff632 100644 --- a/services/monolith/src/Core/Logger/PinoLogger.ts +++ b/services/monolith/src/Core/Logger/PinoLogger.ts @@ -1,5 +1,7 @@ import { Logger as PinoInstance } from 'pino'; +import { getActiveSpan } from '../OpenTracing'; + import { Logger } from './Logger'; /** @@ -28,10 +30,15 @@ export class PinoLogger implements Logger { } private _doLog(logType: string, message: string, obj?: Record): void { - if(obj) { - this.pino[logType](obj, message); - } else { - this.pino[logType](message); - } + const spanContext = getActiveSpan(); + + const logObj = { + traceId: spanContext?.traceId, + spanId: spanContext?.spanId, + traceFlags: spanContext?.traceFlags, + ...obj, + }; + + this.pino[logType](logObj, message); } } diff --git a/services/monolith/src/Core/OpenTracing/LoggerSpanExporter.ts b/services/monolith/src/Core/OpenTracing/LoggerSpanExporter.ts new file mode 100644 index 0000000..3754a96 --- /dev/null +++ b/services/monolith/src/Core/OpenTracing/LoggerSpanExporter.ts @@ -0,0 +1,40 @@ +import { ReadableSpan, SpanExporter } from '@opentelemetry/tracing'; + +import { Logger } from '../Logger'; + +const CODE_OK = 1; + +export class LoggerSpanExporter implements SpanExporter { + public constructor(private readonly logger: Logger) {} + + public export(spans: ReadableSpan[], resultCallback: (result) => void): void { + for (const span of spans) { + this.logger.info(span.name, this.exportInfo(span)); + } + + resultCallback({ code: CODE_OK }); + } + + public shutdown(): Promise { + return Promise.resolve(); + } + + private exportInfo(span): Record { + return { + traceId: span.spanContext.traceId, + parentId: span.parentSpanId, + name: span.name, + id: span.spanContext.spanId, + kind: span.kind, + timestamp: this.hrTimeToMicroseconds(span.startTime), + duration: this.hrTimeToMicroseconds(span.duration), + attributes: span.attributes, + status: span.status, + events: span.events, + }; + } + + private hrTimeToMicroseconds(hrTime): number { + return Math.round(hrTime[0] * 1e6 + hrTime[1] / 1e3); + } +} diff --git a/services/monolith/src/Core/OpenTracing/getActiveSpan.ts b/services/monolith/src/Core/OpenTracing/getActiveSpan.ts new file mode 100644 index 0000000..328a35e --- /dev/null +++ b/services/monolith/src/Core/OpenTracing/getActiveSpan.ts @@ -0,0 +1,6 @@ +import { getSpanContext, SpanContext, context, trace } from '@opentelemetry/api'; + +export const tracer = trace.getTracer('monolith'); + +export const getActiveSpan = (): SpanContext | undefined => + getSpanContext(context.active()); diff --git a/services/monolith/src/Core/OpenTracing/index.ts b/services/monolith/src/Core/OpenTracing/index.ts new file mode 100644 index 0000000..af58399 --- /dev/null +++ b/services/monolith/src/Core/OpenTracing/index.ts @@ -0,0 +1,2 @@ +export * from './getActiveSpan'; +export * from './LoggerSpanExporter'; diff --git a/services/monolith/src/Core/Outbox/MikroOrm/MikroOrmOutbox.ts b/services/monolith/src/Core/Outbox/MikroOrm/MikroOrmOutbox.ts index 1540fc8..03a7cb6 100644 --- a/services/monolith/src/Core/Outbox/MikroOrm/MikroOrmOutbox.ts +++ b/services/monolith/src/Core/Outbox/MikroOrm/MikroOrmOutbox.ts @@ -2,6 +2,7 @@ import { EntityManager } from '@mikro-orm/core'; import { Event } from '../../EventBus'; import { Logger } from '../../Logger'; +import { getActiveSpan } from '../../OpenTracing'; import { Outbox } from '../Outbox'; import { newOutboxMessageId, OutboxMessageEntity } from './OutboxMessageEntity'; @@ -29,10 +30,11 @@ export class MikroOrmOutbox implements Outbox { this.logger?.info(`Persisting event ${event.name}`); } + const tracingContext = getActiveSpan(); const message = new OutboxMessageEntity( newOutboxMessageId(), event.name, - JSON.stringify(event), + JSON.stringify({ tracingContext, event }), ); this.em.persist(message); diff --git a/services/monolith/src/Core/Outbox/MikroOrm/MikroOrmOutboxWorker.ts b/services/monolith/src/Core/Outbox/MikroOrm/MikroOrmOutboxWorker.ts index 7209743..5a89c82 100644 --- a/services/monolith/src/Core/Outbox/MikroOrm/MikroOrmOutboxWorker.ts +++ b/services/monolith/src/Core/Outbox/MikroOrm/MikroOrmOutboxWorker.ts @@ -1,24 +1,31 @@ import { EntityManager } from '@mikro-orm/core'; +import { context, ROOT_CONTEXT, setSpanContext, SpanKind } from '@opentelemetry/api'; import { Event, EventBus } from '../../EventBus'; import { Logger } from '../../Logger'; +import { tracer } from '../../OpenTracing'; import { OutboxMessageEntity } from './OutboxMessageEntity'; const sleep = (ms: number): Promise => new Promise(resolve => setTimeout(resolve, ms)); -const adaptMessageToEvent = (message: OutboxMessageEntity): Event => { - const payload = JSON.parse(message.eventPayload); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const adaptMessageToEvent = (eventName: string, event: any): Event => { + Object.defineProperty(event, 'name', { + value: eventName, + enumerable: false, + writable: false, + }); - Object.defineProperty(payload, 'constructor', { + Object.defineProperty(event, 'constructor', { value: { - name: message.eventName, + name: eventName, }, enumerable: false, writable: false, }); - return payload; + return event; }; type MikroOrmOutboxWorkerOptions = { @@ -83,12 +90,25 @@ export class MikroOrmOutboxWorker { } for(const message of messages) { - const event = adaptMessageToEvent(message); + const payload = JSON.parse(message.eventPayload); + const rootCtx = setSpanContext(ROOT_CONTEXT, payload.tracingContext); + + await context.with(rootCtx, async () => { + const span = tracer.startSpan('outbox-worker', { + kind: SpanKind.CONSUMER, + }); + + const event = adaptMessageToEvent(message.eventName, payload.event); + + span.setAttribute('event.name', event.name); + + this.eventBus.publish(event); - this.eventBus.publish(event); + message.markAsProcessed(); + await this.em.persistAndFlush(message); - message.markAsProcessed(); - await this.em.persistAndFlush(message); + span.end(); + }); } } } diff --git a/services/monolith/src/Core/Outbox/MikroOrm/__tests__/MikroOrmOutbox.test.ts b/services/monolith/src/Core/Outbox/MikroOrm/__tests__/MikroOrmOutbox.test.ts index b638232..9e627b6 100644 --- a/services/monolith/src/Core/Outbox/MikroOrm/__tests__/MikroOrmOutbox.test.ts +++ b/services/monolith/src/Core/Outbox/MikroOrm/__tests__/MikroOrmOutbox.test.ts @@ -26,6 +26,6 @@ it('should serialize and persist the event', async () => { id: expect.any(String), createdAt: expect.any(Date), eventName: 'DummyEvent', - eventPayload: JSON.stringify(event), + eventPayload: JSON.stringify({ event }), } as OutboxMessageEntity); }); diff --git a/services/monolith/src/Core/Outbox/MikroOrm/__tests__/MikroOrmOutboxWorker.test.ts b/services/monolith/src/Core/Outbox/MikroOrm/__tests__/MikroOrmOutboxWorker.test.ts index db70a49..b302d1c 100644 --- a/services/monolith/src/Core/Outbox/MikroOrm/__tests__/MikroOrmOutboxWorker.test.ts +++ b/services/monolith/src/Core/Outbox/MikroOrm/__tests__/MikroOrmOutboxWorker.test.ts @@ -20,7 +20,7 @@ const eventBusMock = { const dummyMessage = new OutboxMessageEntity( 'test-id', 'TestEvent', - JSON.stringify({ prop1: 'test' }), + JSON.stringify({ event: { prop1: 'test' } }), ); const logger = new TestLogger(); diff --git a/services/monolith/src/index.ts b/services/monolith/src/index.ts index 18ac933..a54c7d5 100644 --- a/services/monolith/src/index.ts +++ b/services/monolith/src/index.ts @@ -1,4 +1,7 @@ /* istanbul ignore file */ +// open telemetry doesn't register express.js handlers if import is not on top +// eslint-disable-next-line import/order +import { provider as otelProvider } from './telemetry'; import { once } from 'events'; import * as path from 'path'; @@ -9,12 +12,15 @@ import { AbstractHttpAdapter } from '@nestjs/core'; import { NestFactoryStatic } from '@nestjs/core/nest-factory'; import { ExpressAdapter } from '@nestjs/platform-express'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; +import { SimpleSpanProcessor } from '@opentelemetry/tracing'; import { config as configureDotenv } from 'dotenv'; import { AccountContextModule } from './AccountContext/AccountContextModule'; import { AuctionContextModule } from './AuctionContext/AuctionContextModule'; import { EVENT_BUS, EventBus, EventBusCompositeCoordinator } from './Core/EventBus'; -import { NestJsLoggerAdapter } from './Core/Logger'; +import { NestJsLoggerAdapter, PinoLogger } from './Core/Logger'; +import { pinoFactory } from './Core/Logger/pinoFactory'; +import { LoggerSpanExporter } from './Core/OpenTracing'; patchNestjsSwagger(); @@ -86,6 +92,13 @@ async function createModule( throw error; } + const isProd = process.env.NODE_ENV === 'production'; + if(!isProd) { + const logger = new PinoLogger(pinoFactory()); + const spanExporter = new LoggerSpanExporter(logger); + otelProvider.addSpanProcessor(new SimpleSpanProcessor(spanExporter)); + } + const factoryOptions = { abortOnError: true }; const express = new ExpressAdapter(); diff --git a/services/monolith/src/telemetry.ts b/services/monolith/src/telemetry.ts new file mode 100644 index 0000000..a91efce --- /dev/null +++ b/services/monolith/src/telemetry.ts @@ -0,0 +1,60 @@ +import { AwsXRayIdGenerator } from '@aws/otel-aws-xray-id-generator'; +import { AWSXRayPropagator } from '@aws/otel-aws-xray-propagator'; +import { context, trace, propagation } from '@opentelemetry/api'; +import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; +import { CollectorTraceExporter } from '@opentelemetry/exporter-collector-grpc'; +import { registerInstrumentations } from '@opentelemetry/instrumentation'; +import { NodeTracerProvider } from '@opentelemetry/node'; +import { SimpleSpanProcessor } from '@opentelemetry/tracing'; + +const contextManager = new AsyncHooksContextManager(); +contextManager.enable(); + +// provider.addSpanProcessor( +// new BatchSpanProcessor( +// new ZipkinExporter({ +// serviceName: 'monolith', +// url: 'http://localhost:9411/api/v2/spans', +// }), +// ), +// ); + +propagation.setGlobalPropagator(new AWSXRayPropagator()); +// create a provider for activating and tracking with AWS IdGenerator +const tracerConfig = { + idGenerator: new AwsXRayIdGenerator(), +}; +const provider = new NodeTracerProvider(tracerConfig); +// add OTLP exporter +const otlpExporter = new CollectorTraceExporter({ + serviceName: 'monolith', + // port configured in the Collector config, defaults to 55680 + url: 'localhost:4317', +}); +provider.addSpanProcessor(new SimpleSpanProcessor(otlpExporter)); + +provider.register({ contextManager }); + +context.setGlobalContextManager(contextManager); + +trace.setGlobalTracerProvider(provider); + +registerInstrumentations({ + tracerProvider: provider, + instrumentations: [ + { + plugins: { + express: { + enabled: true, + path: '@opentelemetry/plugin-express', + }, + }, + }, + ], +}); + +console.log('OpenTelemetry initialized'); + +export { + provider, +};