@@ -79,6 +79,72 @@ describe('LifecycleMetrics', () => {
7979 } ) ) ;
8080 } ) ;
8181
82+ it ( 'should catch errors in onConductorFullScan' , ( ) => {
83+ const metric = ZenkoMetrics . getMetric ( 's3_lifecycle_conductor_full_scan_elapsed_seconds' ) ;
84+ sinon . stub ( metric , 'set' ) . throws ( new Error ( 'Metric error' ) ) ;
85+
86+ LifecycleMetrics . onConductorFullScan ( log , 5000 , 10 , 8 , 5 ) ;
87+
88+ assert ( log . error . calledOnce ) ;
89+ assert ( log . error . calledWithMatch ( 'failed to update prometheus metrics' , {
90+ method : 'LifecycleMetrics.onConductorFullScan' ,
91+ elapsedMs : 5000 ,
92+ bucketCount : 10 ,
93+ workflowCount : 8 ,
94+ lifecycleBucketCount : 5 ,
95+ } ) ) ;
96+ } ) ;
97+
98+ it ( 'should set and reset bucket processor scan gauges' , ( ) => {
99+ const scanStartMetric = ZenkoMetrics . getMetric (
100+ 's3_lifecycle_bucket_processor_scan_start_time' ) ;
101+ const bucketsMetric = ZenkoMetrics . getMetric (
102+ 's3_lifecycle_bucket_processor_buckets_count' ) ;
103+ const startSet = sinon . stub ( scanStartMetric , 'set' ) ;
104+ const bucketsSet = sinon . stub ( bucketsMetric , 'set' ) ;
105+ const bucketsInc = sinon . stub ( bucketsMetric , 'inc' ) ;
106+
107+ // start a scan
108+ LifecycleMetrics . onBucketProcessorScanStart (
109+ log , 1706000000000 ) ;
110+ assert ( startSet . calledOnce ) ;
111+ assert ( startSet . calledWithMatch (
112+ { origin : 'bucket_processor' } , 1706000000000 ) ) ;
113+ assert ( bucketsSet . calledOnce ) ;
114+ assert ( bucketsSet . calledWithMatch (
115+ { origin : 'bucket_processor' } , 0 ) ) ;
116+
117+ // process a bucket
118+ LifecycleMetrics . onBucketProcessorBucketDone ( log ) ;
119+ assert ( bucketsInc . calledOnce ) ;
120+
121+ // end the scan
122+ startSet . resetHistory ( ) ;
123+ LifecycleMetrics . onBucketProcessorScanEnd ( log ) ;
124+ assert ( startSet . calledOnce ) ;
125+ assert ( startSet . calledWithMatch (
126+ { origin : 'bucket_processor' } , 0 ) ) ;
127+
128+ assert ( log . error . notCalled ) ;
129+ } ) ;
130+
131+ it ( 'should catch errors in onBucketProcessorScanStart' , ( ) => {
132+ const scanStartMetric = ZenkoMetrics . getMetric (
133+ 's3_lifecycle_bucket_processor_scan_start_time' ) ;
134+ sinon . stub ( scanStartMetric , 'set' )
135+ . throws ( new Error ( 'Metric error' ) ) ;
136+
137+ LifecycleMetrics . onBucketProcessorScanStart (
138+ log , 1706000000000 ) ;
139+
140+ assert ( log . error . calledOnce ) ;
141+ assert ( log . error . calledWithMatch (
142+ 'failed to update prometheus metrics' , {
143+ method :
144+ 'LifecycleMetrics.onBucketProcessorScanStart' ,
145+ } ) ) ;
146+ } ) ;
147+
82148 it ( 'should catch errors in onLifecycleTriggered' , ( ) => {
83149 LifecycleMetrics . onLifecycleTriggered ( log , 'conductor' , 'expiration' , 'us-east-1' , NaN ) ;
84150
@@ -169,5 +235,28 @@ describe('LifecycleMetrics', () => {
169235 process : 'conductor' ,
170236 } ) ) ;
171237 } ) ;
238+
239+ it ( 'should set full scan metrics including lifecycle bucket count' , ( ) => {
240+ const elapsedMetric = ZenkoMetrics . getMetric (
241+ 's3_lifecycle_conductor_full_scan_elapsed_seconds' ) ;
242+ const countMetric = ZenkoMetrics . getMetric (
243+ 's3_lifecycle_conductor_scan_count' ) ;
244+ const elapsedSet = sinon . stub ( elapsedMetric , 'set' ) ;
245+ const countSet = sinon . stub ( countMetric , 'set' ) ;
246+
247+ LifecycleMetrics . onConductorFullScan ( log , 3000 , 7 , 6 , 4 ) ;
248+
249+ assert ( elapsedSet . calledOnce ) ;
250+ assert ( elapsedSet . calledWithMatch (
251+ { origin : 'conductor' } , 3 ) ) ;
252+ assert . strictEqual ( countSet . callCount , 3 ) ;
253+ assert ( countSet . getCall ( 0 ) . calledWithMatch (
254+ { origin : 'conductor' , type : 'bucket' } , 7 ) ) ;
255+ assert ( countSet . getCall ( 1 ) . calledWithMatch (
256+ { origin : 'conductor' , type : 'lifecycle_bucket' } , 4 ) ) ;
257+ assert ( countSet . getCall ( 2 ) . calledWithMatch (
258+ { origin : 'conductor' , type : 'workflow' } , 6 ) ) ;
259+ assert ( log . error . notCalled ) ;
260+ } ) ;
172261 } ) ;
173262} ) ;
0 commit comments