systeminformation 5.31.17 → 5.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -163,6 +163,7 @@ si.cpu()
163
163
 
164
164
  (last 7 major and minor version releases)
165
165
 
166
+ - Version 5.32.0: `graphics()` added temperature values (macOS), `dockerContainer()` addes labels
166
167
  - Version 5.31.0: `diskLayout()` added smartmontools support (macOS)
167
168
  - Version 5.30.0: `processes()` added user (windows) - needed to be reverted
168
169
  - Version 5.29.0: `osInfo()` added OS code name (windows)
@@ -404,14 +405,15 @@ Full function reference with examples can be found at
404
405
  | | ...[0].external | | | X | | | is external GPU |
405
406
  | | ...[0].cores | | | X | | | Apple silicon only |
406
407
  | | ...[0].metalVersion | | | X | | | Apple Metal Version |
408
+ | | ...[0].temperatureGpu | X | | X | X | | GPU temperature (see notes below) |
407
409
  | | displays[] | X | | X | X | | monitor/display array |
408
410
  | | ...[0].vendor | | | | X | | monitor/display vendor |
409
411
  | | ...[0].vendorId | | | X | | | vendor ID |
410
412
  | | ...[0].deviceName | | | | X | | e.g. \\\\.\\DISPLAY1 |
411
413
  | | ...[0].model | X | | X | X | | monitor/display model |
412
- | | ...[0].productionYear | | | X | | | production year |
413
- | | ...[0].serial | | | X | | | serial number |
414
- | | ...[0].displayId | | | X | | | display ID |
414
+ | | ...[0].productionYear | | | X | X | | production year |
415
+ | | ...[0].serial | | | X | X | | serial number |
416
+ | | ...[0].displayId | | | X | X | | display ID |
415
417
  | | ...[0].main | X | | X | X | | true if main monitor |
416
418
  | | ...[0].builtin | X | | X | | | true if built-in monitor |
417
419
  | | ...[0].connection | X | | X | X | | e.g. DisplayPort or HDMI |
@@ -422,8 +424,8 @@ Full function reference with examples can be found at
422
424
  | | ...[0].resolutionY | X | | X | X | | pixel vertical |
423
425
  | | ...[0].currentResX | X | | X | X | | current pixel horizontal |
424
426
  | | ...[0].currentResY | X | | X | X | | current pixel vertical |
425
- | | ...[0].positionX | | | X | X | | display position X |
426
- | | ...[0].positionY | | | X | X | | display position Y |
427
+ | | ...[0].positionX | X | | X | X | | display position X |
428
+ | | ...[0].positionY | X | | X | X | | display position Y |
427
429
  | | ...[0].currentRefreshRate | X | | X | X | | current screen refresh rate |
428
430
 
429
431
  #### 7. Operating System
@@ -434,7 +436,7 @@ Full function reference with examples can be found at
434
436
  | | platform | X | X | X | X | X | 'linux', 'darwin', 'Windows', ... |
435
437
  | | distro | X | X | X | X | X | |
436
438
  | | release | X | X | X | X | X | |
437
- | | codename | X | | X | X | | |
439
+ | | codename | X | | X | X | | |
438
440
  | | kernel | X | X | X | X | X | kernel release - same as os.release() |
439
441
  | | arch | X | X | X | X | X | same as os.arch() |
440
442
  | | hostname | X | X | X | X | X | same as os.hostname() |
@@ -830,6 +832,7 @@ Full function reference with examples can be found at
830
832
  | | [0].startedAt | X | X | X | X | X | creation date time string |
831
833
  | | [0].finishedAt | X | X | X | X | X | creation date time string |
832
834
  | | [0].state | X | X | X | X | X | created, running, exited |
835
+ | | [0].labels | X | X | X | X | X | object of labels (key-value pairs) |
833
836
  | | [0].ports | X | X | X | X | X | array of ports |
834
837
  | | [0].mounts | X | X | X | X | X | array of mounts |
835
838
  | si.dockerContainerStats(ids, cb) | [{...}] | X | X | X | X | X | statistics for specific containers<br>container IDs: space or comma separated,<br>pass '*' for all containers |
@@ -1021,7 +1024,9 @@ $ npm install macos-temperature-sensor --save
1021
1024
  ```
1022
1025
 
1023
1026
  `systeminformation` will then detect this additional library and return the
1024
- temperature when calling systeminformations standard function `cpuTemperature()`
1027
+ temperature when calling systeminformations standard function `cpuTemperature()`.
1028
+ On Apple Silicon machines `macos-temperature-sensor` also enables the GPU
1029
+ temperature (`temperatureGpu`) in the `graphics()` controllers
1025
1030
 
1026
1031
  #### Windows Temperature, Battery, ...
1027
1032
 
package/lib/audio.js CHANGED
@@ -103,16 +103,17 @@ function getLinuxAudioPci() {
103
103
  }
104
104
 
105
105
  function parseWinAudioStatus(n) {
106
+ const num = parseInt(n, 10);
106
107
  let status = n;
107
- if (n === 1) {
108
+ if (num === 1) {
108
109
  status = 'other';
109
- } else if (n === 2) {
110
+ } else if (num === 2) {
110
111
  status = 'unknown';
111
- } else if (n === 3) {
112
+ } else if (num === 3) {
112
113
  status = 'enabled';
113
- } else if (n === 4) {
114
+ } else if (num === 4) {
114
115
  status = 'disabled';
115
- } else if (n === 5) {
116
+ } else if (num === 5) {
116
117
  status = 'not applicable';
117
118
  }
118
119
  return status;
package/lib/battery.js CHANGED
@@ -100,8 +100,12 @@ module.exports = (callback) =>
100
100
  }
101
101
 
102
102
  if (acPath) {
103
- const file = fs.readFileSync(acPath);
104
- acConnected = file.toString().trim() === '1';
103
+ try {
104
+ const file = fs.readFileSync(acPath);
105
+ acConnected = file.toString().trim() === '1';
106
+ } catch {
107
+ util.noop();
108
+ }
105
109
  }
106
110
 
107
111
  if (battery_path) {
package/lib/bluetooth.js CHANGED
@@ -175,8 +175,12 @@ function bluetoothDevices(callback) {
175
175
  const macAddr1 = pathParts.length >= 6 ? pathParts[pathParts.length - 2] : null;
176
176
  const macAddr2 = pathParts.length >= 7 ? pathParts[pathParts.length - 3] : null;
177
177
  if (filename === 'info') {
178
- const infoFile = fs.readFileSync(element, { encoding: 'utf8' }).split('\n');
179
- result.push(parseLinuxBluetoothInfo(infoFile, macAddr1, macAddr2));
178
+ try {
179
+ const infoFile = fs.readFileSync(element, { encoding: 'utf8' }).split('\n');
180
+ result.push(parseLinuxBluetoothInfo(infoFile, macAddr1, macAddr2));
181
+ } catch {
182
+ util.noop();
183
+ }
180
184
  }
181
185
  });
182
186
  // determine "connected" with hcitool con
package/lib/cpu.js CHANGED
@@ -979,8 +979,8 @@ function getCpu() {
979
979
  }
980
980
  }
981
981
  _cpu_speed = result.speed;
982
- result.speedMin = Math.round(parseFloat(util.getValue(lines, 'cpu min mhz').replace(/,/g, '.')) / 10.0) / 100;
983
- result.speedMax = Math.round(parseFloat(util.getValue(lines, 'cpu max mhz').replace(/,/g, '.')) / 10.0) / 100;
982
+ result.speedMin = Math.round(parseFloat(util.getValue(lines, 'cpu min mhz').replace(/,/g, '.')) / 10.0) / 100 || result.speedMin;
983
+ result.speedMax = Math.round(parseFloat(util.getValue(lines, 'cpu max mhz').replace(/,/g, '.')) / 10.0) / 100 || result.speedMax;
984
984
 
985
985
  result = cpuBrandManufacturer(result);
986
986
  result.vendor = cpuManufacturer(util.getValue(lines, 'vendor id'));
@@ -1029,18 +1029,22 @@ function getCpu() {
1029
1029
 
1030
1030
  // Test RISC-V
1031
1031
  if (util.getValue(lines, 'architecture') === 'riscv64') {
1032
- const linesRiscV = fs.readFileSync('/proc/cpuinfo').toString().split('\n');
1033
- const uarch = util.getValue(linesRiscV, 'uarch') || '';
1034
- if (uarch.indexOf(',') > -1) {
1035
- const split = uarch.split(',');
1036
- result.manufacturer = cpuManufacturer(split[0]);
1037
- result.brand = split[1];
1032
+ try {
1033
+ const linesRiscV = fs.readFileSync('/proc/cpuinfo').toString().split('\n');
1034
+ const uarch = util.getValue(linesRiscV, 'uarch') || '';
1035
+ if (uarch.indexOf(',') > -1) {
1036
+ const split = uarch.split(',');
1037
+ result.manufacturer = cpuManufacturer(split[0]);
1038
+ result.brand = split[1];
1039
+ }
1040
+ } catch {
1041
+ util.noop();
1038
1042
  }
1039
1043
  }
1040
1044
 
1041
1045
  // socket type
1042
1046
  let lines2 = [];
1043
- exec('export LC_ALL=C; dmidecode t 4 2>/dev/null | grep "Upgrade: Socket"; unset LC_ALL', (error2, stdout2) => {
1047
+ exec('export LC_ALL=C; dmidecode -t 4 2>/dev/null | grep "Upgrade: Socket"; unset LC_ALL', (error2, stdout2) => {
1044
1048
  lines2 = stdout2.toString().split('\n');
1045
1049
  if (lines2 && lines2.length) {
1046
1050
  result.socket = util.getValue(lines2, 'Upgrade').replace('Socket', '').trim() || result.socket;
@@ -1055,7 +1059,7 @@ function getCpu() {
1055
1059
  if (os.cpus()[0] && os.cpus()[0].model) {
1056
1060
  modelline = os.cpus()[0].model;
1057
1061
  }
1058
- exec('export LC_ALL=C; dmidecode -t 4; dmidecode -t 7 unset LC_ALL', (error, stdout) => {
1062
+ exec('export LC_ALL=C; dmidecode -t 4; dmidecode -t 7; unset LC_ALL', (error, stdout) => {
1059
1063
  let cache = [];
1060
1064
  if (!error) {
1061
1065
  const data = stdout.toString().split('# dmidecode');
@@ -1077,7 +1081,7 @@ function getCpu() {
1077
1081
  }
1078
1082
  _cpu_speed = result.speed;
1079
1083
  result.speedMin = result.speed;
1080
- result.speedMax = Math.round(parseFloat(util.getValue(lines, 'max speed').replace(/Mhz/g, '')) / 10.0) / 100;
1084
+ result.speedMax = Math.round(parseFloat(util.getValue(lines, 'max speed').replace(/Mhz/g, '')) / 10.0) / 100 || result.speed;
1081
1085
 
1082
1086
  result = cpuBrandManufacturer(result);
1083
1087
  result.vendor = cpuManufacturer(util.getValue(lines, 'manufacturer'));
@@ -1149,7 +1153,7 @@ function getCpu() {
1149
1153
  result = cpuBrandManufacturer(result);
1150
1154
  result.revision = util.getValue(lines, 'revision', ':');
1151
1155
  result.vendor = util.getValue(lines, 'manufacturer', ':');
1152
- result.speedMax = Math.round(parseFloat(util.getValue(lines, 'maxclockspeed', ':').replace(/,/g, '.')) / 10.0) / 100;
1156
+ result.speedMax = Math.round(parseFloat(util.getValue(lines, 'maxclockspeed', ':').replace(/,/g, '.')) / 10.0) / 100 || result.speedMax;
1153
1157
  if (result.speed === 0 && (result.brand.indexOf('AMD') > -1 || result.brand.toLowerCase().indexOf('ryzen') > -1)) {
1154
1158
  result.speed = getAMDSpeed(result.brand);
1155
1159
  }
@@ -1440,28 +1444,28 @@ function cpuTemperature(callback) {
1440
1444
 
1441
1445
  if (section === 'acpi') {
1442
1446
  // socket temp
1443
- if (firstPart.indexOf('TEMP') !== -1) {
1447
+ if (firstPart.indexOf('TEMP') !== -1 && temps) {
1444
1448
  result.socket.push(parseFloat(temps));
1445
1449
  }
1446
1450
  } else if (section === 'pch') {
1447
1451
  // chipset temp
1448
- if (firstPart.indexOf('TEMP') !== -1 && !result.chipset) {
1452
+ if (firstPart.indexOf('TEMP') !== -1 && !result.chipset && temps) {
1449
1453
  result.chipset = parseFloat(temps);
1450
1454
  }
1451
1455
  }
1452
1456
  // cpu temp
1453
- if (firstPart.indexOf('PHYSICAL') !== -1 || firstPart.indexOf('PACKAGE') !== -1 || (section === 'coreAMD' && firstPart.indexOf('TDIE') !== -1)) {
1457
+ if ((firstPart.indexOf('PHYSICAL') !== -1 || firstPart.indexOf('PACKAGE') !== -1 || (section === 'coreAMD' && firstPart.indexOf('TDIE') !== -1)) && temps) {
1454
1458
  result.main = parseFloat(temps);
1455
1459
  }
1456
- if (firstPart.indexOf('CORE ') !== -1) {
1460
+ if (firstPart.indexOf('CORE ') !== -1 && temps) {
1457
1461
  result.cores.push(parseFloat(temps));
1458
1462
  }
1459
- if (firstPart.indexOf('TDIE') !== -1 && tdieTemp === null) {
1463
+ if (firstPart.indexOf('TDIE') !== -1 && tdieTemp === null && temps) {
1460
1464
  tdieTemp = parseFloat(temps);
1461
1465
  }
1462
1466
 
1463
1467
  // generic temp value from cpuThermal
1464
- if (section === 'cpuThermal' && firstPart.indexOf('TEMP') !== -1 && cpuThermalTemp === null) {
1468
+ if (section === 'cpuThermal' && firstPart.indexOf('TEMP') !== -1 && cpuThermalTemp === null && temps) {
1465
1469
  cpuThermalTemp = parseFloat(temps);
1466
1470
  }
1467
1471
  });
@@ -1509,7 +1513,7 @@ function cpuTemperature(callback) {
1509
1513
  exec('/opt/vc/bin/vcgencmd measure_temp', (error, stdout) => {
1510
1514
  if (!error) {
1511
1515
  const lines = stdout.toString().split('\n');
1512
- if (lines.length > 0 && lines[0].indexOf('=')) {
1516
+ if (lines.length > 0 && lines[0].indexOf('=') !== -1) {
1513
1517
  result.main = parseFloat(lines[0].split('=')[1]);
1514
1518
  result.max = result.main;
1515
1519
  }
@@ -1863,10 +1867,10 @@ function cpuCache(callback) {
1863
1867
  size = size * (unit === 'kb' ? 1024 : unit === 'mb' ? 1024 * 1024 : unit === 'gb' ? 1024 * 1024 * 1024 : 1);
1864
1868
  if (cacheType) {
1865
1869
  if (cacheType === 'l1') {
1866
- result.cache[cacheType + 'd'] = size / 2;
1867
- result.cache[cacheType + 'i'] = size / 2;
1870
+ result[cacheType + 'd'] = size / 2;
1871
+ result[cacheType + 'i'] = size / 2;
1868
1872
  } else {
1869
- result.cache[cacheType] = size;
1873
+ result[cacheType] = size;
1870
1874
  }
1871
1875
  }
1872
1876
  }
@@ -1883,10 +1887,10 @@ function cpuCache(callback) {
1883
1887
  lines.forEach((line) => {
1884
1888
  let parts = line.split(':');
1885
1889
  if (parts[0].toLowerCase().indexOf('hw.l1icachesize') !== -1) {
1886
- result.l1d = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
1890
+ result.l1i = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
1887
1891
  }
1888
1892
  if (parts[0].toLowerCase().indexOf('hw.l1dcachesize') !== -1) {
1889
- result.l1i = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
1893
+ result.l1d = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
1890
1894
  }
1891
1895
  if (parts[0].toLowerCase().indexOf('hw.l2cachesize') !== -1) {
1892
1896
  result.l2 = parseInt(parts[1].trim()) * (parts[1].indexOf('K') !== -1 ? 1024 : 1);
@@ -2085,14 +2089,15 @@ function getLoad() {
2085
2089
  _cpus[i].loadSteal = _cpus[i].steal - tmpSteal;
2086
2090
  _cpus[i].loadGuest = _cpus[i].guest - tmpGuest;
2087
2091
  cores[i] = {};
2088
- cores[i].load = (_cpus[i].load / _cpus[i].currentTick) * 100;
2089
- cores[i].loadUser = (_cpus[i].loadUser / _cpus[i].currentTick) * 100;
2090
- cores[i].loadSystem = (_cpus[i].loadSystem / _cpus[i].currentTick) * 100;
2091
- cores[i].loadNice = (_cpus[i].loadNice / _cpus[i].currentTick) * 100;
2092
- cores[i].loadIdle = (_cpus[i].loadIdle / _cpus[i].currentTick) * 100;
2093
- cores[i].loadIrq = (_cpus[i].loadIrq / _cpus[i].currentTick) * 100;
2094
- cores[i].loadSteal = (_cpus[i].loadSteal / _cpus[i].currentTick) * 100;
2095
- cores[i].loadGuest = (_cpus[i].loadGuest / _cpus[i].currentTick) * 100;
2092
+ const coreTick = _cpus[i].currentTick || 1;
2093
+ cores[i].load = (_cpus[i].load / coreTick) * 100;
2094
+ cores[i].loadUser = (_cpus[i].loadUser / coreTick) * 100;
2095
+ cores[i].loadSystem = (_cpus[i].loadSystem / coreTick) * 100;
2096
+ cores[i].loadNice = (_cpus[i].loadNice / coreTick) * 100;
2097
+ cores[i].loadIdle = (_cpus[i].loadIdle / coreTick) * 100;
2098
+ cores[i].loadIrq = (_cpus[i].loadIrq / coreTick) * 100;
2099
+ cores[i].loadSteal = (_cpus[i].loadSteal / coreTick) * 100;
2100
+ cores[i].loadGuest = (_cpus[i].loadGuest / coreTick) * 100;
2096
2101
  cores[i].rawLoad = _cpus[i].load;
2097
2102
  cores[i].rawLoadUser = _cpus[i].loadUser;
2098
2103
  cores[i].rawLoadSystem = _cpus[i].loadSystem;
@@ -2104,7 +2109,7 @@ function getLoad() {
2104
2109
  }
2105
2110
  const totalTick = totalUser + totalSystem + totalNice + totalIrq + totalSteal + totalGuest + totalIdle;
2106
2111
  const totalLoad = totalUser + totalSystem + totalNice + totalIrq + totalSteal + totalGuest;
2107
- const currentTick = totalTick - _current_cpu.tick;
2112
+ const currentTick = totalTick - _current_cpu.tick || 1;
2108
2113
  result = {
2109
2114
  avgLoad: avgLoad,
2110
2115
  currentLoad: ((totalLoad - _current_cpu.load) / currentTick) * 100,
@@ -2157,12 +2162,15 @@ function getLoad() {
2157
2162
  const cores = [];
2158
2163
  for (let i = 0; i < _corecount; i++) {
2159
2164
  cores[i] = {};
2160
- cores[i].load = (_cpus[i].load / _cpus[i].currentTick) * 100;
2161
- cores[i].loadUser = (_cpus[i].loadUser / _cpus[i].currentTick) * 100;
2162
- cores[i].loadSystem = (_cpus[i].loadSystem / _cpus[i].currentTick) * 100;
2163
- cores[i].loadNice = (_cpus[i].loadNice / _cpus[i].currentTick) * 100;
2164
- cores[i].loadIdle = (_cpus[i].loadIdle / _cpus[i].currentTick) * 100;
2165
- cores[i].loadIrq = (_cpus[i].loadIrq / _cpus[i].currentTick) * 100;
2165
+ const coreTick = _cpus[i].currentTick || 1;
2166
+ cores[i].load = (_cpus[i].load / coreTick) * 100;
2167
+ cores[i].loadUser = (_cpus[i].loadUser / coreTick) * 100;
2168
+ cores[i].loadSystem = (_cpus[i].loadSystem / coreTick) * 100;
2169
+ cores[i].loadNice = (_cpus[i].loadNice / coreTick) * 100;
2170
+ cores[i].loadIdle = (_cpus[i].loadIdle / coreTick) * 100;
2171
+ cores[i].loadIrq = (_cpus[i].loadIrq / coreTick) * 100;
2172
+ cores[i].loadSteal = (_cpus[i].loadSteal / coreTick) * 100;
2173
+ cores[i].loadGuest = (_cpus[i].loadGuest / coreTick) * 100;
2166
2174
  cores[i].rawLoad = _cpus[i].load;
2167
2175
  cores[i].rawLoadUser = _cpus[i].loadUser;
2168
2176
  cores[i].rawLoadSystem = _cpus[i].loadSystem;
package/lib/docker.js CHANGED
@@ -19,9 +19,8 @@ const DockerSocket = require('./dockerSocket');
19
19
  const _platform = process.platform;
20
20
  const _windows = _platform === 'win32';
21
21
 
22
- const _docker_container_stats = {};
22
+ const _docker_cpu_last_read = {};
23
23
  let _docker_socket;
24
- let _docker_last_read = 0;
25
24
 
26
25
  // --------------------------
27
26
  // get containers (parameter all: get also inactive/exited containers)
@@ -123,7 +122,9 @@ function dockerImages(all, callback) {
123
122
  if (element.Names && Object.prototype.toString.call(element.Names) === '[object Array]' && element.Names.length > 0) {
124
123
  element.Name = element.Names[0].replace(/^\/|\/$/g, '');
125
124
  }
126
- workload.push(dockerImagesInspect(element.Id.trim(), element));
125
+ if (element.Id && typeof element.Id === 'string') {
126
+ workload.push(dockerImagesInspect(element.Id.trim(), element));
127
+ }
127
128
  });
128
129
  if (workload.length) {
129
130
  Promise.all(workload).then((data) => {
@@ -165,13 +166,13 @@ function dockerImagesInspect(imageID, payload) {
165
166
  if (typeof imageID !== 'string') {
166
167
  return resolve();
167
168
  }
168
- const imageIDSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(imageID, true)).trim();
169
+ const imageIDSanitized = util.isPrototypePolluted() ? '' : util.sanitizeImageID(imageID);
169
170
  if (imageIDSanitized) {
170
171
  if (!_docker_socket) {
171
172
  _docker_socket = new DockerSocket();
172
173
  }
173
174
 
174
- _docker_socket.inspectImage(imageIDSanitized.trim(), (data) => {
175
+ _docker_socket.inspectImage(imageIDSanitized, (data) => {
175
176
  try {
176
177
  resolve({
177
178
  id: payload.Id,
@@ -188,8 +189,8 @@ function dockerImagesInspect(imageID, payload) {
188
189
  created: data.Created ? Math.round(new Date(data.Created).getTime() / 1000) : 0,
189
190
  containerConfig: data.ContainerConfig ? data.ContainerConfig : {},
190
191
  graphDriver: data.GraphDriver ? data.GraphDriver : {},
191
- repoDigests: data.RepoDigests ? data.RepoDigests : {},
192
- repoTags: data.RepoTags ? data.RepoTags : {},
192
+ repoDigests: data.RepoDigests ? data.RepoDigests : [],
193
+ repoTags: data.RepoTags ? data.RepoTags : [],
193
194
  config: data.Config ? data.Config : {},
194
195
  rootFS: data.RootFS ? data.RootFS : {}
195
196
  });
@@ -208,14 +209,7 @@ exports.dockerImages = dockerImages;
208
209
 
209
210
  function dockerContainers(all, callback) {
210
211
  function inContainers(containers, id) {
211
- const filtered = containers.filter((obj) => {
212
- /**
213
- * @namespace
214
- * @property {string} Id
215
- */
216
- return obj.Id && obj.Id === id;
217
- });
218
- return filtered.length > 0;
212
+ return containers.some((obj) => obj.Id && obj.Id.indexOf(id) === 0);
219
213
  }
220
214
 
221
215
  // fallback - if only callback is given
@@ -244,11 +238,11 @@ function dockerContainers(all, callback) {
244
238
  try {
245
239
  docker_containers = data;
246
240
  if (docker_containers && Object.prototype.toString.call(docker_containers) === '[object Array]' && docker_containers.length > 0) {
247
- // GC in _docker_container_stats
248
- for (let key in _docker_container_stats) {
249
- if ({}.hasOwnProperty.call(_docker_container_stats, key)) {
241
+ // GC in _docker_cpu_last_read
242
+ for (let key in _docker_cpu_last_read) {
243
+ if ({}.hasOwnProperty.call(_docker_cpu_last_read, key)) {
250
244
  if (!inContainers(docker_containers, key)) {
251
- delete _docker_container_stats[key];
245
+ delete _docker_cpu_last_read[key];
252
246
  }
253
247
  }
254
248
  }
@@ -257,7 +251,9 @@ function dockerContainers(all, callback) {
257
251
  if (element.Names && Object.prototype.toString.call(element.Names) === '[object Array]' && element.Names.length > 0) {
258
252
  element.Name = element.Names[0].replace(/^\/|\/$/g, '');
259
253
  }
260
- workload.push(dockerContainerInspect(element.Id.trim(), element));
254
+ if (element.Id && typeof element.Id === 'string') {
255
+ workload.push(dockerContainerInspect(element.Id.trim(), element));
256
+ }
261
257
  });
262
258
  if (workload.length) {
263
259
  Promise.all(workload).then((data) => {
@@ -279,14 +275,6 @@ function dockerContainers(all, callback) {
279
275
  resolve(result);
280
276
  }
281
277
  } catch (err) {
282
- // GC in _docker_container_stats
283
- for (let key in _docker_container_stats) {
284
- if ({}.hasOwnProperty.call(_docker_container_stats, key)) {
285
- if (!inContainers(docker_containers, key)) {
286
- delete _docker_container_stats[key];
287
- }
288
- }
289
- }
290
278
  if (callback) {
291
279
  callback(result);
292
280
  }
@@ -307,13 +295,13 @@ function dockerContainerInspect(containerID, payload) {
307
295
  if (typeof containerID !== 'string') {
308
296
  return resolve();
309
297
  }
310
- const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
298
+ const containerIdSanitized = util.isPrototypePolluted() ? '' : util.sanitizeContainerID(containerID);
311
299
  if (containerIdSanitized) {
312
300
  if (!_docker_socket) {
313
301
  _docker_socket = new DockerSocket();
314
302
  }
315
303
 
316
- _docker_socket.getInspect(containerIdSanitized.trim(), (data) => {
304
+ _docker_socket.getInspect(containerIdSanitized, (data) => {
317
305
  try {
318
306
  resolve({
319
307
  id: payload.Id,
@@ -331,6 +319,7 @@ function dockerContainerInspect(containerID, payload) {
331
319
  restartCount: data.RestartCount || 0,
332
320
  platform: data.Platform || '',
333
321
  driver: data.Driver || '',
322
+ labels: data.Config && data.Config.Labels ? data.Config.Labels : {},
334
323
  ports: payload.Ports,
335
324
  mounts: payload.Mounts
336
325
  // hostconfig: payload.HostConfig,
@@ -352,7 +341,7 @@ exports.dockerContainers = dockerContainers;
352
341
  // --------------------------
353
342
  // helper functions for calculation of docker stats
354
343
 
355
- function docker_calcCPUPercent(cpu_stats, precpu_stats) {
344
+ function docker_calcCPUPercent(cpu_stats, precpu_stats, id) {
356
345
  /**
357
346
  * @namespace
358
347
  * @property {object} cpu_usage
@@ -361,42 +350,47 @@ function docker_calcCPUPercent(cpu_stats, precpu_stats) {
361
350
  * @property {object} cpu_usage
362
351
  * @property {Array} cpu_usage.percpu_usage
363
352
  */
353
+ if (!cpu_stats || !cpu_stats.cpu_usage || !precpu_stats) {
354
+ return 0;
355
+ }
356
+ const precpuTotal = precpu_stats.cpu_usage && precpu_stats.cpu_usage.total_usage ? precpu_stats.cpu_usage.total_usage : 0;
364
357
 
365
358
  if (!_windows) {
366
359
  let cpuPercent = 0.0;
367
360
  // calculate the change for the cpu usage of the container in between readings
368
- let cpuDelta = cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage;
361
+ const cpuDelta = cpu_stats.cpu_usage.total_usage - precpuTotal;
369
362
  // calculate the change for the entire system between readings
370
- let systemDelta = cpu_stats.system_cpu_usage - precpu_stats.system_cpu_usage;
363
+ const systemDelta = cpu_stats.system_cpu_usage - (precpu_stats.system_cpu_usage || 0);
371
364
 
372
365
  if (systemDelta > 0.0 && cpuDelta > 0.0) {
373
366
  // calculate the change for the cpu usage of the container in between readings
374
367
  if (precpu_stats.online_cpus) {
375
368
  cpuPercent = (cpuDelta / systemDelta) * precpu_stats.online_cpus * 100.0;
376
- } else {
369
+ } else if (cpu_stats.cpu_usage.percpu_usage && cpu_stats.cpu_usage.percpu_usage.length) {
377
370
  cpuPercent = (cpuDelta / systemDelta) * cpu_stats.cpu_usage.percpu_usage.length * 100.0;
378
371
  }
379
372
  }
380
373
 
381
374
  return cpuPercent;
382
375
  } else {
383
- let nanoSecNow = util.nanoSeconds();
376
+ const nanoSecNow = util.nanoSeconds();
384
377
  let cpuPercent = 0.0;
385
- if (_docker_last_read > 0) {
386
- let possIntervals = nanoSecNow - _docker_last_read; // / 100 * os.cpus().length;
387
- let intervalsUsed = cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage;
378
+ const lastRead = _docker_cpu_last_read[id] || 0;
379
+ if (lastRead > 0) {
380
+ const possIntervals = nanoSecNow - lastRead;
381
+ const intervalsUsed = cpu_stats.cpu_usage.total_usage - precpuTotal;
388
382
  if (possIntervals > 0) {
389
383
  cpuPercent = (100.0 * intervalsUsed) / possIntervals;
390
384
  }
391
385
  }
392
- _docker_last_read = nanoSecNow;
386
+ _docker_cpu_last_read[id] = nanoSecNow;
393
387
  return cpuPercent;
394
388
  }
395
389
  }
396
390
 
397
391
  function docker_calcNetworkIO(networks) {
398
- let rx;
399
- let wx;
392
+ let rx = 0;
393
+ let wx = 0;
400
394
  for (let key in networks) {
401
395
  // skip loop if the property is from prototype
402
396
  if (!{}.hasOwnProperty.call(networks, key)) {
@@ -481,25 +475,16 @@ function dockerContainerStats(containerIDs, callback) {
481
475
  Object.setPrototypeOf(containerIDsSanitized, util.stringObj);
482
476
  }
483
477
 
484
- containerIDsSanitized = containerIDs;
485
- containerIDsSanitized = containerIDsSanitized.trim();
478
+ containerIDsSanitized = containerIDs.trim();
486
479
  if (containerIDsSanitized !== '*') {
487
- containerIDsSanitized = '';
488
- const s = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerIDs, true)).trim();
489
- const l = util.mathMin(s.length, 2000);
490
- for (let i = 0; i <= l; i++) {
491
- if (s[i] !== undefined) {
492
- s[i].__proto__.toLowerCase = util.stringToLower;
493
- const sl = s[i].toLowerCase();
494
- if (sl && sl[0] && !sl[1]) {
495
- containerIDsSanitized = containerIDsSanitized + sl[0];
496
- }
497
- }
498
- }
480
+ containerIDsSanitized = util.isPrototypePolluted() ? '' : util.sanitizeContainerID(containerIDs);
499
481
  }
500
-
501
- containerIDsSanitized = containerIDsSanitized.trim().toLowerCase().replace(/,+/g, '|');
502
- containerArray = containerIDsSanitized.split('|');
482
+ containerArray = containerIDsSanitized
483
+ .trim()
484
+ .toLowerCase()
485
+ .replace(/,+/g, '|')
486
+ .split('|')
487
+ .filter((item) => item.trim());
503
488
  }
504
489
 
505
490
  const result = [];
@@ -508,8 +493,10 @@ function dockerContainerStats(containerIDs, callback) {
508
493
  if (containerArray.length && containerArray[0].trim() === '*') {
509
494
  containerArray = [];
510
495
  dockerContainers().then((allContainers) => {
511
- for (let container of allContainers) {
512
- containerArray.push(container.id.substring(0, 12));
496
+ for (let container of (allContainers || []).filter(Boolean)) {
497
+ if (container.id) {
498
+ containerArray.push(container.id.substring(0, 12));
499
+ }
513
500
  }
514
501
  if (containerArray.length) {
515
502
  dockerContainerStats(containerArray.join(',')).then((result) => {
@@ -592,7 +579,7 @@ function dockerContainerStatsSingle(containerID) {
592
579
  result.memUsage = stats.memory_stats && stats.memory_stats.usage ? stats.memory_stats.usage : 0;
593
580
  result.memLimit = stats.memory_stats && stats.memory_stats.limit ? stats.memory_stats.limit : 0;
594
581
  result.memPercent = stats.memory_stats && stats.memory_stats.usage && stats.memory_stats.limit ? (stats.memory_stats.usage / stats.memory_stats.limit) * 100.0 : 0;
595
- result.cpuPercent = stats.cpu_stats && stats.precpu_stats ? docker_calcCPUPercent(stats.cpu_stats, stats.precpu_stats) : 0;
582
+ result.cpuPercent = stats.cpu_stats && stats.precpu_stats ? docker_calcCPUPercent(stats.cpu_stats, stats.precpu_stats, containerID) : 0;
596
583
  result.pids = stats.pids_stats && stats.pids_stats.current ? stats.pids_stats.current : 0;
597
584
  result.restartCount = dataInspect.RestartCount ? dataInspect.RestartCount : 0;
598
585
  if (stats.networks) {
@@ -636,7 +623,7 @@ function dockerContainerProcesses(containerID, callback) {
636
623
  if (typeof containerID !== 'string') {
637
624
  return resolve(result);
638
625
  }
639
- const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
626
+ const containerIdSanitized = util.isPrototypePolluted() ? '' : util.sanitizeContainerID(containerID);
640
627
 
641
628
  if (containerIdSanitized) {
642
629
  if (!_docker_socket) {