@@ -29,49 +29,43 @@ interface OsCgroupMetricsCollectorOptions {
2929}
3030
3131export class OsCgroupMetricsCollector implements MetricsCollector < OsCgroupMetrics > {
32- // Used to prevent unnecessary file reads on systems not using cgroups
32+ /** Used to prevent unnecessary file reads on systems not using cgroups. */
3333 private noCgroupPresent = false ;
34+ private cpuPath ?: string ;
35+ private cpuAcctPath ?: string ;
3436
3537 constructor ( private readonly options : OsCgroupMetricsCollectorOptions ) { }
3638
3739 public async collect ( ) : Promise < OsCgroupMetrics > {
38- if ( this . noCgroupPresent ) {
39- return { } ;
40- }
41-
4240 try {
43- const cgroups = await readControlGroups ( ) ;
44- const cpuPath = this . options . cpuPath || cgroups [ GROUP_CPU ] ;
45- const cpuAcctPath = this . options . cpuAcctPath || cgroups [ GROUP_CPUACCT ] ;
46-
47- // prevents undefined cgroup paths
48- if ( ! cpuPath || ! cpuAcctPath ) {
49- this . noCgroupPresent = true ;
41+ await this . initializePaths ( ) ;
42+ if ( this . noCgroupPresent || ! this . cpuAcctPath || ! this . cpuPath ) {
5043 return { } ;
5144 }
5245
5346 const [ cpuAcctUsage , cpuFsPeriod , cpuFsQuota , cpuStat ] = await Promise . all ( [
54- readCPUAcctUsage ( cpuAcctPath ) ,
55- readCPUFsPeriod ( cpuPath ) ,
56- readCPUFsQuota ( cpuPath ) ,
57- readCPUStat ( cpuPath ) ,
47+ readCPUAcctUsage ( this . cpuAcctPath ) ,
48+ readCPUFsPeriod ( this . cpuPath ) ,
49+ readCPUFsQuota ( this . cpuPath ) ,
50+ readCPUStat ( this . cpuPath ) ,
5851 ] ) ;
5952
6053 return {
6154 cpuacct : {
62- control_group : cpuAcctPath ,
55+ control_group : this . cpuAcctPath ,
6356 usage_nanos : cpuAcctUsage ,
6457 } ,
6558
6659 cpu : {
67- control_group : cpuPath ,
60+ control_group : this . cpuPath ,
6861 cfs_period_micros : cpuFsPeriod ,
6962 cfs_quota_micros : cpuFsQuota ,
7063 stat : cpuStat ,
7164 } ,
7265 } ;
7366 } catch ( err ) {
7467 if ( err . code === 'ENOENT' ) {
68+ this . noCgroupPresent = true ;
7569 return { } ;
7670 } else {
7771 throw err ;
@@ -80,6 +74,29 @@ export class OsCgroupMetricsCollector implements MetricsCollector<OsCgroupMetric
8074 }
8175
8276 public reset ( ) { }
77+
78+ private async initializePaths ( ) {
79+ // Perform this setup lazily on the first collect call and then memoize the results.
80+ // Makes the assumption this data doesn't change while the process is running.
81+ if ( this . cpuPath && this . cpuAcctPath ) {
82+ return ;
83+ }
84+
85+ // Only read the file if both options are undefined.
86+ if ( ! this . options . cpuPath || ! this . options . cpuAcctPath ) {
87+ const cgroups = await readControlGroups ( ) ;
88+ this . cpuPath = this . options . cpuPath || cgroups [ GROUP_CPU ] ;
89+ this . cpuAcctPath = this . options . cpuAcctPath || cgroups [ GROUP_CPUACCT ] ;
90+ } else {
91+ this . cpuPath = this . options . cpuPath ;
92+ this . cpuAcctPath = this . options . cpuAcctPath ;
93+ }
94+
95+ // prevents undefined cgroup paths
96+ if ( ! this . cpuPath || ! this . cpuAcctPath ) {
97+ this . noCgroupPresent = true ;
98+ }
99+ }
83100}
84101
85102const CONTROL_GROUP_RE = new RegExp ( '\\d+:([^:]+):(/.*)' ) ;
0 commit comments