forked from newrelic/node-newrelic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse-proc-cpuinfo.js
130 lines (113 loc) · 3.36 KB
/
parse-proc-cpuinfo.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
* Copyright 2020 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
'use strict'
const logger = require('./logger.js').child({ component: 'proc-cpuinfo' })
const PHYSICAL_ID = 'physical id'
const CPU_CORES = 'cpu cores'
const PROCESSOR = 'processor'
const CORE_ID = 'core id'
module.exports = parseProcCPUInfo
function parseProcCPUInfo(data) {
const relevantAttributes = [PROCESSOR, PHYSICAL_ID, CPU_CORES, CORE_ID]
let processorStats = {
logical: null,
cores: null,
packages: null
}
// In some rare cases the OS may be locked down so that you cannot retrieve this info.
if (!data) {
logger.debug('No CPU data to parse, returning empty stats.')
return processorStats
}
// separate the processors
let splitData = data.split('\n').map(function formatAttribute(attr) {
return attr.split(':').map(function eliminateExtraWhitespace(s) {
return s.replace(/\\r|\\t| {2,}/g, '').trim()
})
})
const validData = splitData.filter(function checkForValidAttrs(a) {
return a.length === 2 && relevantAttributes.indexOf(a[0]) !== -1
})
if (validData.length === 0) {
logger.debug('No applicable cpu attributes found')
return processorStats
}
splitData = collapseMultilineValues(splitData)
const processors = separateProcessors(splitData)
processorStats = countProcessorStats(processors)
if (!processorStats.cores) {
if (processorStats.logical === 1) {
// some older, single-core processors might not list ids,
// so we'll mark them 1
processorStats.cores = 1
processorStats.packages = 1
} else {
// there is no way of knowing how many packages
// or cores there are
processorStats.cores = null
processorStats.packages = null
}
}
return processorStats
}
// some values are split up over multiple lines, these won't be broken
// by split(':'), and should be folded into the last seen valid value
function collapseMultilineValues(li) {
const tmp = []
let last
for (let i = 0; i < li.length; ++i) {
if (li[i].length === 2) {
// store the last valid entry to append invalid entries to
last = li[i]
tmp.push(last)
} else {
last[1] += li[i][0]
}
}
return tmp
}
// walk through the processed list of key, value pairs and populate
// objects till you find a collision
function separateProcessors(processorData) {
const processors = []
let processor = Object.create(null)
for (let i = 0; i < processorData.length; ++i) {
const key = processorData[i][0]
const value = processorData[i][1]
if (processor[key] !== undefined) {
processors.push(processor)
processor = Object.create(null)
}
processor[key] = value
}
processors.push(processor)
return processors
}
function countProcessorStats(processors) {
const phys = []
const cores = []
for (let i = 0; i < processors.length; i++) {
const processor = processors[i]
if (
processor[PHYSICAL_ID] &&
processor[CPU_CORES] &&
phys.indexOf(processor[PHYSICAL_ID]) === -1
) {
phys.push(processor[PHYSICAL_ID])
cores.push(processor[CPU_CORES])
}
}
return {
logical: processors.length,
cores: cores
.map(function convertToInt(s) {
return parseInt(s, 10)
})
.reduce(function sum(a, b) {
return a + b
}, 0),
packages: phys.length
}
}