diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a950a2dfce5..ee4cbcf341d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,10 +79,6 @@ jobs: - name: Checking for mis-matching dependencies... run: node common/scripts/install-run-rush.js check - - name: Prepare .npmrc for GitHub Packages - run: | - echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc - - name: Installing... run: node common/scripts/install-run-rush.js install @@ -238,10 +234,6 @@ jobs: - name: Checking for mis-matching dependencies... run: node common/scripts/install-run-rush.js check - - name: Prepare .npmrc for GitHub Packages - run: | - echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc - - name: Installing... run: node common/scripts/install-run-rush.js install @@ -368,10 +360,6 @@ jobs: - name: Checking for mis-matching dependencies... run: node common/scripts/install-run-rush.js check - - name: Prepare .npmrc for GitHub Packages - run: | - echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc - - name: Installing... run: node common/scripts/install-run-rush.js install @@ -463,10 +451,6 @@ jobs: - name: Checking for mis-matching dependencies... run: node common/scripts/install-run-rush.js check - - name: Prepare .npmrc for GitHub Packages - run: | - echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc - - name: Installing... run: node common/scripts/install-run-rush.js install @@ -541,10 +525,6 @@ jobs: - name: Checking for mis-matching dependencies... run: node common/scripts/install-run-rush.js check - - name: Prepare .npmrc for GitHub Packages - run: | - echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc - - name: Installing... run: node common/scripts/install-run-rush.js install @@ -664,10 +644,6 @@ jobs: restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }} - - name: Prepare .npmrc for GitHub Packages - run: | - echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc - - name: Installing... run: node common/scripts/install-run-rush.js install @@ -745,10 +721,6 @@ jobs: restore-keys: | ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }} - - name: Prepare .npmrc for GitHub Packages - run: | - echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc - - name: Installing... run: node common/scripts/install-run-rush.js install --purge - name: Model version from git tags @@ -851,10 +823,6 @@ jobs: restore-keys: | ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }} - - name: Prepare .npmrc for GitHub Packages - run: | - echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc - - name: Installing... run: node common/scripts/install-run-rush.js install --purge - name: Model version from git tags diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 68a6f5e10f3..e7c515284cb 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -34,6 +34,12 @@ importers: '@faker-js/faker': specifier: ^8.4.1 version: 8.4.1 + '@hcengineering/measurements': + specifier: ^0.7.0 + version: 0.7.0 + '@hcengineering/measurements-otlp': + specifier: ^0.7.0 + version: 0.7.0(encoding@0.1.13) '@hocuspocus/provider': specifier: ^2.15.2 version: 2.15.2(bufferutil@4.0.8)(utf-8-validate@6.0.4)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) @@ -61,48 +67,6 @@ importers: '@octokit/webhooks-types': specifier: ^7.3.1 version: 7.5.1 - '@opentelemetry/api': - specifier: ^1.9.0 - version: 1.9.0 - '@opentelemetry/api-logs': - specifier: ^0.203.0 - version: 0.203.0 - '@opentelemetry/auto-instrumentations-node': - specifier: ^0.62.0 - version: 0.62.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) - '@opentelemetry/core': - specifier: ^2.0.1 - version: 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-http': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-http': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/id-generator-aws-xray': - specifier: ^2.0.0 - version: 2.0.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': - specifier: ^2.0.1 - version: 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': - specifier: ^2.0.1 - version: 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-node': - specifier: ^2.0.1 - version: 2.0.1(@opentelemetry/api@1.9.0) '@playwright/test': specifier: ^1.48.2 version: 1.49.1 @@ -165,7 +129,7 @@ importers: version: file:projects/analytics-providers.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(encoding@0.1.13)(svelte@4.2.20)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) '@rush-temp/analytics-service': specifier: file:./projects/analytics-service.tgz - version: file:projects/analytics-service.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) + version: file:projects/analytics-service.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(encoding@0.1.13)(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) '@rush-temp/api-client': specifier: file:./projects/api-client.tgz version: file:projects/api-client.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@swc/core@1.13.5)(babel-jest@29.7.0(@babel/core@7.23.9))(bufferutil@4.0.8)(esbuild@0.25.9)(utf-8-validate@6.0.4) @@ -535,12 +499,6 @@ importers: '@rush-temp/mail-common': specifier: file:./projects/mail-common.tgz version: file:projects/mail-common.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@swc/core@1.13.5)(babel-jest@29.7.0(@babel/core@7.23.9)) - '@rush-temp/measurements': - specifier: file:./projects/measurements.tgz - version: file:projects/measurements.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) - '@rush-temp/measurements-otlp': - specifier: file:./projects/measurements-otlp.tgz - version: file:projects/measurements-otlp.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(encoding@0.1.13)(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) '@rush-temp/media': specifier: file:./projects/media.tgz version: file:projects/media.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) @@ -3057,6 +3015,12 @@ packages: engines: {node: '>=6'} hasBin: true + '@hcengineering/measurements-otlp@0.7.0': + resolution: {integrity: sha512-RTvUzeIKvCENCG1k8LOfBrC32GiF6fgPnqLRY5U7rXLZFISF+fLWXk1Kp7NtkbQXBUVj7C6jWfWb8psJKyIuKg==} + + '@hcengineering/measurements@0.7.0': + resolution: {integrity: sha512-RxXi7LsInAZNkDPxoS/CcGoEM8FuzYvd5xDyaKu0gQblNXrmMpePzpf4Mk9riJkeocQvzeZnduGSUPdbC6FVCw==} + '@hocuspocus/common@2.15.2': resolution: {integrity: sha512-wU1wxXNnQQMXyeL3mdSDYiQsm/r/QyJVjjQhF7sUBrLnjdsN7bA1cvfcSvJBr1ymrMSeYRmUL3UlQmEHEOaP7w==} @@ -4419,7 +4383,7 @@ packages: version: 0.0.0 '@rush-temp/analytics-service@file:projects/analytics-service.tgz': - resolution: {integrity: sha512-SbyEMU4sni8FrKq4fRlrYnrAXKOEXR+MtJq2rqR1H7tR+VHaCNToj9Sb4duvYetvhoMfrcMrJfDFdzALTmcmgw==, tarball: file:projects/analytics-service.tgz} + resolution: {integrity: sha512-nV/D7Umpfl8EbdeTJPWFf6TsSGJQBVJm0nzIkugVbscJxRPFXbvVQXvxIwIrciJHUSfJvyn+8PUGb4Io+urU+w==, tarball: file:projects/analytics-service.tgz} version: 0.0.0 '@rush-temp/analytics@file:projects/analytics.tgz': @@ -4583,7 +4547,7 @@ packages: version: 0.0.0 '@rush-temp/communication-resources@file:projects/communication-resources.tgz': - resolution: {integrity: sha512-58n6XOZoF73Mv5xxduEr6qD7ROjeb/MfQk3l+0OUtZkYTex+O0bXw8sEuY4rG+zMLOxHVfJ3by+M3esndt2g6A==, tarball: file:projects/communication-resources.tgz} + resolution: {integrity: sha512-ZcX73ZcvQEn3fa+Pvs34vMTkSEnCnkMtEgTBzqTK+i6dKE4a1HZaTmu1JTTigG4lGmPv9nb+vkgfd8yHcSxiwA==, tarball: file:projects/communication-resources.tgz} version: 0.0.0 '@rush-temp/communication-rest-client@file:projects/communication-rest-client.tgz': @@ -4603,7 +4567,7 @@ packages: version: 0.0.0 '@rush-temp/communication-types@file:projects/communication-types.tgz': - resolution: {integrity: sha512-uzZ82V1R+h+TmxBCrmKaAfUgoiX3Z8ciPGrkc42M++M5d5mlfIjTvPh0O+y50pHoFuQ5NQ3pNIjeDkrJE8Dp0w==, tarball: file:projects/communication-types.tgz} + resolution: {integrity: sha512-aXzOYngWVAf17BZO3jVuebv3HOlGDTs3l9+TQ7haGXEE4RbioRwfMEvDZUm7KiZvO/ejZlGc2Pu/3h7E54YWMA==, tarball: file:projects/communication-types.tgz} version: 0.0.0 '@rush-temp/communication@file:projects/communication.tgz': @@ -4635,7 +4599,7 @@ packages: version: 0.0.0 '@rush-temp/core@file:projects/core.tgz': - resolution: {integrity: sha512-btPoIQ23cdSItu4ElKOMNXYuXZ5FxH5PjHKpl2aQXeRNgm48Wby1DAdYeTPseiLRRZhnr94amOd3StT1RbnUUA==, tarball: file:projects/core.tgz} + resolution: {integrity: sha512-UiUM+J5QIY+nftppcxUvIbrGVnOOrj3uGdiuCky1bYV9rWAvCBEotJ3oEyYhUUsQiGQlZIi82pyfXC1be0Pqrw==, tarball: file:projects/core.tgz} version: 0.0.0 '@rush-temp/datalake@file:projects/datalake.tgz': @@ -4918,14 +4882,6 @@ packages: resolution: {integrity: sha512-FmcRe6dmbRK99u1paZJ2+f+JIpt/6rOoCZaSTUW0isvhc5+hNZaqwYFsOMAMuWRNcWlwIclEXwlwkIogHFReKA==, tarball: file:projects/mail.tgz} version: 0.0.0 - '@rush-temp/measurements-otlp@file:projects/measurements-otlp.tgz': - resolution: {integrity: sha512-OF0gOorTONul+LTXobiri6lEXqLNj5YcJnALqvFArHiEAdDnhu/2d9DqZF/+LyZ+SMtsEthL9UEbxTNb/v62Zg==, tarball: file:projects/measurements-otlp.tgz} - version: 0.0.0 - - '@rush-temp/measurements@file:projects/measurements.tgz': - resolution: {integrity: sha512-9yd6zagtxOkzBu0d8oBpu11i8L8a7mNJDQ4jQzb3qjlbLTeFXzOI49nJueQB4zO2d8lvSNrRWhTwJX0ZDHRp8w==, tarball: file:projects/measurements.tgz} - version: 0.0.0 - '@rush-temp/media-assets@file:projects/media-assets.tgz': resolution: {integrity: sha512-5Ppzy6nUxEpzPMKj0xuJTO5Ai0hLAnC7MpNSQ2/euFK56V7L4VeqP8RIuODpZbxtNQueZgVDe7/HrjQN6hDe+g==, tarball: file:projects/media-assets.tgz} version: 0.0.0 @@ -5103,7 +5059,7 @@ packages: version: 0.0.0 '@rush-temp/model-process@file:projects/model-process.tgz': - resolution: {integrity: sha512-/Qar0A6nR5NxD11A64Alers7Dugvmcdo5h7TAV8NB20EroGB2ATe+rqEb6IQzGQ95zwU0QdZ6znWIAXseFCiHA==, tarball: file:projects/model-process.tgz} + resolution: {integrity: sha512-KYA1lJziZLHn/H7Af60nn3W1BCKCp5XDUSH1nCwf3s1vpX/4dRCw9WTGDUYIf0VnpFlr2IaNacsv270ixP64NA==, tarball: file:projects/model-process.tgz} version: 0.0.0 '@rush-temp/model-products@file:projects/model-products.tgz': @@ -5451,7 +5407,7 @@ packages: version: 0.0.0 '@rush-temp/pod-process@file:projects/pod-process.tgz': - resolution: {integrity: sha512-7KLw9Zd8C5hcal9nFPc8zsuWXy8udYCz70h1dsJ9V5vQUnxEL1wyUH2WKSssAsi+yOSy0p0TynCIuIWuH4W0yQ==, tarball: file:projects/pod-process.tgz} + resolution: {integrity: sha512-HNjCJu8XARw6z69jefA0UpCQGz64Ieklyr/0rljMQgsle2/S9BJZDgPZbh9JKHctvRWGOO6666JvaYFAxCKF9A==, tarball: file:projects/pod-process.tgz} version: 0.0.0 '@rush-temp/pod-server@file:projects/pod-server.tgz': @@ -5603,7 +5559,7 @@ packages: version: 0.0.0 '@rush-temp/recruit@file:projects/recruit.tgz': - resolution: {integrity: sha512-haibbmoHj99CxThRcs1uk79phPTmJoU0N41EIR5nY76a8434F2H5HxAqVu+lLhZDGajZQitXtEQByDNqgK4kHg==, tarball: file:projects/recruit.tgz} + resolution: {integrity: sha512-Q6S3IsrawYcEoxt0bdEQri2gZUFXEw9muto9EviPHS/MUAr3WN/68WhNoq3uHmTbl2Un5zNXeM1nZeBLoo3rDQ==, tarball: file:projects/recruit.tgz} version: 0.0.0 '@rush-temp/rekoni-service@file:projects/rekoni-service.tgz': @@ -6059,7 +6015,7 @@ packages: version: 0.0.0 '@rush-temp/text-editor-resources@file:projects/text-editor-resources.tgz': - resolution: {integrity: sha512-2aRRXC4H573M3+OR/vRe5pGoA4tAB3jEbufqAe4/EgKkUHvRlGVZBBUyDAfYtsIHQd7IrAEEVK1NQoC6iZE1Lg==, tarball: file:projects/text-editor-resources.tgz} + resolution: {integrity: sha512-cuY6deLmbq73Rd72z7F2kq8olFFWw+6E053bWb0LqIcJqxPlK2eJkZLgmCpOghVSMzQCb00bQ6lPI4PIUFlJGg==, tarball: file:projects/text-editor-resources.tgz} version: 0.0.0 '@rush-temp/text-editor@file:projects/text-editor.tgz': @@ -6075,7 +6031,7 @@ packages: version: 0.0.0 '@rush-temp/text-ydoc@file:projects/text-ydoc.tgz': - resolution: {integrity: sha512-EdNN9bQUsIb2qPGpotFbm5xIQDH1GJilcCiV66EVTlrsRkQSAjqVDPZyhQALE8200gR8K7OCSayKoQPnb/nPEA==, tarball: file:projects/text-ydoc.tgz} + resolution: {integrity: sha512-7gAsQxiYN/g2MBMo+mvH8ck91Sd4FligskIYDHpwl6uI4mtn2qTLT6yTT3rWbsr/dvbIaLeDrzb4mEkE1ugM9Q==, tarball: file:projects/text-ydoc.tgz} version: 0.0.0 '@rush-temp/text@file:projects/text.tgz': @@ -15587,6 +15543,29 @@ snapshots: protobufjs: 7.5.3 yargs: 17.7.2 + '@hcengineering/measurements-otlp@0.7.0(encoding@0.1.13)': + dependencies: + '@hcengineering/measurements': 0.7.0 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.203.0 + '@opentelemetry/auto-instrumentations-node': 0.62.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) + '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-logs-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/id-generator-aws-xray': 2.0.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-node': 2.0.1(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - encoding + - supports-color + + '@hcengineering/measurements@0.7.0': {} + '@hocuspocus/common@2.15.2': dependencies: lib0: 0.2.114 @@ -17841,8 +17820,9 @@ snapshots: - svelte - ts-node - '@rush-temp/analytics-service@file:projects/analytics-service.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3))': + '@rush-temp/analytics-service@file:projects/analytics-service.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(encoding@0.1.13)(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3))': dependencies: + '@hcengineering/measurements-otlp': 0.7.0(encoding@0.1.13) '@types/jest': 29.5.12 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) @@ -17864,6 +17844,7 @@ snapshots: - '@types/node' - babel-jest - babel-plugin-macros + - encoding - esbuild - node-notifier - supports-color @@ -19473,6 +19454,7 @@ snapshots: '@rush-temp/core@file:projects/core.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3))': dependencies: + '@hcengineering/measurements': 0.7.0 '@types/jest': 29.5.12 '@types/node': 22.15.29 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) @@ -21721,73 +21703,6 @@ snapshots: - supports-color - ts-node - '@rush-temp/measurements-otlp@file:projects/measurements-otlp.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(encoding@0.1.13)(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3))': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/auto-instrumentations-node': 0.62.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/id-generator-aws-xray': 2.0.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-node': 2.0.1(@opentelemetry/api@1.9.0) - '@types/jest': 29.5.12 - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) - '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) - eslint: 8.56.0 - eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3))(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint-plugin-n@15.7.0(eslint@8.56.0))(eslint-plugin-promise@6.1.1(eslint@8.56.0))(eslint@8.56.0)(typescript@5.8.3) - eslint-plugin-import: 2.29.1(eslint@8.56.0) - eslint-plugin-n: 15.7.0(eslint@8.56.0) - eslint-plugin-promise: 6.1.1(eslint@8.56.0) - jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) - prettier: 3.2.5 - simplytyped: 3.3.0(typescript@5.8.3) - ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)))(typescript@5.8.3) - typescript: 5.8.3 - transitivePeerDependencies: - - '@babel/core' - - '@jest/types' - - '@types/node' - - babel-jest - - babel-plugin-macros - - encoding - - esbuild - - node-notifier - - supports-color - - ts-node - - '@rush-temp/measurements@file:projects/measurements.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3))': - dependencies: - '@types/jest': 29.5.12 - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3) - '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.8.3) - eslint: 8.56.0 - eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.3))(eslint@8.56.0)(typescript@5.8.3))(eslint-plugin-import@2.29.1(eslint@8.56.0))(eslint-plugin-n@15.7.0(eslint@8.56.0))(eslint-plugin-promise@6.1.1(eslint@8.56.0))(eslint@8.56.0)(typescript@5.8.3) - eslint-plugin-import: 2.29.1(eslint@8.56.0) - eslint-plugin-n: 15.7.0(eslint@8.56.0) - eslint-plugin-promise: 6.1.1(eslint@8.56.0) - jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) - prettier: 3.2.5 - simplytyped: 3.3.0(typescript@5.8.3) - ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)))(typescript@5.8.3) - typescript: 5.8.3 - transitivePeerDependencies: - - '@babel/core' - - '@jest/types' - - '@types/node' - - babel-jest - - babel-plugin-macros - - esbuild - - node-notifier - - supports-color - - ts-node - '@rush-temp/media-assets@file:projects/media-assets.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3))': dependencies: '@types/jest': 29.5.12 @@ -30027,7 +29942,6 @@ snapshots: fast-equals: 5.2.2 jest: 29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)) jest-environment-jsdom: 29.7.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) - lib0: 0.2.114 prettier: 3.2.5 ts-jest: 29.1.2(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.25.9)(jest@29.7.0(@types/node@22.15.29)(ts-node@10.9.2(@swc/core@1.13.5)(@types/node@22.15.29)(typescript@5.8.3)))(typescript@5.8.3) typescript: 5.8.3 @@ -32115,7 +32029,7 @@ snapshots: '@types/pg-pool@2.0.6': dependencies: - '@types/pg': 8.11.11 + '@types/pg': 8.15.4 '@types/pg@8.11.11': dependencies: @@ -40650,19 +40564,19 @@ snapshots: y-indexeddb@9.0.12(yjs@13.6.27): dependencies: - lib0: 0.2.89 + lib0: 0.2.114 yjs: 13.6.27 y-leveldb@0.1.2(yjs@13.6.27): dependencies: level: 6.0.1 - lib0: 0.2.109 + lib0: 0.2.114 yjs: 13.6.27 optional: true y-prosemirror@1.3.7(prosemirror-model@1.24.1)(prosemirror-state@1.4.3)(prosemirror-view@1.37.2)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27): dependencies: - lib0: 0.2.109 + lib0: 0.2.114 prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 prosemirror-view: 1.37.2 @@ -40671,7 +40585,7 @@ snapshots: y-protocols@1.0.6(yjs@13.6.27): dependencies: - lib0: 0.2.89 + lib0: 0.2.114 yjs: 13.6.27 y-websocket@2.1.0(yjs@13.6.27): @@ -40739,7 +40653,7 @@ snapshots: yjs@13.6.27: dependencies: - lib0: 0.2.109 + lib0: 0.2.114 ylru@1.3.2: {} diff --git a/packages/analytics-service/package.json b/packages/analytics-service/package.json index 0dd58651e50..4365990e98a 100644 --- a/packages/analytics-service/package.json +++ b/packages/analytics-service/package.json @@ -41,7 +41,7 @@ "@hcengineering/platform": "^0.6.11", "@hcengineering/core": "^0.6.32", "@hcengineering/analytics": "^0.6.0", - "@hcengineering/measurements-otlp": "^0.6.0", + "@hcengineering/measurements-otlp": "^0.7.0", "winston": "^3.11.0", "winston-daily-rotate-file": "^5.0.0" }, diff --git a/packages/core/package.json b/packages/core/package.json index dca0881af8e..4e952538228 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -41,7 +41,7 @@ "dependencies": { "@hcengineering/platform": "^0.6.11", "@hcengineering/analytics": "^0.6.0", - "@hcengineering/measurements": "^0.6.0", + "@hcengineering/measurements": "^0.7.0", "fast-equals": "^5.2.2" }, "repository": "https://github.com/hcengineering/platform", diff --git a/packages/measurements-otlp/.eslintrc.js b/packages/measurements-otlp/.eslintrc.js deleted file mode 100644 index 72235dc2833..00000000000 --- a/packages/measurements-otlp/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'], - parserOptions: { - tsconfigRootDir: __dirname, - project: './tsconfig.json' - } -} diff --git a/packages/measurements-otlp/.npmignore b/packages/measurements-otlp/.npmignore deleted file mode 100644 index e3ec093c383..00000000000 --- a/packages/measurements-otlp/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -* -!/lib/** -!CHANGELOG.md -/lib/**/__tests__/ diff --git a/packages/measurements-otlp/config/rig.json b/packages/measurements-otlp/config/rig.json deleted file mode 100644 index 0110930f55e..00000000000 --- a/packages/measurements-otlp/config/rig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", - "rigPackageName": "@hcengineering/platform-rig" -} diff --git a/packages/measurements-otlp/jest.config.js b/packages/measurements-otlp/jest.config.js deleted file mode 100644 index 2cfd408b679..00000000000 --- a/packages/measurements-otlp/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], - roots: ["./src"], - coverageReporters: ["text-summary", "html"] -} diff --git a/packages/measurements-otlp/package.json b/packages/measurements-otlp/package.json deleted file mode 100644 index 79f67f2ae76..00000000000 --- a/packages/measurements-otlp/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "@hcengineering/measurements-otlp", - "version": "0.6.0", - "main": "lib/index.js", - "svelte": "src/index.ts", - "types": "types/index.d.ts", - "files": [ - "lib/**/*", - "types/**/*", - "tsconfig.json" - ], - "author": "Anticrm Platform Contributors", - "license": "EPL-2.0", - "scripts": { - "build": "compile", - "build:watch": "compile", - "test": "jest --passWithNoTests --silent", - "format": "format src", - "_phase:build": "compile transpile src", - "_phase:test": "jest --passWithNoTests --silent", - "_phase:format": "format src", - "_phase:validate": "compile validate" - }, - "devDependencies": { - "@hcengineering/platform-rig": "^0.6.0", - "@typescript-eslint/eslint-plugin": "^6.11.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-n": "^15.4.0", - "eslint": "^8.54.0", - "simplytyped": "^3.3.0", - "@typescript-eslint/parser": "^6.11.0", - "eslint-config-standard-with-typescript": "^40.0.0", - "prettier": "^3.1.0", - "typescript": "^5.8.3", - "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "@types/jest": "^29.5.5" - }, - "dependencies": { - "@hcengineering/measurements": "^0.6.0", - "@opentelemetry/sdk-node": "^0.203.0", - "@opentelemetry/sdk-logs": "^0.203.0", - "@opentelemetry/auto-instrumentations-node": "^0.62.0", - "@opentelemetry/resources": "^2.0.1", - "@opentelemetry/sdk-trace-node": "^2.0.1", - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/core": "^2.0.1", - "@opentelemetry/exporter-trace-otlp-http": "^0.203.0", - "@opentelemetry/exporter-logs-otlp-http": "^0.203.0", - "@opentelemetry/otlp-exporter-base": "^0.203.0", - "@opentelemetry/id-generator-aws-xray": "^2.0.0", - "@opentelemetry/exporter-metrics-otlp-http": "^0.203.0", - "@opentelemetry/api-logs": "^0.203.0", - "@opentelemetry/sdk-metrics": "^2.0.1" - }, - "repository": "https://github.com/hcengineering/platform", - "publishConfig": { - "access": "public" - } -} diff --git a/packages/measurements-otlp/src/index.ts b/packages/measurements-otlp/src/index.ts deleted file mode 100644 index 8b5ba81c39f..00000000000 --- a/packages/measurements-otlp/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './telemetry' diff --git a/packages/measurements-otlp/src/telemetry.ts b/packages/measurements-otlp/src/telemetry.ts deleted file mode 100644 index ec170c01623..00000000000 --- a/packages/measurements-otlp/src/telemetry.ts +++ /dev/null @@ -1,608 +0,0 @@ -import { - childMetrics, - consoleLogger, - MeasureContext, - MeasureMetricsContext, - newMetrics, - noParamsLogger, - nullPromise, - platformNow, - platformNowDiff, - updateMeasure, - type FullParamsType, - type MeasureLogger, - type Metrics, - type ParamsType, - type WithOptions -} from '@hcengineering/measurements' -import { - context, - metrics as otelMetrics, - propagation, - Span, - SpanStatusCode, - trace, - type Context, - type Gauge, - type Meter, - type Tracer -} from '@opentelemetry/api' -import { Logger, SeverityNumber } from '@opentelemetry/api-logs' -import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node' -import { suppressTracing } from '@opentelemetry/core' -import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http' -import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http' -import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http' -import { AWSXRayIdGenerator } from '@opentelemetry/id-generator-aws-xray' -import { CompressionAlgorithm } from '@opentelemetry/otlp-exporter-base' -import { resourceFromAttributes } from '@opentelemetry/resources' -import { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs' -import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics' -import { NodeSDK } from '@opentelemetry/sdk-node' -import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-node' - -class MetricsContext { - counters = new Map() - constructor (readonly meter?: Meter) {} - - getCounter (name: string): { counter: Gauge, value: number } | undefined { - if (this.meter === undefined) { - return undefined - } - let counter = this.counters.get(name) - if (counter === undefined) { - counter = { counter: this.meter.createGauge(name), value: 0 } - this.counters.set(name, counter) - } - return counter - } -} - -/** - * @public - */ -export class OpenTelemetryMetricsContext implements MeasureContext { - private readonly name: string - private readonly params: ParamsType - - private readonly fullParams: FullParamsType | (() => FullParamsType) = {} - logger: MeasureLogger - metrics: Metrics - id?: string - - st = platformNow() - contextData: object = {} - isDone = false - doneTrace: string = '' - - private done (value?: number, override?: boolean): void { - if (!this.isDone) { - this.doneTrace = new Error().stack ?? '' - this.isDone = true - updateMeasure(this.metrics, this.st, this.params, this.fullParams, (spend) => {}, value, override) - this.span?.end() - } - } - - constructor ( - name: string, - readonly tracer: Tracer, - readonly context: Context | undefined, - readonly span: Span | undefined, - params: ParamsType, - fullParams: FullParamsType | (() => FullParamsType) = {}, - metrics: Metrics = newMetrics(), - logger?: MeasureLogger, - readonly parent?: MeasureContext, - readonly logParams?: ParamsType, - - readonly otlpLogger?: Logger, - readonly meter?: MetricsContext - ) { - this.name = name - this.params = params - this.fullParams = fullParams - this.metrics = metrics - this.metrics.namedParams = this.metrics.namedParams ?? {} - for (const [k, v] of Object.entries(params)) { - if (this.metrics.namedParams[k] !== v) { - this.metrics.namedParams[k] = v - } else { - this.metrics.namedParams[k] = '*' - } - } - - this.logger = logger ?? (this.logParams != null ? consoleLogger(this.logParams ?? {}) : noParamsLogger) - } - - measure (name: string, value: number, override?: boolean): void { - const cnt = this.meter?.getCounter(name) - if (cnt !== undefined) { - if (cnt.value !== value) { - cnt.counter.record(value, this.params) - cnt.value = value - } - } - } - - newChild ( - name: string, - params: ParamsType, - opt?: { - fullParams?: FullParamsType - logger?: MeasureLogger - span?: WithOptions['span'] // By default true - meta?: Record - } - ): MeasureContext { - let _span: Span | undefined - let childContext: Context | undefined - if (opt?.span === true || opt?.span === 'inherit') { - childContext = opt?.span === 'inherit' ? context.active() : this.context ?? context.active() - - if (opt.meta !== undefined && Object.keys(opt.meta).length > 0) { - // We need to set meta params - childContext = propagation.extract(childContext ?? context.active(), opt.meta) - } - _span = this.tracer.startSpan(name, undefined, childContext) - - const spanParams = [...Object.entries(params)] - for (const [k, v] of spanParams) { - _span?.setAttribute(k, v as any) - } - } - if (opt?.span === 'disable') { - childContext = suppressTracing(childContext ?? context.active()) - } - if (childContext !== undefined && _span !== undefined) { - childContext = trace.setSpan(childContext, _span) - } - - const result = new OpenTelemetryMetricsContext( - name, - this.tracer, - childContext, - _span, - params, - opt?.fullParams ?? {}, - childMetrics(this.metrics, [name]), - opt?.logger ?? this.logger, - this, - this.logParams, - this.otlpLogger, - this.meter - ) - result.id = this.id - result.contextData = this.contextData - return result - } - - extractMeta (): Record { - const headers: Record = {} - if (this.context !== undefined) { - propagation.inject(this.context, headers) - } - return headers - } - - with( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T | Promise, - fullParams?: ParamsType | (() => FullParamsType), - opt?: WithOptions - ): Promise { - const c = this.newChild(name, opt?.inheritParams === true ? { ...this.params, ...params } : params, { - fullParams, - logger: this.logger, - span: opt?.span ?? true, - meta: opt?.meta - }) - let needFinally = true - try { - const _context = (c as OpenTelemetryMetricsContext).context - - const span = (c as OpenTelemetryMetricsContext).span - - const value = _context !== undefined ? context.with(_context, () => op(c)) : op(c) - if (value instanceof Promise) { - needFinally = false - if (span !== undefined) { - void value.catch((err) => { - span?.recordException(err) - span?.setStatus({ - code: SpanStatusCode.ERROR, - message: err.message - }) - }) - } - return value.finally(() => { - if (span !== undefined) { - const fParams = typeof fullParams === 'function' ? fullParams() : fullParams - const spanParams = [...Object.entries(params), ...Object.entries(fParams ?? {})] - for (const [k, v] of spanParams) { - span?.setAttribute(k, typeof v === 'object' ? JSON.stringify(v) : v) - } - } - c.end() - if (opt?.log === true) { - this.logger.logOperation(name, platformNowDiff((c as OpenTelemetryMetricsContext).st), { - ...params, - ...fullParams - }) - } - }) - } else { - if (value == null) { - return nullPromise as Promise - } - return Promise.resolve(value) - } - } finally { - if (needFinally) { - c.end() - } - } - } - - withSync( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T, - fullParams?: ParamsType | (() => FullParamsType), - opt?: WithOptions - ): T { - const c = this.newChild(name, params, { fullParams, logger: this.logger, span: opt?.span ?? true }) - const _context = (c as OpenTelemetryMetricsContext).context - try { - return _context !== undefined ? context.with(_context, () => op(c)) : op(c) - } finally { - c.end() - } - } - - error (message: string, args?: Record): void { - if (this.otlpLogger !== undefined) { - this.otlpLogger.emit({ - severityNumber: SeverityNumber.ERROR, - severityText: 'error', - context: this.context, - body: message, - attributes: { - 'service.name': sdkServiceName, - ...(args ?? {}) - } - }) - } - this.logger.error(message, { ...this.params, ...args, ...(this.logParams ?? {}) }) - } - - info (message: string, args?: Record): void { - if (this.otlpLogger !== undefined) { - this.otlpLogger.emit({ - context: this.context, - severityNumber: SeverityNumber.INFO, - severityText: 'info', - body: message, - attributes: { - 'service.name': sdkServiceName, - ...(args ?? {}) - } - }) - } - this.logger.info(message, { ...this.params, ...args, ...(this.logParams ?? {}) }) - } - - warn (message: string, args?: Record): void { - if (this.otlpLogger !== undefined) { - this.otlpLogger.emit({ - severityNumber: SeverityNumber.WARN, - severityText: 'warn', - context: this.context, - body: message, - attributes: { - 'service.name': sdkServiceName, - ...(args ?? {}) - } - }) - } - this.logger.warn(message, { ...this.params, ...args, ...(this.logParams ?? {}) }) - } - - end (): void { - this.done() - } - - getParams (): ParamsType { - return this.params - } -} - -/** - * Parse W3C baggage header format to Record - * - * W3C baggage format: "key1=value1,key2=value2;property=value,key3=value3" - * Returns only the key-value pairs, ignoring properties - */ -function parseBaggage (baggageHeader?: string): Record { - if (baggageHeader == null || typeof baggageHeader !== 'string') { - return {} - } - - const result: Record = {} - - // Split by comma to get individual baggage members - const members = baggageHeader.split(',') - - for (const member of members) { - const trimmedMember = member.trim() - if (trimmedMember === '') continue - - // Split by semicolon to separate key=value from properties - const parts = trimmedMember.split(';') - const keyValuePart = parts[0]?.trim() - - if (keyValuePart == null) continue - - // Split by equals to get key and value - const equalIndex = keyValuePart.indexOf('=') - if (equalIndex === -1) continue - - const key = keyValuePart.substring(0, equalIndex).trim() - const value = keyValuePart.substring(equalIndex + 1).trim() - - if (key != null) { - // URL decode the key and value - try { - const decodedKey = decodeURIComponent(key) - const decodedValue = decodeURIComponent(value) - result[decodedKey] = decodedValue - } catch (error) { - // If decoding fails, use the original values - result[key] = value - } - } - } - - return result -} - -let sdk: NodeSDK | undefined -let sdkServiceName: string | undefined -let sdkServiceVersion: string | undefined -let loggerProvider: LoggerProvider | undefined - -export function initOpenTelemetrySDK (serviceName: string, version: string): boolean { - if (sdk !== undefined) { - return true - } - process.env.OTEL_SERVICE_NAME = serviceName - process.env.OTEL_SERVICE_VERSION = version - - sdkServiceName = serviceName - sdkServiceVersion = version - const tracesUrl = getTracesUrl() - - if (tracesUrl === undefined) { - return false - } - - const traceHeaders = parseTraceExporterHeaders() - - const exporter = new OTLPTraceExporter({ - url: tracesUrl, - headers: traceHeaders, - compression: - (process.env.OTEL_EXPORTER_OTLP_COMPRESSION as CompressionAlgorithm) ?? - (process.env.OTEL_EXPORTER_OTLP_TRACES_COMPRESSION as CompressionAlgorithm) ?? - CompressionAlgorithm.GZIP, - keepAlive: true - }) - - const batchSpanProcessor = new BatchSpanProcessor(exporter, { - maxExportBatchSize: parseInt(process.env.OTEL_EXPORTER_OTLP_TRACES_MAX_EXPORT_BATCH_SIZE ?? '1000'), - maxQueueSize: parseInt(process.env.OTEL_EXPORTER_OTLP_TRACES_MAX_QUEUE_SIZE ?? '1000') - }) - - // Logs - const logsEndpoint = getLogsUrl() - const logHeaders = parseLogsExporterHeaders() - const logExporter = new OTLPLogExporter({ - url: logsEndpoint, - headers: logHeaders, - compression: - (process.env.OTEL_EXPORTER_OTLP_COMPRESSION as CompressionAlgorithm) ?? - (process.env.OTEL_EXPORTER_OTLP_LOGS_COMPRESSION as CompressionAlgorithm) ?? - CompressionAlgorithm.GZIP, - keepAlive: true - }) - - const batchLogProcessor = new BatchLogRecordProcessor(logExporter, { - maxExportBatchSize: parseInt(process.env.OTEL_EXPORTER_OTLP_LOGS_MAX_EXPORT_BATCH_SIZE ?? '1000'), - maxQueueSize: parseInt(process.env.OTEL_EXPORTER_OTLP_LOGS_MAX_QUEUE_SIZE ?? '1000') - }) - - // Metrics - - const metricsUrl = getMetricsUrl() - const metricsHeaders = parseMetricsExporterHeaders() - const metricsExporter = new OTLPMetricExporter({ - url: metricsUrl, - headers: metricsHeaders - }) - const metricReader = new PeriodicExportingMetricReader({ - exporter: metricsExporter, - exportIntervalMillis: 15000 - }) - - // SDK - - sdk = new NodeSDK({ - spanProcessors: [batchSpanProcessor], - serviceName, - traceExporter: exporter, - resource: resourceFromAttributes({ - 'service-name': serviceName, - 'service-version': version ?? '0.7', - 'deployment-environment': process.env.OTEL_ENVIRONMENT - }), - instrumentations: [getNodeAutoInstrumentations()], - idGenerator: new AWSXRayIdGenerator(), - logRecordProcessors: [batchLogProcessor], - metricReader - }) - - sdk.start() - - loggerProvider = new LoggerProvider({ - processors: [batchLogProcessor] - }) - - // Graceful shutdown - process.on('SIGTERM', () => { - sdk - ?.shutdown() - .then(() => { - console.log('Tracing terminated') - }) - .catch((error) => { - console.log('Error terminating tracing', error) - }) - .finally(() => process.exit(0)) - }) - console.log('Using open telemetry metrics context', { - traceEndpoint: tracesUrl, - tracerHeadersSet: Array.from(Object.keys(traceHeaders)), - logsEndpoint, - logHeadersSet: Array.from(Object.keys(logHeaders)) - }) - return true -} - -export function reportOTELError (error: Error): void { - if (sdkServiceName !== undefined && sdkServiceVersion !== undefined && loggerProvider !== undefined) { - const otlpLogger = loggerProvider?.getLogger(sdkServiceName, sdkServiceVersion) - otlpLogger?.emit({ - severityNumber: SeverityNumber.ERROR, - severityText: 'error', - body: error.message, - context: context.active(), - attributes: { - 'service.name': sdkServiceName, - 'service.version': sdkServiceVersion, - 'error.stack': error.stack - } - }) - } -} - -export function createOpenTelemetryMetricsContext ( - name: string, - params: ParamsType, - fullParams: FullParamsType | (() => FullParamsType) = {}, - metrics: Metrics = newMetrics(), - logger?: MeasureLogger, - version?: string -): MeasureContext { - if (!initOpenTelemetrySDK(name, version ?? '')) { - console.warn('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT is not set, OpenTelemetry metrics will not be sent') - return new MeasureMetricsContext(name, params, fullParams, metrics, logger) - } - - // Traces - - const tracer = trace.getTracer(name) - - const otlpLogger = - process.env.OTEL_LOGGER_ENABLED === 'true' ? loggerProvider?.getLogger(sdkServiceName ?? name, version) : undefined - - const meter = otelMetrics.getMeter(name, version) - - const ctx = new OpenTelemetryMetricsContext( - name, - tracer, - undefined, - undefined, - params, - fullParams, - metrics, - logger, - undefined, - undefined, - otlpLogger, - new MetricsContext(meter) - ) - return ctx -} -function parseTraceExporterHeaders (): Record { - const headers: Record = parseBaggage(process.env.OTEL_EXPORTER_OTLP_HEADERS) ?? {} - - if (process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS !== undefined) { - const extraHeaders = parseBaggage(process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS) - for (const [key, value] of Object.entries(extraHeaders)) { - headers[key] = value - } - } - return headers -} - -function getTracesUrl (): string | undefined { - let tracesUrl = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? process.env.OTEL_EXPORTER_OTLP_ENDPOINT - - if (tracesUrl !== undefined && !tracesUrl.endsWith('/v1/traces')) { - if (tracesUrl.endsWith('/')) { - tracesUrl += 'v1/traces' - } else { - tracesUrl += '/v1/traces' - } - } - return tracesUrl -} - -function getLogsUrl (): string | undefined { - let logsUrl = process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT ?? process.env.OTEL_EXPORTER_OTLP_ENDPOINT - - if (logsUrl !== undefined && !logsUrl.endsWith('/v1/logs')) { - if (logsUrl.endsWith('/')) { - logsUrl += 'v1/logs' - } else { - logsUrl += '/v1/logs' - } - } - return logsUrl -} -function parseLogsExporterHeaders (): Record { - const headers: Record = parseBaggage(process.env.OTEL_EXPORTER_OTLP_HEADERS) ?? {} - - if (process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS !== undefined) { - const extraHeaders = parseBaggage(process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS) - for (const [key, value] of Object.entries(extraHeaders)) { - headers[key] = value - } - } - return headers -} - -function getMetricsUrl (): string | undefined { - let metricsUrl = process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT ?? process.env.OTEL_EXPORTER_OTLP_ENDPOINT - - if (metricsUrl !== undefined && !metricsUrl.endsWith('/v1/metrics')) { - if (metricsUrl.endsWith('/')) { - metricsUrl += 'v1/metrics' - } else { - metricsUrl += '/v1/metrics' - } - } - return metricsUrl -} -function parseMetricsExporterHeaders (): Record { - const headers: Record = parseBaggage(process.env.OTEL_EXPORTER_OTLP_HEADERS) ?? {} - - if (process.env.OTEL_EXPORTER_OTLP_METRICS_HEADERS !== undefined) { - const extraHeaders = parseBaggage(process.env.OTEL_EXPORTER_OTLP_METRICS_HEADERS) - for (const [key, value] of Object.entries(extraHeaders)) { - headers[key] = value - } - } - return headers -} diff --git a/packages/measurements-otlp/tsconfig.json b/packages/measurements-otlp/tsconfig.json deleted file mode 100644 index b5ae22f6e46..00000000000 --- a/packages/measurements-otlp/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json", - - "compilerOptions": { - "rootDir": "./src", - "outDir": "./lib", - "declarationDir": "./types", - "tsBuildInfoFile": ".build/build.tsbuildinfo" - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "lib", "dist", "types", "bundle"] -} \ No newline at end of file diff --git a/packages/measurements/.eslintrc.js b/packages/measurements/.eslintrc.js deleted file mode 100644 index 72235dc2833..00000000000 --- a/packages/measurements/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'], - parserOptions: { - tsconfigRootDir: __dirname, - project: './tsconfig.json' - } -} diff --git a/packages/measurements/.npmignore b/packages/measurements/.npmignore deleted file mode 100644 index e3ec093c383..00000000000 --- a/packages/measurements/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -* -!/lib/** -!CHANGELOG.md -/lib/**/__tests__/ diff --git a/packages/measurements/config/rig.json b/packages/measurements/config/rig.json deleted file mode 100644 index 0110930f55e..00000000000 --- a/packages/measurements/config/rig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", - "rigPackageName": "@hcengineering/platform-rig" -} diff --git a/packages/measurements/jest.config.js b/packages/measurements/jest.config.js deleted file mode 100644 index 2cfd408b679..00000000000 --- a/packages/measurements/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], - roots: ["./src"], - coverageReporters: ["text-summary", "html"] -} diff --git a/packages/measurements/package.json b/packages/measurements/package.json deleted file mode 100644 index 9f78a24bd38..00000000000 --- a/packages/measurements/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@hcengineering/measurements", - "version": "0.6.0", - "main": "lib/index.js", - "svelte": "src/index.ts", - "types": "types/index.d.ts", - "files": [ - "lib/**/*", - "types/**/*", - "tsconfig.json" - ], - "author": "Anticrm Platform Contributors", - "license": "EPL-2.0", - "scripts": { - "build": "compile", - "build:watch": "compile", - "test": "jest --passWithNoTests --silent", - "format": "format src", - "_phase:build": "compile transpile src", - "_phase:test": "jest --passWithNoTests --silent", - "_phase:format": "format src", - "_phase:validate": "compile validate" - }, - "devDependencies": { - "@hcengineering/platform-rig": "^0.6.0", - "@typescript-eslint/eslint-plugin": "^6.11.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-n": "^15.4.0", - "eslint": "^8.54.0", - "simplytyped": "^3.3.0", - "@typescript-eslint/parser": "^6.11.0", - "eslint-config-standard-with-typescript": "^40.0.0", - "prettier": "^3.1.0", - "typescript": "^5.8.3", - "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "@types/jest": "^29.5.5" - }, - "repository": "https://github.com/hcengineering/platform", - "publishConfig": { - "access": "public" - }, - "exports": { - ".": { - "types": "./types/index.d.ts", - "require": "./lib/index.js", - "import": "./lib/index.js" - } - } -} diff --git a/packages/measurements/src/context.ts b/packages/measurements/src/context.ts deleted file mode 100644 index 50808665181..00000000000 --- a/packages/measurements/src/context.ts +++ /dev/null @@ -1,386 +0,0 @@ -// Basic performance metrics suite. - -import { platformNow, platformNowDiff } from '.' -import { childMetrics, newMetrics, updateMeasure } from './metrics' -import { - type FullParamsType, - type MeasureContext, - type MeasureLogger, - type Metrics, - type ParamsType, - type OperationLog, - type OperationLogEntry, - type WithOptions -} from './types' - -const errorPrinter = ({ message, stack, ...rest }: Error): object => ({ - message, - stack, - ...rest -}) -function replacer (value: any): any { - return value instanceof Error ? errorPrinter(value) : value -} - -export const consoleLogger = (logParams: Record): MeasureLogger => ({ - info: (msg, args) => { - console.info( - msg, - ...Object.entries({ ...(args ?? {}), ...(logParams ?? {}) }).map( - (it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}` - ) - ) - }, - error: (msg, args) => { - console.error( - msg, - ...Object.entries({ ...(args ?? {}), ...(logParams ?? {}) }).map( - (it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}` - ) - ) - }, - warn: (msg, args) => { - console.warn(msg, ...Object.entries(args ?? {}).map((it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}`)) - }, - close: async () => {}, - logOperation: (operation, time, params) => {} -}) - -export const noParamsLogger = consoleLogger({}) - -export const nullPromise = Promise.resolve() - -/** - * @public - */ -export class MeasureMetricsContext implements MeasureContext { - private readonly name: string - private readonly params: ParamsType - - private readonly fullParams: FullParamsType | (() => FullParamsType) = {} - logger: MeasureLogger - metrics: Metrics - id?: string - - st = platformNow() - contextData: object = {} - private done (value?: number, override?: boolean): void { - updateMeasure(this.metrics, this.st, this.params, this.fullParams, (spend) => {}, value, override) - } - - constructor ( - name: string, - params: ParamsType, - fullParams: FullParamsType | (() => FullParamsType) = {}, - metrics: Metrics = newMetrics(), - logger?: MeasureLogger, - readonly parent?: MeasureContext, - readonly logParams?: ParamsType - ) { - this.name = name - this.params = params - this.fullParams = fullParams - this.metrics = metrics - this.metrics.namedParams = this.metrics.namedParams ?? {} - for (const [k, v] of Object.entries(params)) { - if (this.metrics.namedParams[k] !== v) { - this.metrics.namedParams[k] = v - } else { - this.metrics.namedParams[k] = '*' - } - } - - this.logger = logger ?? (this.logParams != null ? consoleLogger(this.logParams ?? {}) : noParamsLogger) - } - - measure (name: string, value: number, override?: boolean): void { - const c = new MeasureMetricsContext('#' + name, {}, {}, childMetrics(this.metrics, ['#' + name]), this.logger, this) - c.contextData = this.contextData - c.done(value, override) - } - - newChild ( - name: string, - params: ParamsType, - opt?: { - fullParams?: FullParamsType - logger?: MeasureLogger - span?: WithOptions['span'] // By default true - } - ): MeasureContext { - const result = new MeasureMetricsContext( - name, - params, - opt?.fullParams ?? {}, - childMetrics(this.metrics, [name]), - opt?.logger ?? this.logger, - this, - this.logParams - ) - result.id = this.id - result.contextData = this.contextData - return result - } - - with( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T | Promise, - fullParams?: ParamsType | (() => FullParamsType), - opt?: WithOptions - ): Promise { - const c = this.newChild(name, params, { fullParams, logger: this.logger }) - let needFinally = true - try { - const value = op(c) - if (value instanceof Promise) { - needFinally = false - return value.finally(() => { - c.end() - if (opt?.log === true) { - this.logger.logOperation(name, platformNowDiff((c as MeasureMetricsContext).st), { - ...params, - ...fullParams - }) - } - }) - } else { - if (value == null) { - return nullPromise as Promise - } - return Promise.resolve(value) - } - } finally { - if (needFinally) { - c.end() - } - } - } - - extractMeta (): Record { - return {} - } - - withSync( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T, - fullParams?: ParamsType | (() => FullParamsType) - ): T { - const c = this.newChild(name, params, { fullParams, logger: this.logger }) - try { - return op(c) - } finally { - c.end() - } - } - - error (message: string, args?: Record): void { - this.logger.error(message, { ...this.params, ...args, ...(this.logParams ?? {}) }) - } - - info (message: string, args?: Record): void { - this.logger.info(message, { ...this.params, ...args, ...(this.logParams ?? {}) }) - } - - warn (message: string, args?: Record): void { - this.logger.warn(message, { ...this.params, ...args, ...(this.logParams ?? {}) }) - } - - end (): void { - this.done() - } - - getParams (): ParamsType { - return this.params - } -} - -export class NoMetricsContext implements MeasureContext { - logger: MeasureLogger - id?: string - - contextData: object = {} - - constructor (logger?: MeasureLogger) { - this.logger = logger ?? consoleLogger({}) - } - - measure (name: string, value: number, override?: boolean): void {} - - newChild ( - name: string, - params: ParamsType, - fullParams?: FullParamsType | (() => FullParamsType), - logger?: MeasureLogger - ): MeasureContext { - const result = new NoMetricsContext(logger ?? this.logger) - result.id = this.id - result.contextData = this.contextData - return result - } - - with( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T | Promise, - fullParams?: ParamsType | (() => FullParamsType) - ): Promise { - const r = op(this.newChild(name, params, fullParams, this.logger)) - return r instanceof Promise ? r : Promise.resolve(r) - } - - extractMeta (): Record { - return {} - } - - withSync( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T, - fullParams?: ParamsType | (() => FullParamsType) - ): T { - const c = this.newChild(name, params, fullParams, this.logger) - return op(c) - } - - withLog( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T | Promise, - fullParams?: ParamsType - ): Promise { - const r = op(this.newChild(name, params, fullParams, this.logger)) - return r instanceof Promise ? r : Promise.resolve(r) - } - - error (message: string, args?: Record): void { - this.logger.error(message, { ...args }) - } - - info (message: string, args?: Record): void { - this.logger.info(message, { ...args }) - } - - warn (message: string, args?: Record): void { - this.logger.warn(message, { ...args }) - } - - end (): void {} - - getParams (): ParamsType { - return {} - } -} - -/** - * Allow to use decorator for context enabled functions - */ -export function withContext (name: string, params: ParamsType = {}): any { - return (target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor => { - const originalMethod = descriptor.value - descriptor.value = function (...args: any[]): Promise { - const ctx = args[0] as MeasureContext - return ctx.with(name, params, (ctx) => originalMethod.apply(this, [ctx, ...args.slice(1)]) as Promise) - } - return descriptor - } -} - -let operationProfiling = false - -export function setOperationLogProfiling (value: boolean): void { - operationProfiling = value -} - -let globalId: number = 0 - -export function registerOperationLog (ctx: MeasureContext): { opLogMetrics?: Metrics, op?: OperationLog } { - if (!operationProfiling) { - return {} - } - const op: OperationLog = { start: platformNow(), ops: [], end: -1 } - let opLogMetrics: Metrics | undefined - - if (ctx.id === undefined) { - ctx.id = 'op_' + (++globalId).toString(16) - } - if (ctx.metrics !== undefined) { - if (ctx.metrics.opLog === undefined) { - ctx.metrics.opLog = {} - } - ctx.metrics.opLog[ctx.id] = op - opLogMetrics = ctx.metrics - } - return { opLogMetrics, op } -} - -export function updateOperationLog (opLogMetrics: Metrics | undefined, op: OperationLog | undefined): void { - if (!operationProfiling) { - return - } - if (op !== undefined) { - op.end = platformNow() - } - // We should keep only longest one entry - if (opLogMetrics?.opLog !== undefined) { - const entries = Object.entries(opLogMetrics.opLog) - - const incomplete = entries.filter((it) => it[1].end === -1) - const complete = entries.filter((it) => it[1].end !== -1) - complete.sort((a, b) => a[1].start - b[1].start) - if (complete.length > 30) { - complete.splice(0, complete.length - 30) - } - - opLogMetrics.opLog = Object.fromEntries(incomplete.concat(complete)) - } -} - -export function addOperation ( - ctx: MeasureContext, - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => Promise, - fullParams?: FullParamsType -): Promise { - if (!operationProfiling) { - return op(ctx) - } - let opEntry: OperationLogEntry | undefined - - let p: MeasureContext | undefined = ctx - let opLogMetrics: Metrics | undefined - let id: string | undefined - - while (p !== undefined) { - if (p.metrics?.opLog !== undefined) { - opLogMetrics = p.metrics - } - if (id === undefined && p.id !== undefined) { - id = p.id - } - p = p.parent - } - const opLog = id !== undefined ? opLogMetrics?.opLog?.[id] : undefined - - if (opLog !== undefined) { - opEntry = { - op: name, - start: performance.now(), - params: {}, - end: -1 - } - } - const result = op(ctx) - if (opEntry !== undefined && opLog !== undefined) { - void result.finally(() => { - if (opEntry !== undefined && opLog !== undefined) { - opEntry.end = performance.now() - opEntry.params = { ...params, ...(typeof fullParams === 'function' ? fullParams() : fullParams) } - opLog.ops.push(opEntry) - } - }) - } - return result -} diff --git a/packages/measurements/src/index.ts b/packages/measurements/src/index.ts deleted file mode 100644 index d736098c8a3..00000000000 --- a/packages/measurements/src/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export * from './context' -export * from './metrics' -export * from './types' - -/** - * Return a current performance timestamp - */ -export const platformNow: () => number = () => performance.now() - -/** - * Return a diff with previous performance snapshot with 2 digits after . max. - */ -export const platformNowDiff = (old: number): number => Math.round((performance.now() - old) * 100) / 100 diff --git a/packages/measurements/src/metrics.ts b/packages/measurements/src/metrics.ts deleted file mode 100644 index 55b23fc318f..00000000000 --- a/packages/measurements/src/metrics.ts +++ /dev/null @@ -1,337 +0,0 @@ -// Basic performance metrics suite. - -import { platformNow, type MetricsData } from '.' -import { type FullParamsType, type Metrics, type ParamsType } from './types' - -/** - * @public - */ -export const globals: Metrics = newMetrics() - -/** - * @public - * @returns - */ -export function newMetrics (): Metrics { - return { - operations: 0, - value: 0, - measurements: {}, - params: {}, - namedParams: {} - } -} - -function getUpdatedTopResult ( - current: Metrics['topResult'], - time: number, - params: FullParamsType -): Metrics['topResult'] { - if (time === 0) { - return current - } - const result: Metrics['topResult'] = current ?? [] - - const newValue = { - value: time, - params - } - - if (result.length > 6) { - if (result[0].value < newValue.value) { - result[0] = newValue - return result - } - if (result[result.length - 1].value > newValue.value) { - result[result.length - 1] = newValue - return result - } - - // Shift the middle - return [result[0], newValue, ...result.slice(1, 3), result[5]] - } else { - result.push(newValue) - return result - } -} - -/** - * Measure with tree expansion. Operation counter will be added only to leaf's. - * @public - */ -export function measure ( - metrics: Metrics, - params: ParamsType, - fullParams: FullParamsType | (() => FullParamsType) = {}, - endOp?: (spend: number) => void -): () => void { - const st = platformNow() - return () => { - updateMeasure(metrics, st, params, fullParams, endOp) - } -} -export function updateMeasure ( - metrics: Metrics, - st: number, - params: ParamsType, - fullParams: FullParamsType | (() => FullParamsType), - endOp?: (spend: number) => void, - value?: number, - override?: boolean -): void { - const ed = platformNow() - - const fParams = typeof fullParams === 'function' ? fullParams() : fullParams - // Update params if required - const pparams = Object.entries(params) - if (pparams.length > 0) { - const [k, v] = pparams[0] - let params = metrics.params[k] - if (params === undefined) { - params = {} - metrics.params[k] = params - } - const vKey = `${v?.toString() ?? ''}` - let param = params[vKey] - if (param === undefined) { - param = { - operations: 0, - value: 0 - } - params[vKey] = param - } - if (override === true) { - param.operations = value ?? ed - st - } else { - param.value += value ?? ed - st - param.operations++ - } - // Do not update top results for params. - if (pparams.length > 1) { - // We need to update all other params as counters. - if (param.topResult === undefined) { - param.topResult = [] - } - for (const [, v] of pparams.slice(1)) { - const r = (param.topResult ?? []).find((it) => it.params[`${v}`] === true) - if (r !== undefined) { - r.value += 1 // Counter of operations - r.time = (r.time ?? 0) + (value ?? ed - st) - } else { - param.topResult.push({ params: { [`${v}`]: true }, value: 1, time: value ?? ed - st }) - } - } - param.topResult.sort((a, b) => b.value - a.value) - } - } - // Update leaf data - if (override === true) { - metrics.operations = value ?? ed - st - } else { - metrics.value += value ?? ed - st - metrics.operations++ - } - - metrics.topResult = getUpdatedTopResult(metrics.topResult, ed - st, fParams) - endOp?.(ed - st) -} - -/** - * @public - */ -export function childMetrics (root: Metrics, path: string[]): Metrics { - const segments = path - let oop = root - for (const p of segments) { - const v = oop.measurements[p] ?? { operations: 0, value: 0, measurements: {}, params: {} } - oop.measurements[p] = v - oop = v - } - return oop -} - -/** - * @public - */ -export function metricsAggregate (m: Metrics, limit: number = -1, roundMath: boolean = false): Metrics { - let ms = aggregateMetrics(m.measurements, limit) - - // Use child overage, if there is no top level value specified. - const me = Object.entries(ms) - const sumVal: number = - (me.length === 0 ? m.value : 0) + - me - .filter((it) => !it[0].startsWith('#')) - .map((it) => it[1]) - .reduce((p, v) => { - return p + v.value - }, 0) - - if (limit !== -1) { - // We need to keep only top limit items in ms - if (Object.keys(ms).length > 0) { - const newMs: typeof ms = {} - let added = 0 - for (const [k, v] of Object.entries(ms)) { - newMs[k] = v - added++ - if (added >= limit) { - break - } - } - ms = newMs - } - } - - return { - operations: m.operations, - measurements: ms, - params: m.params, - value: sumVal, - topResult: m.topResult, - namedParams: m.namedParams, - opLog: m.opLog - } -} - -function aggregateMetrics (m: Record, limit: number = -1): Record { - const result: Record = {} - for (const [k, v] of Object.entries(m).sort((a, b) => b[1].value - a[1].value)) { - result[k] = metricsAggregate(v, limit) - } - return result -} - -function toLen (val: string, sep: string, len: number): string { - while (val.length < len) { - val += sep - } - return val -} - -function printMetricsChildren (params: Record, offset: number, length: number): string { - let r = '' - if (Object.keys(params).length > 0) { - r += '\n' + toLen('', ' ', offset) - r += Object.entries(params) - .filter((it) => it[1].value > 0.1) - .map(([k, vv]) => toString(k, vv, offset, length)) - .join('\n' + toLen('', ' ', offset)) - } - return r -} - -function printMetricsParams ( - params: Record>, - offset: number, - length: number -): string { - let r = '' - const joinP = (key: string, data: Record): string[] => { - return Object.entries(data) - .filter((it) => it[1].value >= 0.1) - .map(([k, vv]) => - `${toLen('', ' ', offset)}${toLen(key + '=' + k, '-', length - offset)}: avg ${ - Math.round((vv.value / (vv.operations > 0 ? vv.operations : 1)) * 100) / 100 - } total: ${Math.round(vv.value * 100) / 100} ops: ${vv.operations}`.trim() - ) - } - const joinParams = Object.entries(params).reduce((p, c) => [...p, ...joinP(c[0], c[1])], []) - if (Object.keys(joinParams).length > 0) { - r += '\n' + toLen('', ' ', offset) - r += joinParams.join('\n' + toLen('', ' ', offset)) - } - return r -} - -function toString (name: string, m: Metrics, offset: number, length: number): string { - let r = `${toLen('', ' ', offset)}${toLen(name, '-', length - offset)}: avg ${ - Math.round((m.value / (m.operations > 0 ? m.operations : 1)) * 100) / 100 - } total: ${Math.round(m.value * 100) / 100} ops: ${m.operations}`.trim() - r += printMetricsParams(m.params, offset + 4, length) - r += printMetricsChildren(m.measurements, offset + 4, length) - return r -} - -function toJson (m: Metrics): any { - const obj: any = { - $total: m.value, - $ops: m.operations - } - if (m.operations > 1) { - obj.avg = Math.round((m.value / (m.operations > 0 ? m.operations : 1)) * 100) / 100 - } - if (Object.keys(m.params).length > 0) { - obj.params = m.params - } - for (const [k, v] of Object.entries(m.measurements ?? {})) { - obj[ - `${k} ${v.value} ${v.operations} ${ - v.operations > 1 ? Math.round((v.value / (v.operations > 0 ? m.operations : 1)) * 100) / 100 : '' - }` - ] = toJson(v) - } - - return obj -} - -/** - * @public - */ -export function metricsToString (metrics: Metrics, name = 'System', length: number): string { - return toString(name, metricsAggregate(metrics, 50, true), 0, length) -} - -export function metricsToJson (metrics: Metrics): any { - return toJson(metricsAggregate(metrics)) -} - -function printMetricsParamsRows ( - params: Record>, - offset: number -): (string | number)[][] { - const r: (string | number)[][] = [] - function joinP (key: string, data: Record): (string | number)[][] { - return Object.entries(data).map(([k, vv]) => [ - offset, - `${key}=${k}`, - Math.round((vv.value / (vv.operations > 0 ? vv.operations : 1)) * 100) / 100, - Math.round(vv.value * 100) / 100, - vv.operations - ]) - } - for (const [k, v] of Object.entries(params)) { - r.push(...joinP(k, v)) - } - return r -} - -function printMetricsChildrenRows (params: Record, offset: number): (string | number)[][] { - const r: (string | number)[][] = [] - if (Object.keys(params).length > 0) { - Object.entries(params).forEach(([k, vv]) => r.push(...toStringRows(k, vv, offset))) - } - return r -} - -function toStringRows (name: string, m: Metrics, offset: number): (number | string)[][] { - const r: (number | string)[][] = [ - [ - offset, - name, - Math.round((m.value / (m.operations > 0 ? m.operations : 1)) * 100) / 100, - Math.round(m.value * 100) / 100, - m.operations - ] - ] - r.push(...printMetricsParamsRows(m.params, offset + 1)) - r.push(...printMetricsChildrenRows(m.measurements, offset + 1)) - return r -} - -/** - * @public - */ -export function metricsToRows (metrics: Metrics, name = 'System'): (number | string)[][] { - return toStringRows(name, metricsAggregate(metrics, 50, true), 0) -} diff --git a/packages/measurements/src/types.ts b/packages/measurements/src/types.ts deleted file mode 100644 index 18db172604a..00000000000 --- a/packages/measurements/src/types.ts +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @public - */ -export type ParamType = string | number | boolean | undefined - -/** - * @public - */ -export type ParamsType = Record - -/** - * @public - */ -export type FullParamsType = Record - -/** - * @public - */ -export interface MetricsData { - operations: number - value: number - topResult?: { - value: number - time?: number - params: FullParamsType - }[] -} - -export interface OperationLogEntry { - op: string - params: ParamsType - start: number - end: number -} -export interface OperationLog { - ops: OperationLogEntry[] - start: number - end: number -} - -/** - * @public - */ -export interface Metrics extends MetricsData { - namedParams: ParamsType - params: Record> - measurements: Record - - opLog?: Record -} - -/** - * @public - */ -export interface MeasureLogger { - info: (message: string, obj?: Record) => void - error: (message: string, obj?: Record) => void - - warn: (message: string, obj?: Record) => void - - logOperation: (operation: string, time: number, params: ParamsType) => void - - childLogger?: (name: string, params: Record) => MeasureLogger - - close: () => Promise -} - -export interface WithOptions { - span?: true | false | 'disable' | 'skip' | 'inherit' // 'none' means no span will be created, 'disable' means context will be tracing disabled - log?: boolean - inheritParams?: boolean - - // Passed context metadata - meta?: Record -} - -/** - * @public - */ -export interface MeasureContext { - id?: string - - // Context data will be copied referenced for all child contexts. - contextData: Q - // Create a child metrics context - newChild: ( - name: string, - params: ParamsType, - opt?: { - fullParams?: FullParamsType - logger?: MeasureLogger - span?: WithOptions['span'] // By default true - meta?: Record - } - ) => MeasureContext - - metrics?: Metrics - - with: ( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T | Promise, - fullParams?: FullParamsType | (() => FullParamsType), - opt?: WithOptions - ) => Promise - - withSync: ( - name: string, - params: ParamsType, - op: (ctx: MeasureContext) => T, - fullParams?: FullParamsType | (() => FullParamsType), - opt?: WithOptions - ) => T - - extractMeta: () => Record - - logger: MeasureLogger - - parent?: MeasureContext - getParams: () => ParamsType - - measure: (name: string, value: number, override?: boolean) => void - - // Capture error - error: (message: string, obj?: Record) => void - info: (message: string, obj?: Record) => void - warn: (message: string, obj?: Record) => void - - // Mark current context as complete - // If no value is passed, time difference will be used. - end: (value?: number) => void -} diff --git a/packages/measurements/tsconfig.json b/packages/measurements/tsconfig.json deleted file mode 100644 index b5ae22f6e46..00000000000 --- a/packages/measurements/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json", - - "compilerOptions": { - "rootDir": "./src", - "outDir": "./lib", - "declarationDir": "./types", - "tsBuildInfoFile": ".build/build.tsbuildinfo" - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "lib", "dist", "types", "bundle"] -} \ No newline at end of file diff --git a/rush.json b/rush.json index ee83a730624..3eb8561d4aa 100644 --- a/rush.json +++ b/rush.json @@ -340,16 +340,6 @@ "projectFolder": "packages/platform", "shouldPublish": true }, - { - "packageName": "@hcengineering/measurements", - "projectFolder": "packages/measurements", - "shouldPublish": true - }, - { - "packageName": "@hcengineering/measurements-otlp", - "projectFolder": "packages/measurements-otlp", - "shouldPublish": true - }, { "packageName": "@hcengineering/core", "projectFolder": "packages/core",