@@ -6,6 +6,8 @@ import { CcapiService } from '../services/CcapiService';
66import { ISettingsSubscriber , SettingsConfigurable , SettingsSubscription } from '../settings/ISettingsSubscriber' ;
77import { DefaultSettings , ProfileSettings } from '../settings/Settings' ;
88import { LoggerFactory } from '../telemetry/LoggerFactory' ;
9+ import { ScopedTelemetry } from '../telemetry/ScopedTelemetry' ;
10+ import { Telemetry , Measure } from '../telemetry/TelemetryDecorator' ;
911import { Closeable } from '../utils/Closeable' ;
1012import { ListResourcesResult , RefreshResourcesResult } from './ResourceStateTypes' ;
1113
@@ -32,6 +34,7 @@ type ResourceStateMap = Map<ResourceType, Map<ResourceId, ResourceState>>;
3234type ResourceListMap = Map < ResourceType , ResourceList > ;
3335
3436export class ResourceStateManager implements SettingsConfigurable , Closeable {
37+ @Telemetry ( ) private readonly telemetry ! : ScopedTelemetry ;
3538 private settingsSubscription ?: SettingsSubscription ;
3639 private settings : ProfileSettings = DefaultSettings . profile ;
3740 private isRefreshing = false ;
@@ -43,13 +46,20 @@ export class ResourceStateManager implements SettingsConfigurable, Closeable {
4346 constructor (
4447 private readonly ccapiService : CcapiService ,
4548 private readonly schemaRetriever : SchemaRetriever ,
46- ) { }
49+ ) {
50+ this . registerCacheGauges ( ) ;
51+ this . initializeCounters ( ) ;
52+ }
4753
54+ @Measure ( { name : 'getResource' } )
4855 public async getResource ( typeName : ResourceType , identifier : ResourceId ) : Promise < ResourceState | undefined > {
4956 const cachedResources = this . getResourceState ( typeName , identifier ) ;
5057 if ( cachedResources ) {
58+ this . telemetry . count ( 'state.hit' , 1 ) ;
5159 return cachedResources ;
5260 }
61+ this . telemetry . count ( 'state.miss' , 1 ) ;
62+
5363 let output : GetResourceCommandOutput | undefined = undefined ;
5464
5565 try {
@@ -58,6 +68,7 @@ export class ResourceStateManager implements SettingsConfigurable, Closeable {
5868 log . error ( error , `CCAPI GetResource failed for type ${ typeName } and identifier "${ identifier } "` ) ;
5969 if ( error instanceof ResourceNotFoundException ) {
6070 log . info ( `No resource found for type ${ typeName } and identifier "${ identifier } "` ) ;
71+ this . telemetry . count ( 'state.fault' , 1 ) ;
6172 }
6273 return ;
6374 }
@@ -80,6 +91,7 @@ export class ResourceStateManager implements SettingsConfigurable, Closeable {
8091 return value ;
8192 }
8293
94+ @Measure ( { name : 'listResources' } )
8395 public async listResources ( typeName : string , nextToken ?: string ) : Promise < ResourceList | undefined > {
8496 const cached = this . resourceListMap . get ( typeName ) ;
8597
@@ -108,6 +120,7 @@ export class ResourceStateManager implements SettingsConfigurable, Closeable {
108120 return resourceListNextPage ;
109121 }
110122
123+ @Measure ( { name : 'searchResourceByIdentifier' } )
111124 public async searchResourceByIdentifier (
112125 typeName : string ,
113126 identifier : string ,
@@ -184,6 +197,7 @@ export class ResourceStateManager implements SettingsConfigurable, Closeable {
184197 }
185198 }
186199
200+ @Measure ( { name : 'refreshResourceList' } )
187201 public async refreshResourceList ( resourceTypes : string [ ] ) : Promise < RefreshResourcesResult > {
188202 if ( this . isRefreshing ) {
189203 // return cached resource list
@@ -233,6 +247,9 @@ export class ResourceStateManager implements SettingsConfigurable, Closeable {
233247 nextToken : response . nextToken ,
234248 } ) ;
235249 }
250+ if ( anyRefreshFailed ) {
251+ this . telemetry . count ( 'refresh.fault' , 1 ) ;
252+ }
236253 return { ...result , refreshFailed : anyRefreshFailed } ;
237254 } finally {
238255 this . isRefreshing = false ;
@@ -259,12 +276,37 @@ export class ResourceStateManager implements SettingsConfigurable, Closeable {
259276 private onSettingsChanged ( newSettings : ProfileSettings ) {
260277 // clear cached resources if AWS profile or region changes as data is redundant
261278 if ( newSettings . profile !== this . settings . profile || newSettings . region !== this . settings . region ) {
279+ this . telemetry . count ( 'state.invalidated' , 1 ) ;
280+ this . telemetry . count ( 'list.invalidated' , 1 ) ;
262281 this . resourceStateMap . clear ( ) ;
263282 this . resourceListMap . clear ( ) ;
264283 }
265284 this . settings = newSettings ;
266285 }
267286
287+ private initializeCounters ( ) : void {
288+ this . telemetry . count ( 'state.hit' , 0 ) ;
289+ this . telemetry . count ( 'state.miss' , 0 ) ;
290+ this . telemetry . count ( 'state.fault' , 0 ) ;
291+ this . telemetry . count ( 'state.invalidated' , 0 ) ;
292+ this . telemetry . count ( 'list.invalidated' , 0 ) ;
293+ this . telemetry . count ( 'refresh.fault' , 0 ) ;
294+ }
295+
296+ private registerCacheGauges ( ) : void {
297+ this . telemetry . registerGaugeProvider ( 'state.types' , ( ) => this . resourceStateMap . size ) ;
298+
299+ this . telemetry . registerGaugeProvider ( 'list.types' , ( ) => this . resourceListMap . size ) ;
300+
301+ this . telemetry . registerGaugeProvider ( 'state.count' , ( ) => {
302+ let total = 0 ;
303+ for ( const resourceMap of this . resourceStateMap . values ( ) ) {
304+ total += resourceMap . size ;
305+ }
306+ return total ;
307+ } ) ;
308+ }
309+
268310 static create ( external : CfnExternal ) {
269311 return new ResourceStateManager ( external . ccapiService , external . schemaRetriever ) ;
270312 }
0 commit comments