{"_id":"custom-metrics","_rev":"16-e55e732f72af4b2d889ee8d837c6934e","name":"custom-metrics","dist-tags":{"latest":"1.1.0"},"versions":{"0.7.0":{"name":"custom-metrics","version":"0.7.0","keywords":["metrics","serverless","log","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.7.0","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/metrics","bugs":{"url":"http://github.com/sensedeep/metrics/issues"},"dist":{"shasum":"cf2dde76eaea854eee00ed3edd01d6cb99d455a6","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.7.0.tgz","fileCount":12,"integrity":"sha512-YWpe3j2Dq5m5yx3uFodTu7iAsUUTq+xtaTULFiDvOZ8FuV3BxqhttBexRyaKgA43gmszv2E15kccW5QFm/aO6w==","signatures":[{"sig":"MEQCIEkm44LhVSjN5itX0Idh82OxtWJmUecbIYcbsx6n2TtcAiBjC8pC9fh5UKLzKGlKWI5Xs7urBo1BfR3vVFOGXBBxnA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":93386},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"1445516773a7569f5997e2201ef90cad78e7fee4","scripts":{"test":"jest","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Low cost custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"dynamodb-onetable":"^2.6.3","@aws-sdk/util-dynamodb":"^3.391.0","@aws-sdk/client-dynamodb":"^3.391.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.2","ts-jest":"^29.1.1","senselogs":"^1.0.5","wait-port":"^1.0.4","typescript":"^5.1.6","@types/jest":"^29.5.3","@types/node":"^20.5.0","dynamo-db-local":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.7.0_1692328970403_0.05657065764686009","host":"s3://npm-registry-packages"}},"0.7.1":{"name":"custom-metrics","version":"0.7.1","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.7.1","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"97fd70b4b77b8fdf8b3fa41ba129afaad309ea0d","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.7.1.tgz","fileCount":13,"integrity":"sha512-7Z1ORAFl7rSm48Lg3K2tVHEseCoonHUcImdlNN8E4Jf1M6N7pQdj/w7Y3EL6s9zWtB1OuE2sgT+QPj1V0aR7Zw==","signatures":[{"sig":"MEYCIQCbHPdEWGt5U2SpF5JifLqMsUqTqhg/nn7/IZwqjFqB9AIhAK9jJyheWUj52uPE2VSdPDL+KPDcyXyMNYBMp0BgQsYV","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":94455},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"0d68ee6c4cfca8249befda4913c206a07587e1d7","scripts":{"test":"jest","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Low cost custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"dynamodb-onetable":"^2.6.4","@aws-sdk/util-dynamodb":"^3.391.0","@aws-sdk/client-dynamodb":"^3.391.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.2","ts-jest":"^29.1.1","senselogs":"^1.0.5","wait-port":"^1.0.4","typescript":"^5.1.6","@types/jest":"^29.5.3","@types/node":"^20.5.0","dynamo-db-local":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.7.1_1692330709042_0.22792397188336921","host":"s3://npm-registry-packages"}},"0.7.2":{"name":"custom-metrics","version":"0.7.2","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.7.2","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"6a644c21c764eff4000ad2005fc382c6b04a0e8c","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.7.2.tgz","fileCount":13,"integrity":"sha512-lYfDDs/2EjiD5gETiUux+7apoZ8NkwaMWpX8L2vjacccsMXoQsV4mHCBYSCG0s2zkcgIicXdBWkKImTWW9SNeA==","signatures":[{"sig":"MEUCIQCbwmKi7/Gbg21Jv9rC87d+KSbEWplUpYPJVJXF6PCSIgIgMwLtxxTdoXH/qVAAFzjoCJu8fYwTKXjiUbs9WOm/kw8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":93125},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"779b52bad16cbcec8a0e6839b1bc5bc384af616a","scripts":{"test":"jest","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Low cost custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"dynamodb-onetable":"^2.6.4","@aws-sdk/util-dynamodb":"^3.395.0","@aws-sdk/client-dynamodb":"^3.395.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.2","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.0.4","typescript":"^5.1.6","@types/jest":"^29.5.3","@types/node":"^20.5.1","dynamo-db-local":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.7.2_1692517933184_0.7733585592664369","host":"s3://npm-registry-packages"}},"0.7.3":{"name":"custom-metrics","version":"0.7.3","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.7.3","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"50c22dc29a66187d4a505ae12cc45c2095f750c8","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.7.3.tgz","fileCount":13,"integrity":"sha512-qQPvolY3pCm4BMNCiUv5McG6+s04oKt5Wrpu9ph7OlmvREKAglbOimIVvf7EoB1Fjp2Gg82pMc5oRd4/mYGNeg==","signatures":[{"sig":"MEQCIGAa/9KbyztHLOjbDdgh9PDnCPNXAbZDYebgkmL+6pvXAiBLBx4WdT5Hop7i9hsXHV6RuEbHOxm9dvig0J4OMgHdAA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":93126},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"f31a86115e06abc583f3efe00ffaf637a4324f26","scripts":{"test":"jest","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Low cost custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"dynamodb-onetable":"^2.6.4","@aws-sdk/util-dynamodb":"^3.395.0","@aws-sdk/client-dynamodb":"^3.395.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.2","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.0.4","typescript":"^5.1.6","@types/jest":"^29.5.3","@types/node":"^20.5.1","dynamo-db-local":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.7.3_1692523690893_0.6261061188352302","host":"s3://npm-registry-packages"}},"0.7.4":{"name":"custom-metrics","version":"0.7.4","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.7.4","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"c5e135ad8c48158c63e33cd87b4cb85a8ce7b398","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.7.4.tgz","fileCount":9,"integrity":"sha512-DqoLXdR2jpSK52YFYGV+YsUHTn9On/4CqQ1bbs6e+rwnbHyKVPJnu4y1FCU5Dcin6SNXG7Ov8BXcnfFnsbjSeA==","signatures":[{"sig":"MEUCIQCA/0lAwfSti6287kLifxZP8waGNUJf8ELFVcGLyqFyTwIgRoKXDjF798nYBkTmWmojJRnP7X7mkZEr5wziV/hquIs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":93817},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"2d1ffd254e33d6569e4ba87ec7631d5d32d9f82d","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Low cost custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.395.0","@aws-sdk/client-dynamodb":"^3.395.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.2","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.0.4","typescript":"^5.1.6","@types/jest":"^29.5.3","@types/node":"^20.5.1","dynamo-db-local":"^6.0.0"},"peerDependencies":{"dynamodb-onetable":"^2.6.4"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.7.4_1693365879731_0.20918337895730055","host":"s3://npm-registry-packages"}},"0.7.5":{"name":"custom-metrics","version":"0.7.5","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.7.5","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"84bf8038daafb8dd57d275a987d1b7edc01f40fe","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.7.5.tgz","fileCount":9,"integrity":"sha512-FLxuNri/Xzho5MmnUcYsPmKLAXX7PP95av3gUHV1PgjdayHNvUVYyCC3etvHrYTFHXn5Ky39GouO1hGoCiILJw==","signatures":[{"sig":"MEUCIEDpjHPCtERob0CxMBwpNPHKuKGbW6MItPtAYQK9kbisAiEA16MA+wWQVSWC/QldkJRs+iOd/dsOxa6Jt/Kc/tkYctg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":96428},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"2aada37c3652096d92ac7530c40a4ebcfde74449","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Low cost custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.398.0","@aws-sdk/client-dynamodb":"^3.398.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.4","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.0.4","typescript":"^5.2.2","@types/jest":"^29.5.4","@types/node":"^20.5.7","dynamo-db-local":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.7.5_1693621629030_0.4272073059939967","host":"s3://npm-registry-packages"}},"0.7.6":{"name":"custom-metrics","version":"0.7.6","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.7.6","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"21ee38cc26aa7efc66e13e0f38c5e6edf4d47361","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.7.6.tgz","fileCount":9,"integrity":"sha512-BbRejoyDP8Hwd8q5ZqcpDrmKn6zmOUjDh9RxGHXJFG/HzdDPVwam0anpsU418Jfp/Bo+pm+FKNY8advDcyi6Qw==","signatures":[{"sig":"MEYCIQDg9++sw8E9aM9fqJLSQ0f1V/9FWRXUVOjlDO/4ZPi6twIhANLWmXM1g483/Xpo7SLU8PH2d8CJQp1ro1w0vxGNwv7S","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":95929},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"552c8390fe9912e4d3996b477060d925cbcc2539","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.405.0","@aws-sdk/client-dynamodb":"^3.405.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.4","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.0.4","typescript":"^5.2.2","@types/jest":"^29.5.4","@types/node":"^20.5.8","dynamo-db-local":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.7.6_1693628680238_0.45102605058635037","host":"s3://npm-registry-packages"}},"0.8.0":{"name":"custom-metrics","version":"0.8.0","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.8.0","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"40853c7e031c1481868f4a15513754cefa168911","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.8.0.tgz","fileCount":9,"integrity":"sha512-Xs/YZ7j+MC+XZQ0+x8y8cUUtZfmfKMVq7SUHUjyCpUohARpiJaVRmGrrZmFoCU/rYc9khCocMyvIua1zfRIJNg==","signatures":[{"sig":"MEUCIQDPVDsdKfDva9zHVfklunlIXZYO163ozqslsloLYLq6nAIgWp3Qmcb87ZufKFYiJa2cIH9ntoUpGcNDGi9puGmRv/0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":96158},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"21ca7d1e6d81525fb15db5e7f0ddfb0271996acf","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.405.0","@aws-sdk/client-dynamodb":"^3.405.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.4","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.0.4","typescript":"^5.2.2","@types/jest":"^29.5.4","@types/node":"^20.5.8","dynamo-db-local":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.8.0_1693908465491_0.7183290212191316","host":"s3://npm-registry-packages"}},"0.8.1":{"name":"custom-metrics","version":"0.8.1","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.8.1","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"473424c98c41b25a01d2d65c61b1459f273ba445","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.8.1.tgz","fileCount":9,"integrity":"sha512-4a7P2pMvW8K7rgFPGGcnkSa/JGzT1q9/rdpJkrFR/CGGMjbGMR1dX/6QqOYUqwtjvQb3TOaVG5pLqw2RpGKf3A==","signatures":[{"sig":"MEQCIFjluEWezM9h7gxquYqro2hd+Xck8w4XAjmmDzE3rG54AiBt23ckbdMEVmw5bu9adyPWofcjawK+1gPnjC9ZYXHKiQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":97396},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"f4be9d52291d04a946e755a5d191b822c5553173","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.405.0","@aws-sdk/client-dynamodb":"^3.405.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.4","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.0.4","typescript":"^5.2.2","@types/jest":"^29.5.4","@types/node":"^20.5.8","dynamo-db-local":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.8.1_1694586410550_0.32225263041589414","host":"s3://npm-registry-packages"}},"0.8.2":{"name":"custom-metrics","version":"0.8.2","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@0.8.2","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"d1a7edaa7e5f651a443d0cb1db1548d70a5213ea","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-0.8.2.tgz","fileCount":9,"integrity":"sha512-pT+AmdYC8Y5Hx9qkqklN9ywA9qs0WiA0TyIZxYa6qLkX63XbXByTsWvxGCo4zkDAeTA8NQwLWRojjOvk/xZ6QA==","signatures":[{"sig":"MEQCICi9EKPhxoZyGJ8pgs+dqWTL4p+WNSwM5HTlea38GztfAiBASyhnAzp1lAfSduZmYdCnwlgFD/pZ/nmwt2taDBdg9g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":99897},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"eca7c699e04fe861927cb83957bf88d1d3c80b51","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"8.15.0","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"16.17.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.418.0","@aws-sdk/client-dynamodb":"^3.418.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.1.0","typescript":"^5.2.2","@types/jest":"^29.5.5","@types/node":"^20.6.4","dynamo-db-local":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_0.8.2_1699088434963_0.7534570001048655","host":"s3://npm-registry-packages"}},"1.0.0":{"name":"custom-metrics","version":"1.0.0","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@1.0.0","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"9f6619e87263b9dfb3ce0dd6550fae51962ab2b1","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-1.0.0.tgz","fileCount":9,"integrity":"sha512-kah+xUceIE2q/slPmrExGVN7gYMhzVLBHBhoAg57gnmdRQwTvADMvQ/V83EmonswmIk/0TV73dWCeWeKkDH3ow==","signatures":[{"sig":"MEQCIC9IyEF4pW6FFe0xzXkGQzFG4xQB5TEKTrAqjQ5BfsB0AiAHSrGVct/JxeFSpCZpUq24WhnIu1IK6GLrz76Xw58lkw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":99938},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"b45cd588cdb6b023a4ffab1f4e93493c44d3ed1a","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"10.2.4","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"20.11.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.418.0","@aws-sdk/client-dynamodb":"^3.418.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.1","senselogs":"^1.0.6","wait-port":"^1.1.0","typescript":"^5.2.2","@types/jest":"^29.5.5","@types/node":"^20.6.4","dynamo-db-local":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_1.0.0_1715299320120_0.7518034141977288","host":"s3://npm-registry-packages"}},"1.0.1":{"name":"custom-metrics","version":"1.0.1","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@1.0.1","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"4cd39cf44478e5717df775ec33ee03983056a21d","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-1.0.1.tgz","fileCount":9,"integrity":"sha512-ZF4rDm25Hp0JGcCiNRtEPmrlIO+qfUnVIQLB1LtOa2ZQI5lJWckM/8YxqlrkadXTqU/KIMCqo+khFK0Kp6dvjA==","signatures":[{"sig":"MEUCIQCq3EimNKLfknRh3Zn8v/1xPXwDzxF1tBdGdDHkTUkYFQIgZLuzPtEj2V7ar879Wvk4QO2Wj8iOxlzcQFOs0QPzfHE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":102459},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"f5ac357062581461808cb7f57ee2ba094a9cb768","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"10.2.4","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"20.11.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.598.0","@aws-sdk/client-dynamodb":"^3.598.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.5","senselogs":"^1.0.6","wait-port":"^1.1.0","typescript":"^5.4.5","@types/jest":"^29.5.12","@types/node":"^20.14.2","dynamo-db-local":"^9.1.1"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_1.0.1_1718573438132_0.07560102882179365","host":"s3://npm-registry-packages"}},"1.0.3":{"name":"custom-metrics","version":"1.0.3","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@1.0.3","homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"4828a46e07860097679dd8d15b26c9394ea8c34d","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-1.0.3.tgz","fileCount":9,"integrity":"sha512-xguNYSVfzfkTeQdKvBwY6+UskG+BQFwP5uAelnAt4AAoMJbAsUj8W1WtDKzI5UPQFm9VzAU1fHFtS7rSDYrlCQ==","signatures":[{"sig":"MEQCIHVEetadDD23SFedGmDuHoAFcogFyzn4SsqbQg/ehZ5cAiBNoOPX26m3sY/+GuuggJpmGen3Asmp8YTqz7OuB35Idg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":103138},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"76dc5cac662435428c8a442bd9eaa37281633139","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"10.2.4","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"20.11.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.606.0","@aws-sdk/client-dynamodb":"^3.606.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.5","senselogs":"^1.0.7","wait-port":"^1.1.0","typescript":"^5.5.2","@types/jest":"^29.5.12","@types/node":"^20.14.9","dynamo-db-local":"^9.1.1"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_1.0.3_1719636619302_0.48819086081291574","host":"s3://npm-registry-packages"}},"1.0.4":{"name":"custom-metrics","version":"1.0.4","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@1.0.4","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"98e132fa8e6a835b9d526761c4cfb52437d67839","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-1.0.4.tgz","fileCount":9,"integrity":"sha512-iWIdpxGHcaaZtnnNKlmlH0Bj4AqbKzEJb1+fwtCBw3o8hfscRY3GGNymn3DRU9mlb6TTUrbAr6GMA5At9V+i/g==","signatures":[{"sig":"MEUCIGvIOICa46UnPCnmL7FqsBrCo/YTIvBB0I77HoeGCQfbAiEAgiCi7hVVcBdhYsqYgRGStn6xcLe56FX9NAPLigXgo8M=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":103140},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"1a8dd197c6a22e6055c868648f97c37d260a68bd","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"10.2.4","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"20.11.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.609.0","@aws-sdk/client-dynamodb":"^3.609.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.1.5","senselogs":"^1.0.7","wait-port":"^1.1.0","typescript":"^5.5.3","@types/jest":"^29.5.12","@types/node":"^20.14.9","dynamo-db-local":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_1.0.4_1720309832313_0.5010521630860156","host":"s3://npm-registry-packages"}},"1.0.5":{"name":"custom-metrics","version":"1.0.5","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"author":{"name":"Michael O'Brien","email":"mob@sensedeep.com"},"license":"MIT","_id":"custom-metrics@1.0.5","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"homepage":"https://github.com/sensedeep/custom-metrics","bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"dist":{"shasum":"a0201005afec40c01fc4bc57347787337e823c94","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-1.0.5.tgz","fileCount":9,"integrity":"sha512-5LOTCd5nCE95HQS3rSHm9yAcnLGdjlbWpvFafdAd9oAnTeVkfQcN8rZgizSZJD9z+5LF5VYt6moeuvbyHQshIQ==","signatures":[{"sig":"MEQCIFLu3QJsvJslUGRJ8VaKwh/5QK7gqAgiBKMHoN1PXWQ2AiB8IFw+x8fkk5g4WHeNz+wZAeE9XQD4Hyqi08iRI8LNKQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":109950},"main":"dist/cjs/index.js","types":"dist/mjs/index.d.ts","module":"dist/mjs/index.js","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"gitHead":"e2ed6556c273da40e1377e031d980bb1ab1a7c43","scripts":{"test":"jest --runInBand","build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test-cov":"jest --coverage"},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"repository":{"url":"git+https://github.com/sensedeep/custom-metrics.git","type":"git"},"_npmVersion":"10.2.4","description":"Custom metrics for AWS","directories":{},"_nodeVersion":"20.11.1","dependencies":{"@aws-sdk/util-dynamodb":"^3.705.0","@aws-sdk/client-dynamodb":"^3.705.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","ts-jest":"^29.2.5","senselogs":"^1.0.7","wait-port":"^1.1.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.1","dynamo-db-local":"^9.3.0"},"_npmOperationalInternal":{"tmp":"tmp/custom-metrics_1.0.5_1733699640094_0.24709885846158852","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"custom-metrics","version":"1.1.0","description":"Custom metrics for AWS","main":"dist/cjs/index.js","module":"dist/mjs/index.js","types":"dist/mjs/index.d.ts","exports":{".":{"import":"./dist/mjs/index.js","require":"./dist/cjs/index.js"}},"keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"repository":{"type":"git","url":"git+https://github.com/sensedeep/custom-metrics.git"},"bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"homepage":"https://github.com/sensedeep/custom-metrics","license":"MIT","scripts":{"build":"rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup","test":"jest --runInBand","test-cov":"jest --runInBand --coverage"},"dependencies":{"@aws-sdk/client-dynamodb":"^3.879.0","@aws-sdk/util-dynamodb":"^3.879.0"},"devDependencies":{"@types/jest":"^30.0.0","@types/node":"^24.3.0","dynamo-db-local":"^10.0.0","jest":"^30.1.3","senselogs":"^1.0.7","ts-jest":"^29.4.1","typescript":"^5.9.2","wait-port":"^1.1.0"},"_id":"custom-metrics@1.1.0","gitHead":"68f4b783b60ef4859436a0d56cff65b590f10833","_nodeVersion":"24.5.0","_npmVersion":"11.5.1","dist":{"integrity":"sha512-DUflupebUOtqd8xAhL8blq7PrXdLGoU9h2bE43Dcxob9oNrEn05NwMNZQUwwERuIQD2WCjGj0zyZAbv+RIMVQg==","shasum":"b8f4e3b96e5f4584a161118d33924bb7e09a2fca","tarball":"https://registry.npmjs.org/custom-metrics/-/custom-metrics-1.1.0.tgz","fileCount":9,"unpackedSize":123178,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDoxRadevRf0tYscMgIu5aYecWAQ2bO7xScaypFugKGvAIhAIXn749hGhelPIvxiBGqD/mQoTO1N1UW65xyFTkwSvaK"}]},"_npmUser":{"name":"sensedeep","email":"mob@sensedeep.com"},"directories":{},"maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/custom-metrics_1.1.0_1757037944059_0.11099500924548034"},"_hasShrinkwrap":false}},"time":{"created":"2023-08-18T03:22:50.401Z","modified":"2025-09-05T02:05:44.493Z","0.7.0":"2023-08-18T03:22:50.670Z","0.7.1":"2023-08-18T03:51:49.256Z","0.7.2":"2023-08-20T07:52:13.405Z","0.7.3":"2023-08-20T09:28:11.034Z","0.7.4":"2023-08-30T03:24:39.954Z","0.7.5":"2023-09-02T02:27:09.217Z","0.7.6":"2023-09-02T04:24:40.442Z","0.8.0":"2023-09-05T10:07:45.682Z","0.8.1":"2023-09-13T06:26:50.700Z","0.8.2":"2023-11-04T09:00:35.233Z","1.0.0":"2024-05-10T00:02:00.306Z","1.0.1":"2024-06-16T21:30:38.322Z","1.0.3":"2024-06-29T04:50:19.480Z","1.0.4":"2024-07-06T23:50:32.474Z","1.0.5":"2024-12-08T23:14:00.289Z","1.1.0":"2025-09-05T02:05:44.265Z"},"bugs":{"url":"http://github.com/sensedeep/custom-metrics/issues"},"license":"MIT","homepage":"https://github.com/sensedeep/custom-metrics","keywords":["custom-metrics","metrics","serverless","observability","typescript","aws","amazon"],"repository":{"type":"git","url":"git+https://github.com/sensedeep/custom-metrics.git"},"description":"Custom metrics for AWS","maintainers":[{"name":"sensedeep","email":"mob@sensedeep.com"}],"readme":"# CustomMetrics\n\n![CustomMetrics](https://www.sensedeep.com/images/metrics.png)\n\n## Low cost, fast, simple, scalable metrics for AWS\n\n<!--\n[![Build Status](https://img.shields.io/github/actions/workflow/status/sensedeep/custom-metrics/build.yml?branch=main)](https://img.shields.io/github/actions/workflow/status/sensedeep/custom-metrics/build.yml?branch=main)\n[![npm](https://img.shields.io/npm/v/custom-metrics.svg)](https://www.npmjs.com/package/custom-metrics)\n[![npm](https://img.shields.io/npm/l/custom-metrics.svg)](https://www.npmjs.com/package/custom-metrics)\n[![Coverage Status](https://coveralls.io/repos/github/sensedeep/custom-metrics/badge.svg?branch=main)](https://coveralls.io/github/sensedeep/custom-metrics?branch=main)\n-->\n\nCustomMetrics is a NodeJS library to emit and query custom metrics for AWS apps. \n\nIt provides more efficient, scalable metrics that are dramatically less expensive and faster than standard AWS CloudWatch metrics. \n\n## Background\n\nAWS CloudWatch offers metrics to monitor AWS services and your apps. Unfortunately, custom AWS CloudWatch metrics can be very expensive. If updated or queried regularly, each each custom AWS CloudWatch metric may cost up to $3.60 per metric per year with additional costs for querying. If you have many metrics or high dimensionality on your metrics, this can lead to a very large CloudWatch Metrics bill. This high cost prevents using metrics liberally in your app at scale.\n\n**CustomMetrics** provides lower cost metrics that are dramatically less expensive and faster than standard AWS CloudWatch metrics.  \n \n> CustomMetrics is up to 1000x times less expensive per metric than CloudWatch. \n\nCustomMetrics achieves these savings by supporting **latest** period metrics. i.e. last day, last month, last hour, last 5 minutes etc. This enables each metric to be saved in a single DynamoDB item, and can be stored and queried fast, with minimal cost.\n\nCustomMetrics stores metrics to a DynamoDB table of your choosing that can coexist with existing application data.\n\n![Dashboard](./doc/dashboard.avif)\n\n## CustomMetrics Features\n\n-   Simple one line API to emit metrics from any NodeJS TypeScript or JavaScript app.\n-   Similar metric model to AWS CloudWatch metrics supporting namespaces, metrics, dimensions, statistics and intervals.\n-   Computes statistics for: average, min, max, count and sum.\n-   Computes P value statistics with configurable P value resolution.\n-   Supports default metric intervals of: last 5 mins, hour, day, week, month and year.\n-   Supports querying from arbitrary start dates for most recent period.\n-   Configurable custom intervals for higher or different metric intervals.\n-   Fast and flexible metric query API.\n-   Query API can return data points or aggregate metric data to a single statistic.\n-   Scalable and supports many simultaneous clients emitting metrics.\n-   Stores data in any existing DynamoDB table and coexists with existing app data.\n-   Supports multiple services, apps, namespaces and metrics in a single DynamoDB table.\n-   Extremely fast initialization time.\n-   Written in TypeScript with full TypeScript support.\n-   Clean, readable, small, TypeScript code base (~1.4K lines).\n-   No external dependencies.\n-   [DynamoDB Onetable](https://www.npmjs.com/package/dynamodb-onetable) uses CustomMetrics for detailed single table metrics. [EmbedThis Ioto](https://www.embedthis.com/) uses CustomMetrics for IoT metrics.\n\n![Custom Metrics](./doc/dashboard-dark.avif)\n\n## Quick Tour\n\nInstall the library using npm:\n\n    npm i custom-metrics\n\nImport the CustomMetrics library. If you are not using ES modules or TypeScript, use `require` to import the library.\n\n```javascript\nimport {CustomMetrics} from 'CustomMetrics'\n```\n\nNext create and configure the CustomMetrics instance by nominating the DynamoDB table and key structure to hold your metrics. \n\n```javascript\nconst metrics = new CustomMetrics({\n    table: 'MyTable',\n    region: 'us-east-1',\n    primaryKey: 'pk',\n    sortKey: 'sk',\n})\n```\n\nMetrics are stored in the DynamoDB database referenced by the **table** name in the desired region. This table can be your existing application DynamoDB table and metrics can safely coexist with your data.\n\nThe **primaryKey** and **sortKey** are the primary and sort keys for the main table index. These default to 'pk' and 'sk' respectively. CustomMetrics does not support tables without a sort key.\n\nIf you have an existing AWS SDK V3 DynamoDB client instance, you can use that with the CustomMetrics constructor. This will have slightly faster initialization time than simply providing the table name.\n\n```javascript\nimport {DynamoDBClient} from '@aws-sdk/client-dynamodb'\nconst dynamoDbClient = new DynamoDBClient()\n```\n\n```javascript\nconst metrics = new CustomMetrics({\n    client: myDynamoDbClient,\n    table: 'MyTable',\n    region: 'us-east-1',\n    primaryKey: 'pk',\n    sortKey: 'sk',\n})\n```\n\n## Emitting Metric Data\n\nYou can emit metrics via the `emit` API:\n\n```javascript\nawait metrics.emit('Acme/Metrics', 'launches', 10)\n```\n\nThis will emit the `launches` metric in the `Acme/Metrics` namespace with the value of **10**. \n\nA metric can have dimensions that are unique metric values for specific instances. For example, we may want to count the number of launches for a specific rocket.\n\n```javascript\nawait metrics.emit('Acme/Metrics', 'launches', 10, [\n    {rocket: 'saturnV'}\n])\n```\n\nThe metric will be emitted for each dimension provided. A dimension may have one or more properties. A metric can also be emitted for multiple dimensions. \n\nIf you want to emit a metric over all dimensions, you can add {}. For example:\n\n```javascript\nawait metrics.emit('Acme/Metrics', 'launches', 10, [\n    {}, \n    {rocket: 'saturnV'}\n])\nawait metrics.emit('Acme/Metrics', 'launches', 10, [\n    {}, \n    {rocket: 'falcon9'}\n])\n```\n\nThis will emit a metric that is a total of all launches for all rocket types.\n\n## Query Metrics\n\nTo query a metric, use the `query` method:\n\n```javascript\nlet results = await metrics.query('Acme/Metrics', 'speed', {\n    rocket: 'saturnV'\n}, 86400, 'max')\n```\n\nThis will retrieve the `speed` metric from the `Acme/Metrics` namespace for the `{rocket == 'saturnV'}` dimension. The data points returned will be the maximum speed measured over the day's launches (86400 seconds). Intervals that have no data will have points set to {count: 0, value: 0, timestamp}. Use {} for the all-dimensions value.\n\nThis will return data like this:\n\n```json\n{\n    \"namespace\": \"Acme/Metrics\",\n    \"metric\": \"launches\",\n    \"dimensions\": {\"rocket\": \"saturnV\"},\n    \"period\": 300,\n    \"points\": [{\n        \"period\": 3600,\n        \"samples\": 10,\n        \"points\": [\n            { \"value\": 24000, \"count\": 19, \"timestamp\": 1715298000 },\n            ...\n        ]\n    }]\n}\n```\n\nIf you want to query the results as a single value over the entire period (instead of as a set of data points), set the `accumulate` options to true.\n\n```javascript\nlet results = await metrics.query('Acme/Metrics', 'speed', {\n    rocket: 'saturnV'\n}, 86400, 'max', {accumulate: true})\n```\n\nThis will return a single maximum speed over the last day.\n\nThe following will do the same but from a specific start date.\n\n```javascript\nlet results = await metrics.query('Acme/Metrics', 'speed', {\n    rocket: 'saturnV'\n}, 28 * 86400, 'max', {accumulate: true, start: new Date(2000, 0, 1).getTime()})\n```\n\nTo query multiple metrics, use the `queryMetrics` method. This will query all dimensions for a metric and \nreturn a list of metric results for all dimensions. Note: this will not flush buffered metric values before computing the results.\n\n```javascript\nlet results = await metrics.queryMetrics('Acme/Metrics', 'speed', 86400, 'avg')\n```\n\n\nTo obtain a list of metrics, use the `getMetricList` method:\n\n```typescript\nlet list: MetricList = await metrics.getMetricList()\n```\n\nThis will return an array of available namespaces in **list.namespaces**.\n\nTo get a list of the metrics available for a given namespace, pass the namespace as the first argument.\n\n```typescript\nlet list: MetricList = await metrics.getMetricList('Acme/Metrics')\n```\n\nThis will return a list of metrics in **list.metrics**. Note: this will return the namespaces and metrics for any namespace that begins with the given namespace. Consequently, all namespaces should be unique and not be substrings of another namespace.\n\nTo get a list of the dimensions available for a metric, pass in a namespace and metric.\n\n```typescript\nlet list: MetricList = await metrics.getMetricList('Acme/Metrics', 'speed')\n```\n\nThis will also return a list of dimensions in **list.dimensions**.\n\n## Metrics Scoping\n\nYou can scope metrics by chosing unique namespaces for different applications or services, or by using various dimensions for applications/services. This is the preferred design pattern.\n\nYou can also scope metrics by selecting a unique `owner` property via the CustomMetrics constructor. This property is used, in the primary key of metric items. This owner defaults to **'default'**.\n\n```javascript\nconst cartMetrics = new CustomMetrics({\n    owner: 'cart',\n    table: 'MyTable',\n    primaryKey: 'pk',\n    sortKey: 'sk',\n})\n```\n\n## Limitations\n\nIf you are updating metrics extremely frequently, CustomMetrics can impose a meaningful DynamoDB write load as each metric update will result in one database write. If you have very high frequency metric updates, consider using [Metric Buffering](#buffering) to buffer and coalesce metric updates.\n\n### CustomMetrics Class API\n\nThe CustomMetrics class provides the public API for CustomMetrics and public properties.\n\n### CustomMetrics Constructor\n\n```javascript\nconst metrics = new CustomMetrics({\n    owner: 'my-service',\n    primaryKey: 'pk',\n    region: 'us-east-1',\n    sortKey: 'sk',\n    table: 'MyTable',\n})\n```\n\nThe CustomMetrics constructor takes an options parameter and an optional context property.\n\nThe `options` parameter is of type `object` with the following properties:\n\n| Property | Type | Description | \n| -------- | :--: |------------ |\n| buffer | `object` | Buffer metric emits. Has properties: {count, elapsed, sum}\n| client | `object` | AWS DynamoDB client instance. Optional. If not specified, a client is created using the `table`, `creds` and `region` options.\n| consistent | `boolean` | Use DynamoDB consistent reads. Default false.\n| creds | `object` | AWS credentials to use when accessing the table. Not required if client supplied.\n| expires | `string` | Name of the DynamoDB TTL expiry attributes. Defaults to 'expires'.\n| log | `boolean | object` | Set to true for default logging or provide a logging object with methods for 'info', 'error' and 'trace'. Default to null.\n| owner | `string` | Unique owner of the metrics. This is used to compute the primary key for the metric data item.\n| prefix | `string` | Primary and sort key prefix to use. Defaults to 'metric#'.\n| pResolution | `number` | Number of values to store to compute P value statistics. Defaults to zero.\n| primaryKey | `string` | Name of the DynamoDB table primary key attribute. Defaults to 'pk'.\n| region | `string` | AWS region containing the table. Required if not the current region. Defaults to null.\n| sortKey | `string` | Name of the DynamoDB table sort key attribute. Defaults to 'sk'.\n| source | `string` | Reserved.\n| spans | `array` | Array of span definitions. See below.\n| table | `string` | Name of the DynamoDB table to use. (Required)\n| ttl | `number` | Maximum lifespan of the metrics in seconds.\n| type | `{[type]: \"Model\"}` | Define a type field in metric items for single table designs. Defaults to {_type: 'Metric'}.\n\nFor example:\n\n```javascript\nconst metrics = new CustomMetrics({\n    table: 'MyTable',\n    region: 'us-east-1',\n    primaryKey: 'pk',\n    sortKey: 'sk',\n    owner: 'my-service',\n    pResolution: 100,\n    ttl: 6 * 24 * 86400,\n    log: true,\n})\n```\n\nCustomMetric spans define how each metric is processed and aged. The spans are an ordered list of metric interval periods. \n\nThe default spans will store statistics for the periods: 5 minutes, 1 hour, 1 day, 1 week, 1 month and 1 year. \n\nVia the `spans` CustomMetrics constructor you can provide an alternate list of spans for higher, lower or more granular resolution.\n\nThe default CustomMetrics spans are:\n\n```typescript\nconst DefaultSpans: SpanDef[] = [\n    {period: 5 * 60, samples: 10}, //  5 mins, interval: 30 secs\n    {period: 60 * 60, samples: 12}, //  1 hr, interval: 5 mins\n    {period: 24 * 60 * 60, samples: 12}, //  24 hrs, interval: 2 hrs\n    {period: 7 * 24 * 60 * 60, samples: 14}, //  7 days, interval: 1/2 day\n    {period: 28 * 24 * 60 * 60, samples: 14}, //  28 days, interval: 2 days\n    {period: 365 * 24 * 60 * 60, samples: 12}, //  1 year, interval: 1 month\n]\n```\n\nThe span `period` property is the number of seconds in that span. The `samples` property specifies the number of data points to be captured. If you call emit() more frequently than the `period/samples` interval, CustomMetrics will agregate the extra values into the relevant span point value.\n\nHere is an example of a higher resolution set of spans that keep metric values for 1 minute, 5 minutes, 1 hour and 1 day.\n\n```typescript\nconst metrics = new CustomMetrics({\n    table: 'mytable',\n    spans: [\n        {period: 1 * 60, samples: 5}, //  interval: 5 secs\n        {period: 5 * 60, samples: 10}, //  interval: 30 secs\n        {period: 60 * 60, samples: 12}, //  interval: 5 mins\n        {period: 24 * 60 * 60, samples: 12}, //  interval: 2 hrs\n    ]\n})\n```\n\n#### Upgrading Metric Spans\n\nIf you want to change your spans in the future, you can upgrade your metric data with new spans. To do this, you can use the `upgrade` method. This will apportion data points from the old spans to the new spans based on the point's timestamp. The **upgrade** call takes the namespace, metric name and specific dimensions to upgrade. \n\nYou can also upgrade metrics by providing an **upgrade: true** parameter to the emit calls.\n\nIf you define new spans via the constructor and do not call upgrade, your new metrics will use the new spans and the old metrics will utilize the old spans. Query will still work, and CustomMetrics will return metrics according to the spans in use when the metric was first created. \n\nThe **upgrade** API and emit **upgrade** option are idempotent in that there is no ill effects from upgrading a metric that is already upgraded. The emit call will only upgrade if an upgrade is required.\n\nIf you do use custom span definitions, ensure you supply the custom span definition to all your constructor calls going forward. Otherwise, the default spans will be used for any new metrics.\n\n```typescript\nconst metrics = new CustomMetrics({\n    table: 'mytable',\n    //  New spans\n    spans: [\n        {period: 24 * 60 * 60, samples: 24},\n        {period: 7 * 24 * 60 * 60, samples: 28},\n        {period: 28 * 24 * 60 * 60, samples: 28},\n        {period: 365 * 24 * 60 * 60, samples: 48},\n    ]\n})\nawait metrics.upgrade('Acme/Metrics', 'launches', \n    [{}, {rocket: 'saturnV'}, {mission: 'ISS-service'}])\n\n// or\nawait metrics.emit('Acme/Metrics', 'launches', 5,\n    [{}, {rocket: 'saturnV'}, {mission: 'ISS-service'}])\n\n```\n\n## Logging\n\nIf the `log` constructor option is set to true, CustomMetrics will log errors to the console. If set to \"verbose\", CustomMetrics will also trace metric database accesses to the console.\n\nAlternatively, the `log` constructor can be set to a logging object such as [SenseLogs](https://www.npmjs.com/package/senselogs) that provides `info`, `error` and `trace` methods.\n\n## Buffering\n\nIf your app emits metrics at a very high frequency, you may wish to optimize metrics by aggregating metric database updates. CustomMetrics can optimize metric updates by buffering emit calls. These are then persisted according to a buffering policy.\n\nFor example:\n\n```javascript\nawait metrics.emit('Acme/Metrics', 'DataSent', 123, [], {\n    buffer: {sum: 1024, count: 20, elapsed: 60}\n})\n```\n\nThis example will buffer metric updates in-memory until the sum of buffered `DataSent` is greater than 1024, or there have been 20 calls to emit, or 60 seconds has elapsed, whichever is reached first. If the `elapsed` property is not provided, the default elapsed period is the data point interval of the lowest span (default 30 seconds).  CustomMetrics will regularly flush metrics as required.\n\nYou can also flush metrics manually by calling `flush` to flush metrics for an instance or `flushAll` which flushes metrics for all CustomMetrics instances.\n\n```javascript\nawait metrics.flush()\nawait CustomMetrics.flushAll()\n```\n\nIf you configure a Lambda layer (any layer will do), CustomMetrics will save buffered metrics upon Lambda instance termination. Unfortunately, Lambda will only send a termination signal to lambdas that utilize a Lambda layer.\n\nBuffered metrics may be less accurate than non-buffered metrics. Metrics may be retained in-memory for a period of time (as specified by the emit option.buffer parameter) before being flushed to DynamoDB. If a Lambda instance is not required to service a request, any buffered metrics will remain in-memory until the next request or when AWS terminates the Lambda -- whereupon the buffered values will be saved. This may mean a temporary loss of accuracy to querying entities.\n\nFurthermore, if you have a very large number of metrics in one Lambda instance, it is possible that the Lambda instance may not be able to save all buffered metrics during Lambda termination. This can be somewhat mitigated by using shorter buffering criteria.\n\nFor these reasons, don't use buffered metrics if you require absolute precision. But if you do have metrics where less than perfect accuracy is acceptable, then buffered metrics can give very large performance gains with minimal loss of precision.\n\n## Methods\n\n### emit\n\nEmit one or more metrics.\n\n```typescript\nasync emit(namespace: string, \n    metric: string, \n    value: number, \n    dimensions: MetricDimensionsList = [{}],\n    options?: {\n        buffer: {\n            sum: number, \n            count: number, \n            elapsed: number,\n        },\n        log: boolean,\n    }): Promise<Metric>\n```\n\nThis call will emit metrics for each of the specified dimensions using the supplied namespace and metric name. These will be combined with the CustomMetrics owner supplied via the constructor to scope the metric. \n\nFor example:\n\n```typescript\nawait metrics.emit('Acme/Metrics', 'launches', 10, \n    [{}, {rocket: 'saturnV'}, {mission: 'ISS-service'}])\n```\n\nThis will create three metrics:\n|Namespace|Metric|Dimensions|\n|-|-|-|\n|Acme/Metrics|launches|All|\n|Acme/Metrics|launches|rocket == saturnV|\n|Acme/Metrics|launches|mission == ISS-service|\n\nThe `buffer` option can be provided to optimize metric load by aggregating calls to emit(). See [Buffering](#buffering) for details.\n\nThe `log` option if set to true, will emit debug trace to the console.\n\n### query\n\nQuery a metric value.\n\n```typescript\nasync query(namespace: string, \n    metricName: string, \n    dimensions: MetricDimensions, \n    period: number, \n    statistic: string, \n    options: MetricQueryOptions,\n    Promise<MetricQueryResult>\n```\n\nThis will retrieve a metric value for a given namespace, metric name and set of dimensions.\n\nThe `period` argument selects the best metric span to query. For example: 3600 for one hour. The period will be used by query to find the span that has the same or closest (and greater) period.\n\nThe `statistic` can be `avg`, `current`, `max`, `min`, `sum`, `count` or a P-value of the form `pNN` where NN is the P-value. \n\nThe returned data will contain the `namespace`, `metric`, `dimensions` and data `points` for the query. The data points array will contain data with `value`, `count`, `timestamp` properties.\n\nThe `avg`, `max` and `min` statistics compute the average, maximum and minimum value for each span data point. The `current` statistic uses the most recent value for each span data point and is useful when used with the `accumulate` option to return the most recent value of a metric.\n\nThe `sum` statistic returns the summation of the values for each span data point and the `count` statistic returns the number of values for a span data point. \n\nFor a P-value metric example: p95 would return the P-95 value. To get meaningful P-value statistics you must set the CustomMetrics pResolution parameter to the number of data points to keep for computing P-values. By default this resolution is zero, which means P-values are not computed. To enable, you should set this to at least 100.\n\nThe `options` map can modify the query. If `options.accumulate` is true, all points will be aggregated and a single data point will be returned that will represent the desired statistic for the requested period.\n\nIf `options.owner` is provided, it overrides the default owner or the `owner` given to the CustomMetrics constructor. \n\nIf `options.id` is provided, the ID will be returned in the corresponding result items. This can help to correlate parallel queries with results.\n\nIf `options.log` is set to true, this will emit debug trace to the console.\n\nIf `options.start` is set to a date, the query will return data starting at that date for the requested period.\n\nTo optimize performance and data resolution, query point data has timestamps aligned on span boundaries. This means that your point timestamps, including the last point's timestamp will not generally align with the current time, but will be advanced to align with stored span's boundaries. \n\nThe timestamp for the last data point will not be greater than the current time and so the last data point may be shorter duration than previous points.\n\n### getMetricList\n\nReturn a list of supported namespaces, metrics and dimensions.\n\n```typescript\nasync getMetricList(\n    namespace: string | undefined, \n    metric: string | undefined, \n    options = {fields, limit}): Promise<MetricList>\n```\n\nThis call will return a MetricList of the form:\n\n```typescript\ntype MetricList = {\n    namespaces: string[]\n    metrics?: string[]\n    dimensions?: MetricDimensions[]\n}\n```\n\nIf a namespace argument is provided, the list of metrics in that namespace will be returned. If a metric argument is provided, the list of dimensions for that metric will be returned.\n\n\n## Metric Schema\n\nCustomMetrics are stored in a DynamoDB table using the following single-table schema. Metrics are stored as a single, compressed DynamoDB item. \n\nThe metric namespace, metric name and dimensions are encoded in the sort key to minimize space. The primary key encodes the metric owner to support multi-tenant security of items.\n\n| Field | Attribute | Encoding | Notes |\n| - | - | - | - |\n| primaryKey | primaryKey | ${prefix}#${version}#${owner} |\n| sortKey | primaryKey | ${prefix}#${namespace}#${metric}#${dimensions} |\n| expires | expires | number | Time in seconds when for DynamoDB auto removal |\n| spans | spans | string | Array of time spans |\n\n\nThe metric spans are encoded as:\n\n| Field | Attribute | Encoding | Notes |\n| - | - | - | - |\nend | se | number | Time in seconds of the end of the last point in the span\nperiod | sp | number | Span period in seconds\nsamples | ss | number | Number of data points in the span\npoints | pt | array | Data points \n\nThe span points are encoded as:\n\n| Field | Attribute | Encoding | Notes |\n| - | - | - | - |\ncount | c | number | Count of the values in sum\nsum | s | number | Sum of values\nmax | x | number | Maximum value seen\nmin | m | number | Minimum value seen\npvalues | v | array | P values\n\nHere is what a metric item looks like:\n\n```javascript\n{\n    pk: `metric#${version}#${owner}`,\n    sk: `metric#${namespace}#${metric}#${dimensions}`,\n    expires: Number,        // Time in seconds since Jan 1, 1970 when the item expires\n    spans: [\n        {\n            se: Number,     // Span End -- Time in seconds for the end of this span\n            sp: Number,     // Span Period -- Time span period in seconds\n            ss: Number,     // Span Samples -- Number of points in this span\n            pt: [\n                c: Number,  // Count of data measurments in this data point\n                x: Number,  // Maximum value in this point\n                m: Number,  // Minimum value in this point\n                s: Number,  // Sum of values in this point (Divide by c for average)\n            ]\n        }, ...\n    ],\n    seq: Number,            // Update sequence number for update collision detection\n    _type: \"Metric\"         // Item type for Single Table design patterns\n}\n```\n\nData from shorter spans are propagated lazily to longer spans when the span points become full. This is done during emit and flush only. Queries will flush buffered metrics for the matching query to disk. Queries will propagate earlier span data points in-memory and will not otherwise update the on-disk representation.\n\nThe span.end marks the time of the end of the point bucket and is updated whenever a new data point is added to the span. Spans may have zero or more data points. The span.end values for the various spans are not ordered, correlated or coordinated between spans. \n\n### References\n\n-   [DynamoDB OneTable](https://www.npmjs.com/package/dynamodb-onetable)\n-   [SenseDeep Blog](https://www.sensedeep.com/blog/)\n-   [SenseDeep Web Site](https://www.sensedeep.com/)\n-   [SenseDeep Developer Studio](https://app.sensedeep.com/)\n\n### Participate\n\nAll feedback, discussion, contributions and bug reports are very welcome.\n\n-   [Discussions](https://github.com/sensedeep/custom-metrics/discussions)\n-   [Issues](https://github.com/sensedeep/custom-metrics/issues)\n\n### Blog Articles\n\nHere is a collection of articles that can help you on your way with Custom Metrics\n\nTopic|Link\n-|-\nIntro to Custom Metrics | [https://www.sensedeep.com/blog/posts/stories/custom-metrics.html](https://www.sensedeep.com/blog/posts/stories/custom-metrics.html)\nCustom Metrics with IoT | [https://www.embedthis.com/blog/ioto/ioto-metrics.html](https://www.embedthis.com/blog/ioto/ioto-metrics.html).\n\n\n### Contact\n\nYou can contact me (Michael O'Brien) on Twitter at: [@mobstream](https://twitter.com/mobstream), and read my [Blog](https://www.sensedeep.com/blog).\n\n","readmeFilename":"README.md"}