-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Core metrics collection - collect more memory related metrics #172146
Changes from all commits
b98182e
c584ff4
9fa6b7c
10e9799
c5d4f89
237814c
d726930
d98af78
9dc5441
31b88e8
a3e9c6b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,37 +13,60 @@ import type { OsCgroupMetrics } from './types'; | |
const PROC_CGROUP2_DIR = '/sys/fs/cgroup'; | ||
const CPU_STATS_FILE = 'cpu.stat'; | ||
const CPU_MAX_FILE = 'cpu.max'; | ||
const MEMORY_CURRENT_FILE = 'memory.current'; | ||
const MEMORY_SWAP_CURRENT_FILE = 'memory.swap.current'; | ||
|
||
interface Arg { | ||
cpuPath: string; | ||
cpuAcctPath: string; | ||
} | ||
const getCGroupFilePath = (group: string, fileName: string): string => { | ||
return joinPath(PROC_CGROUP2_DIR, group, fileName); | ||
}; | ||
|
||
export async function gatherV2CgroupMetrics(arg: Arg): Promise<OsCgroupMetrics> { | ||
const [{ usage_nanos: usageNanos, ...stat }, cpuMax] = await Promise.all([ | ||
readCPUStat(arg.cpuPath), | ||
readCPUMax(arg.cpuPath), | ||
]); | ||
export async function gatherV2CgroupMetrics(group: string): Promise<OsCgroupMetrics> { | ||
const [{ usage_nanos: usageNanos, ...stat }, cpuMax, memoryCurrent, swapCurrent] = | ||
await Promise.all([ | ||
readCPUStat(group), | ||
readCPUMax(group), | ||
readMemoryCurrent(group), | ||
readSwapCurrent(group), | ||
]); | ||
|
||
return { | ||
cpu: { | ||
...cpuMax, | ||
control_group: arg.cpuPath, | ||
control_group: group, | ||
stat, | ||
}, | ||
cpuacct: { | ||
control_group: arg.cpuPath, | ||
control_group: group, | ||
usage_nanos: usageNanos, | ||
}, | ||
cgroup_memory: { | ||
current_in_bytes: memoryCurrent, | ||
swap_current_in_bytes: swapCurrent, | ||
}, | ||
}; | ||
} | ||
|
||
interface CPUMax { | ||
cfs_period_micros: number; | ||
cfs_quota_micros: number; | ||
} | ||
|
||
async function readMemoryCurrent(group: string): Promise<number> { | ||
const rawMemoryCurrent = (await fs.readFile(getCGroupFilePath(group, MEMORY_CURRENT_FILE))) | ||
.toString() | ||
.trim(); | ||
return parseInt(rawMemoryCurrent, 10); | ||
} | ||
|
||
async function readSwapCurrent(group: string): Promise<number> { | ||
const rawMemoryCurrent = (await fs.readFile(getCGroupFilePath(group, MEMORY_SWAP_CURRENT_FILE))) | ||
.toString() | ||
.trim(); | ||
return parseInt(rawMemoryCurrent, 10); | ||
} | ||
Comment on lines
+54
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both are "single constant" numeric files |
||
|
||
async function readCPUMax(group: string): Promise<CPUMax> { | ||
const [quota, period] = (await fs.readFile(joinPath(PROC_CGROUP2_DIR, group, CPU_MAX_FILE))) | ||
const [quota, period] = (await fs.readFile(getCGroupFilePath(group, CPU_MAX_FILE))) | ||
.toString() | ||
.trim() | ||
.split(/\s+/); | ||
|
@@ -62,7 +85,7 @@ async function readCPUStat(group: string): Promise<CPUStat> { | |
time_throttled_nanos: -1, | ||
usage_nanos: -1, | ||
}; | ||
return (await fs.readFile(joinPath(PROC_CGROUP2_DIR, group, CPU_STATS_FILE))) | ||
return (await fs.readFile(getCGroupFilePath(group, CPU_STATS_FILE))) | ||
.toString() | ||
.split(/\n/) | ||
.reduce((acc, line) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,7 +86,12 @@ export function getEcsOpsMetricsLog(metrics: OpsMetrics) { | |
memory: { | ||
heap: { | ||
usedInBytes: processMemoryUsedInBytes, | ||
totalInBytes: process?.memory?.heap.total_in_bytes, | ||
sizeLimit: process?.memory?.heap.size_limit, | ||
}, | ||
residentSetSizeInBytes: process?.memory?.resident_set_size_in_bytes, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want these to log to stdout in pattern format, we'll need to need to fiddle with
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logs are fine in `json` format:{
"event": {
"kind": "metric",
"category": [
"process",
"host"
],
"type": [
"info"
]
},
"process": {
"uptime": 72.65337025,
"memory": {
"heap": {
"usedInBytes": 602026648,
"totalInBytes": 695664640,
"sizeLimit": 4345298944
},
"residentSetSizeInBytes": 1079312384,
"externalInBytes": 7233984, <--- this PR
"arrayBuffersInBytes": <--- this PR
},
"eventLoopDelay": 10.336272995850623,
"eventLoopDelayHistogram": {
"50": 10.346495,
"95": 11.010047,
"99": 12.140543
},
"eventLoopUtilization": {
"active": 279.28487307039177,
"idle": 4719.119918999997,
"utilization": 0.05587480099920223
},
"pid": 63971
},
"host": {
"os": {
"load": {
"1m": 6.076171875,
"5m": 6.0078125,
"15m": 6.32568359375
}
}
},
"service": {
"node": {
"roles": [
"background_tasks",
"ui"
]
}
},
"ecs": {
"version": "8.6.1"
},
"@timestamp": "2023-11-29T16:15:47.457-07:00",
"message": "memory: 574.1MB uptime: 0:01:12 load: [6.08,6.01,6.33] mean delay: 10.336 delay histogram: { 50: 10.346; 95: 11.010; 99: 12.141 } utilization: 0.05587",
"log": {
"level": "DEBUG",
"logger": "metrics.ops"
},
"trace": {
"id": "095027dd7070903121c4316455216d32"
},
"transaction": {
"id": "56fde480923f64a4"
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think it's fine. It's mostly for debug scenarios anyway, and we're using the json layout where it matters. But thanks for pointing that out! |
||
externalInBytes: process?.memory?.external_in_bytes, | ||
arrayBuffersInBytes: process?.memory?.array_buffers_in_bytes, | ||
}, | ||
eventLoopDelay: eventLoopDelayVal, | ||
eventLoopDelayHistogram: eventLoopDelayHistVals, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored the signatures about v1/v2 detection a bit to get closer to reality (v2 -> a single group path)