mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-12 12:47:45 +02:00
qfix: Use measurements from published packages (#9984)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
Generated
+55
-141
@@ -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: {}
|
||||
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export * from './telemetry'
|
||||
@@ -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<string, { counter: Gauge, value: 0 }>()
|
||||
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<string, string | number | boolean>
|
||||
}
|
||||
): 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<string, string | number | boolean> {
|
||||
const headers: Record<string, string> = {}
|
||||
if (this.context !== undefined) {
|
||||
propagation.inject(this.context, headers)
|
||||
}
|
||||
return headers
|
||||
}
|
||||
|
||||
with<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext) => T | Promise<T>,
|
||||
fullParams?: ParamsType | (() => FullParamsType),
|
||||
opt?: WithOptions
|
||||
): Promise<T> {
|
||||
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<T>
|
||||
}
|
||||
return Promise.resolve(value)
|
||||
}
|
||||
} finally {
|
||||
if (needFinally) {
|
||||
c.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
withSync<T>(
|
||||
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<string, any>): 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<string, any>): 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<string, any>): 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<string, string>
|
||||
*
|
||||
* W3C baggage format: "key1=value1,key2=value2;property=value,key3=value3"
|
||||
* Returns only the key-value pairs, ignoring properties
|
||||
*/
|
||||
function parseBaggage (baggageHeader?: string): Record<string, string> {
|
||||
if (baggageHeader == null || typeof baggageHeader !== 'string') {
|
||||
return {}
|
||||
}
|
||||
|
||||
const result: Record<string, string> = {}
|
||||
|
||||
// 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<string, string> {
|
||||
const headers: Record<string, string> = 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<string, string> {
|
||||
const headers: Record<string, string> = 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<string, string> {
|
||||
const headers: Record<string, string> = 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
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<string, any>): 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<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext) => T | Promise<T>,
|
||||
fullParams?: ParamsType | (() => FullParamsType),
|
||||
opt?: WithOptions
|
||||
): Promise<T> {
|
||||
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<T>
|
||||
}
|
||||
return Promise.resolve(value)
|
||||
}
|
||||
} finally {
|
||||
if (needFinally) {
|
||||
c.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extractMeta (): Record<string, string | number | boolean> {
|
||||
return {}
|
||||
}
|
||||
|
||||
withSync<T>(
|
||||
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<string, any>): void {
|
||||
this.logger.error(message, { ...this.params, ...args, ...(this.logParams ?? {}) })
|
||||
}
|
||||
|
||||
info (message: string, args?: Record<string, any>): void {
|
||||
this.logger.info(message, { ...this.params, ...args, ...(this.logParams ?? {}) })
|
||||
}
|
||||
|
||||
warn (message: string, args?: Record<string, any>): 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<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext) => T | Promise<T>,
|
||||
fullParams?: ParamsType | (() => FullParamsType)
|
||||
): Promise<T> {
|
||||
const r = op(this.newChild(name, params, fullParams, this.logger))
|
||||
return r instanceof Promise ? r : Promise.resolve(r)
|
||||
}
|
||||
|
||||
extractMeta (): Record<string, string | number | boolean> {
|
||||
return {}
|
||||
}
|
||||
|
||||
withSync<T>(
|
||||
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<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext) => T | Promise<T>,
|
||||
fullParams?: ParamsType
|
||||
): Promise<T> {
|
||||
const r = op(this.newChild(name, params, fullParams, this.logger))
|
||||
return r instanceof Promise ? r : Promise.resolve(r)
|
||||
}
|
||||
|
||||
error (message: string, args?: Record<string, any>): void {
|
||||
this.logger.error(message, { ...args })
|
||||
}
|
||||
|
||||
info (message: string, args?: Record<string, any>): void {
|
||||
this.logger.info(message, { ...args })
|
||||
}
|
||||
|
||||
warn (message: string, args?: Record<string, any>): 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<any> {
|
||||
const ctx = args[0] as MeasureContext
|
||||
return ctx.with(name, params, (ctx) => originalMethod.apply(this, [ctx, ...args.slice(1)]) as Promise<any>)
|
||||
}
|
||||
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<T> (
|
||||
ctx: MeasureContext,
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext) => Promise<T>,
|
||||
fullParams?: FullParamsType
|
||||
): Promise<T> {
|
||||
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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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<string, Metrics>, limit: number = -1): Record<string, Metrics> {
|
||||
const result: Record<string, Metrics> = {}
|
||||
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<string, Metrics>, 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<string, Record<string, MetricsData>>,
|
||||
offset: number,
|
||||
length: number
|
||||
): string {
|
||||
let r = ''
|
||||
const joinP = (key: string, data: Record<string, MetricsData>): 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<string[]>((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<string, Record<string, MetricsData>>,
|
||||
offset: number
|
||||
): (string | number)[][] {
|
||||
const r: (string | number)[][] = []
|
||||
function joinP (key: string, data: Record<string, MetricsData>): (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<string, Metrics>, 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)
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type ParamType = string | number | boolean | undefined
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type ParamsType = Record<string, ParamType>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type FullParamsType = Record<string, any>
|
||||
|
||||
/**
|
||||
* @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<string, Record<string, MetricsData>>
|
||||
measurements: Record<string, Metrics>
|
||||
|
||||
opLog?: Record<string, OperationLog>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface MeasureLogger {
|
||||
info: (message: string, obj?: Record<string, any>) => void
|
||||
error: (message: string, obj?: Record<string, any>) => void
|
||||
|
||||
warn: (message: string, obj?: Record<string, any>) => void
|
||||
|
||||
logOperation: (operation: string, time: number, params: ParamsType) => void
|
||||
|
||||
childLogger?: (name: string, params: Record<string, any>) => MeasureLogger
|
||||
|
||||
close: () => Promise<void>
|
||||
}
|
||||
|
||||
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<string, string | number | boolean>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface MeasureContext<Q = any> {
|
||||
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<string, string | number | boolean>
|
||||
}
|
||||
) => MeasureContext
|
||||
|
||||
metrics?: Metrics
|
||||
|
||||
with: <T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext<Q>) => T | Promise<T>,
|
||||
fullParams?: FullParamsType | (() => FullParamsType),
|
||||
opt?: WithOptions
|
||||
) => Promise<T>
|
||||
|
||||
withSync: <T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext<Q>) => T,
|
||||
fullParams?: FullParamsType | (() => FullParamsType),
|
||||
opt?: WithOptions
|
||||
) => T
|
||||
|
||||
extractMeta: () => Record<string, string | number | boolean>
|
||||
|
||||
logger: MeasureLogger
|
||||
|
||||
parent?: MeasureContext
|
||||
getParams: () => ParamsType
|
||||
|
||||
measure: (name: string, value: number, override?: boolean) => void
|
||||
|
||||
// Capture error
|
||||
error: (message: string, obj?: Record<string, any>) => void
|
||||
info: (message: string, obj?: Record<string, any>) => void
|
||||
warn: (message: string, obj?: Record<string, any>) => void
|
||||
|
||||
// Mark current context as complete
|
||||
// If no value is passed, time difference will be used.
|
||||
end: (value?: number) => void
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user