Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 49f63cace9 |
+3
-7
@@ -1,14 +1,10 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
spaces_around_brackets = both
|
||||
|
||||
[*.py]
|
||||
[*.{js,json,yml}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
|
||||
@@ -6,7 +6,6 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
.yarn
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
+4
-65
@@ -1,72 +1,11 @@
|
||||
import globals from 'globals'
|
||||
import pluginJs from '@eslint/js'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import prettierConfig from 'eslint-config-prettier'
|
||||
import { fileURLToPath } from 'url'
|
||||
import { dirname } from 'path'
|
||||
|
||||
export const getESMDirname = (importMetaUrl) => {
|
||||
return dirname(fileURLToPath(importMetaUrl))
|
||||
}
|
||||
|
||||
export default [
|
||||
{
|
||||
files: ['**/*.mjs'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.cjs'],
|
||||
languageOptions: {
|
||||
sourceType: 'commonjs'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.{js,mjs,cjs}', '**/.*.{js,mjs,cjs}'],
|
||||
...pluginJs.configs.recommended
|
||||
},
|
||||
{ ignores: ['node_modules', 'dist', '**/*.cjs'] },
|
||||
{
|
||||
files: ['**/*.{js,ts}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
globals: { ...globals.node },
|
||||
parserOptions: {
|
||||
tsconfigRootDir: getESMDirname(import.meta.url),
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
},
|
||||
{ files: ['**/*.{js,ts}'] },
|
||||
{ languageOptions: { globals: globals.browser } },
|
||||
pluginJs.configs.recommended,
|
||||
...tseslint.configs.recommendedTypeChecked.map((c) => ({
|
||||
...c,
|
||||
files: [...(c.files || []), '**/*.ts', '**/*.d.ts']
|
||||
})),
|
||||
{
|
||||
files: ['**/*.ts', '**/*.d.ts', 'bin/www'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
parserOptions: {
|
||||
tsconfigRootDir: getESMDirname(import.meta.url),
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/no-unsafe-return': 'error'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.spec.{js,ts}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node
|
||||
}
|
||||
}
|
||||
},
|
||||
prettierConfig
|
||||
...tseslint.configs.recommended,
|
||||
{ ignores: ['node_modules', 'dist', '**/*.cjs'] }
|
||||
]
|
||||
|
||||
+11
-13
@@ -3,19 +3,19 @@
|
||||
"description": "Default metrics for prom-client with higher frequency collection to histogram",
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.6.0",
|
||||
"@types/eslint": "^8.56.10",
|
||||
"@types/node": "^20.14.9",
|
||||
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
||||
"@typescript-eslint/parser": "^7.15.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||
"@typescript-eslint/parser": "^7.14.1",
|
||||
"eslint": "9.x",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-config-standard-with-typescript": "^43.0.1",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"globals": "^15.8.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-n": "^17.9.0",
|
||||
"eslint-plugin-promise": "^6.4.0",
|
||||
"globals": "^15.7.0",
|
||||
"lockfile-lint": "^4.14.0",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-organize-imports": "^3.2.4",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.5.2",
|
||||
"typescript-eslint": "^7.14.1"
|
||||
},
|
||||
@@ -23,10 +23,12 @@
|
||||
"node": "18"
|
||||
},
|
||||
"license": "Apache 2.0",
|
||||
"main": "./src/setup.ts",
|
||||
"name": "prom-client-fine-grained-metrics",
|
||||
"packageManager": "yarn@4.2.2",
|
||||
"repository": "https://github.com/specklesystems/prom-client-fine-grained-metrics",
|
||||
"peerDependencies": {
|
||||
"prom-client": ">= 10 <= 15"
|
||||
},
|
||||
"scripts": {
|
||||
"lint:eslint": "eslint .",
|
||||
"lint:tsc": "tsc --noEmit",
|
||||
@@ -39,11 +41,7 @@
|
||||
"prettier:fix": "yarn prettier --write .",
|
||||
"pre-commit:install": "pre-commit install",
|
||||
"pre-commit": "pre-commit run --all-files",
|
||||
"test": "NODE_ENV=test LOG_LEVEL=silent LOG_PRETTY=true vitest --run"
|
||||
"test": "yarn run test"
|
||||
},
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"prom-client": "^15.1.3"
|
||||
}
|
||||
"version": "0.0.1"
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Registry } from 'prom-client'
|
||||
export type Config = {
|
||||
register?: Registry
|
||||
namePrefix?: string
|
||||
collectionPeriodMilliseconds?: number
|
||||
labels?: string[]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export default function () {
|
||||
console.log('hello world!')
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/**
|
||||
* The default eventLoopLag metric in prom-client
|
||||
* already collects the data in a histogram, running repeatedly from
|
||||
* the start of the application.
|
||||
* We do not need to re-implement it.
|
||||
*/
|
||||
@@ -1,6 +0,0 @@
|
||||
/**
|
||||
* The default gc metric in prom-client
|
||||
* already collects the data in a histogram, running repeatedly from
|
||||
* the start of the application.
|
||||
* We do not need to re-implement it.
|
||||
*/
|
||||
@@ -1,65 +0,0 @@
|
||||
import { Gauge, Histogram } from 'prom-client'
|
||||
import { safeMemoryUsage } from '@/metrics/helpers/safeMemoryUsage'
|
||||
import { Config } from '@/domain/types'
|
||||
|
||||
const NODEJS_HEAP_SIZE_TOTAL = 'nodejs_heap_size_total_bytes'
|
||||
const NODEJS_HEAP_SIZE_USED = 'nodejs_heap_size_used_bytes'
|
||||
const NODEJS_EXTERNAL_MEMORY = 'nodejs_external_memory_bytes'
|
||||
const NODEJS_HEAP_SIZE_TOTAL_HISTOGRAM = 'nodejs_heap_size_total_bytes_histogram'
|
||||
|
||||
export const heapSizeAndUsed = (config: Config) => {
|
||||
if (typeof process.memoryUsage !== 'function') {
|
||||
return
|
||||
}
|
||||
const labels = config.labels ?? {}
|
||||
const labelNames = Object.keys(labels)
|
||||
|
||||
const registers = config.register ? [config.register] : undefined
|
||||
const namePrefix = config.namePrefix ?? ''
|
||||
|
||||
const collect = () => {
|
||||
const memUsage = safeMemoryUsage()
|
||||
if (memUsage) {
|
||||
heapSizeTotal.set(labels, memUsage.heapTotal)
|
||||
heapSizeUsed.set(labels, memUsage.heapUsed)
|
||||
if (memUsage.external !== undefined) {
|
||||
externalMemUsed.set(labels, memUsage.external)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const h = new Histogram({
|
||||
name: namePrefix + NODEJS_HEAP_SIZE_TOTAL_HISTOGRAM,
|
||||
help: 'Process heap size from Node.js in bytes.',
|
||||
registers,
|
||||
labelNames,
|
||||
collect
|
||||
})
|
||||
|
||||
const heapSizeTotal = new Gauge({
|
||||
name: namePrefix + NODEJS_HEAP_SIZE_TOTAL,
|
||||
help: 'Process heap size from Node.js in bytes.',
|
||||
registers,
|
||||
labelNames,
|
||||
// Use this one metric's `collect` to set all metrics' values.
|
||||
collect
|
||||
})
|
||||
const heapSizeUsed = new Gauge({
|
||||
name: namePrefix + NODEJS_HEAP_SIZE_USED,
|
||||
help: 'Process heap size used from Node.js in bytes.',
|
||||
registers,
|
||||
labelNames
|
||||
})
|
||||
const externalMemUsed = new Gauge({
|
||||
name: namePrefix + NODEJS_EXTERNAL_MEMORY,
|
||||
help: 'Node.js external memory size in bytes.',
|
||||
registers,
|
||||
labelNames
|
||||
})
|
||||
}
|
||||
|
||||
export const metricNames = [
|
||||
NODEJS_HEAP_SIZE_TOTAL,
|
||||
NODEJS_HEAP_SIZE_USED,
|
||||
NODEJS_EXTERNAL_MEMORY
|
||||
]
|
||||
@@ -1,8 +0,0 @@
|
||||
// process.memoryUsage() can throw on some platforms, see #67
|
||||
export function safeMemoryUsage() {
|
||||
try {
|
||||
return process.memoryUsage()
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import { isObject } from '@/utils'
|
||||
import { heapSizeAndUsed } from '@/metrics/heapSizeAndUsed'
|
||||
import { Config } from '@/domain/types'
|
||||
|
||||
const metrics = [heapSizeAndUsed]
|
||||
|
||||
export default function (config: Config) {
|
||||
console.log('registering metrics!')
|
||||
|
||||
//register metrics
|
||||
if (config !== null && config !== undefined && !isObject(config)) {
|
||||
throw new TypeError('config must be null, undefined, or an object')
|
||||
}
|
||||
|
||||
for (const metric of Object.values(metrics)) {
|
||||
metric(config)
|
||||
}
|
||||
|
||||
return () => {
|
||||
repeatAction({
|
||||
action: collectMetrics,
|
||||
period: config.collectionPeriodMilliseconds ?? 100
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const shouldStopRepeatingAction = false
|
||||
const repeatAction = (params: { action: () => Promise<void>; period: number }) => {
|
||||
return async () => {
|
||||
if (shouldStopRepeatingAction) return
|
||||
setInterval(repeatAction(params), params.period)
|
||||
await params.action()
|
||||
}
|
||||
}
|
||||
|
||||
const collectMetrics = () => {
|
||||
console.log('collecting metrics')
|
||||
return Promise.resolve()
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export const isObject = (obj: unknown): boolean => {
|
||||
return obj !== null && typeof obj === 'object'
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["**/*.spec.js", "**/*.spec.ts", "tests/**/*"]
|
||||
"exclude": ["**/*.spec.js", "**/*.spec.ts", "test/**/*"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [".*.cjs"]
|
||||
}
|
||||
+11
-12
@@ -24,17 +24,16 @@
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
|
||||
/* Modules */
|
||||
"module": "Node16" /* Specify what module code is generated. */,
|
||||
"rootDir": "./" /* Specify the root folder within your source files. */,
|
||||
"moduleResolution": "Node16" /* Specify how TypeScript looks up a file from a given module specifier. */,
|
||||
"baseUrl": "./" /* Specify the base directory to resolve non-relative module names. */,
|
||||
"module": "NodeNext" /* Specify what module code is generated. */,
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"moduleResolution": "NodeNext" /* Specify how TypeScript looks up a file from a given module specifier. */,
|
||||
"baseUrl": "." /* Specify the base directory to resolve non-relative module names. */,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
"#/*": ["./tests/*"]
|
||||
"@/*": ["./*"]
|
||||
},
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
|
||||
// "types": ["node"], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files */
|
||||
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
|
||||
@@ -45,8 +44,8 @@
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
|
||||
// "declarationMap": true /* Create sourcemaps for d.ts files. */,
|
||||
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
|
||||
"declarationMap": true /* Create sourcemaps for d.ts files. */,
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
"sourceMap": true /* Create source map files for emitted JavaScript files. */,
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
|
||||
@@ -94,8 +93,8 @@
|
||||
"noUncheckedIndexedAccess": true /* Include 'undefined' in index signature results */,
|
||||
"noImplicitOverride": true /* Ensure overriding members in derived classes are marked with an override modifier. */,
|
||||
"noPropertyAccessFromIndexSignature": true /* Enforces using indexed accessors for keys declared using an indexed type */,
|
||||
// "allowUnusedLabels": true /* Disable error reporting for unused labels. */,
|
||||
// "allowUnreachableCode": true /* Disable error reporting for unreachable code. */,
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
"noErrorTruncation": true,
|
||||
|
||||
/* Completeness */
|
||||
@@ -105,6 +104,6 @@
|
||||
"ts-node": {
|
||||
"swc": true
|
||||
},
|
||||
"include": ["tests/**/*.ts", "src/**/*.ts", "eslint.config.mjs"],
|
||||
"include": ["src/**/*.ts", "eslint.config.mjs"],
|
||||
"exclude": ["node_modules", "dist/**/*"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user