LCOV - code coverage report
Current view: top level - pageserver/src/consumption_metrics/metrics - tests.rs (source / functions) Coverage Total Hit
Test: 1e20c4f2b28aa592527961bb32170ebbd2c9172f.info Lines: 100.0 % 436 436
Test Date: 2025-07-16 12:29:03 Functions: 100.0 % 20 20

            Line data    Source code
       1              : use std::collections::HashMap;
       2              : 
       3              : use super::*;
       4              : use crate::consumption_metrics::RawMetric;
       5              : 
       6              : #[test]
       7            1 : fn startup_collected_timeline_metrics_before_advancing() {
       8            1 :     let tenant_id = TenantId::generate();
       9            1 :     let timeline_id = TimelineId::generate();
      10              : 
      11            1 :     let mut metrics = Vec::new();
      12            1 :     let cache = HashMap::new();
      13              : 
      14            1 :     let initdb_lsn = Lsn(0x10000);
      15            1 :     let pitr_cutoff = Lsn(0x11000);
      16            1 :     let disk_consistent_lsn = Lsn(initdb_lsn.0 * 2);
      17            1 :     let logical_size = 0x42000;
      18              : 
      19            1 :     let snap = TimelineSnapshot {
      20            1 :         loaded_at: (disk_consistent_lsn, SystemTime::now()),
      21            1 :         last_record_lsn: disk_consistent_lsn,
      22            1 :         ancestor_lsn: Lsn(0),
      23            1 :         current_exact_logical_size: Some(logical_size),
      24            1 :         pitr_enabled: true,
      25            1 :         pitr_cutoff: Some(pitr_cutoff),
      26            1 :     };
      27              : 
      28            1 :     let now = DateTime::<Utc>::from(SystemTime::now());
      29              : 
      30            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
      31              : 
      32            1 :     assert_eq!(
      33              :         metrics,
      34            1 :         &[
      35            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(
      36            1 :                 snap.loaded_at.1.into(),
      37            1 :                 now,
      38            1 :                 0
      39            1 :             ),
      40            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(now, disk_consistent_lsn.0),
      41            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id)
      42            1 :                 .at(now, disk_consistent_lsn.0),
      43            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id)
      44            1 :                 .at(now, disk_consistent_lsn.0 - pitr_cutoff.0),
      45            1 :             MetricsKey::timeline_logical_size(tenant_id, timeline_id).at(now, logical_size)
      46            1 :         ]
      47              :     );
      48            1 : }
      49              : 
      50              : #[test]
      51            1 : fn startup_collected_timeline_metrics_second_round() {
      52            1 :     let tenant_id = TenantId::generate();
      53            1 :     let timeline_id = TimelineId::generate();
      54              : 
      55            1 :     let [now, before, init] = time_backwards();
      56              : 
      57            1 :     let now = DateTime::<Utc>::from(now);
      58            1 :     let before = DateTime::<Utc>::from(before);
      59              : 
      60            1 :     let initdb_lsn = Lsn(0x10000);
      61            1 :     let pitr_cutoff = Lsn(0x11000);
      62            1 :     let disk_consistent_lsn = Lsn(initdb_lsn.0 * 2);
      63            1 :     let logical_size = 0x42000;
      64              : 
      65            1 :     let mut metrics = Vec::new();
      66            1 :     let cache = HashMap::from([MetricsKey::written_size(tenant_id, timeline_id)
      67            1 :         .at(before, disk_consistent_lsn.0)
      68            1 :         .to_kv_pair()]);
      69              : 
      70            1 :     let snap = TimelineSnapshot {
      71            1 :         loaded_at: (disk_consistent_lsn, init),
      72            1 :         last_record_lsn: disk_consistent_lsn,
      73            1 :         ancestor_lsn: Lsn(0),
      74            1 :         current_exact_logical_size: Some(logical_size),
      75            1 :         pitr_enabled: true,
      76            1 :         pitr_cutoff: Some(pitr_cutoff),
      77            1 :     };
      78              : 
      79            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
      80              : 
      81            1 :     assert_eq!(
      82              :         metrics,
      83            1 :         &[
      84            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(before, now, 0),
      85            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(now, disk_consistent_lsn.0),
      86            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id)
      87            1 :                 .at(now, disk_consistent_lsn.0),
      88            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id)
      89            1 :                 .at(now, disk_consistent_lsn.0 - pitr_cutoff.0),
      90            1 :             MetricsKey::timeline_logical_size(tenant_id, timeline_id).at(now, logical_size)
      91            1 :         ]
      92              :     );
      93            1 : }
      94              : 
      95              : #[test]
      96            1 : fn startup_collected_timeline_metrics_nth_round_at_same_lsn() {
      97            1 :     let tenant_id = TenantId::generate();
      98            1 :     let timeline_id = TimelineId::generate();
      99              : 
     100            1 :     let [now, just_before, before, init] = time_backwards();
     101              : 
     102            1 :     let now = DateTime::<Utc>::from(now);
     103            1 :     let just_before = DateTime::<Utc>::from(just_before);
     104            1 :     let before = DateTime::<Utc>::from(before);
     105              : 
     106            1 :     let initdb_lsn = Lsn(0x10000);
     107            1 :     let pitr_cutoff = Lsn(0x11000);
     108            1 :     let disk_consistent_lsn = Lsn(initdb_lsn.0 * 2);
     109            1 :     let logical_size = 0x42000;
     110              : 
     111            1 :     let mut metrics = Vec::new();
     112            1 :     let cache = HashMap::from([
     113            1 :         // at t=before was the last time the last_record_lsn changed
     114            1 :         MetricsKey::written_size(tenant_id, timeline_id)
     115            1 :             .at(before, disk_consistent_lsn.0)
     116            1 :             .to_kv_pair(),
     117            1 :         // end time of this event is used for the next ones
     118            1 :         MetricsKey::written_size_delta(tenant_id, timeline_id)
     119            1 :             .from_until(before, just_before, 0)
     120            1 :             .to_kv_pair(),
     121            1 :     ]);
     122              : 
     123            1 :     let snap = TimelineSnapshot {
     124            1 :         loaded_at: (disk_consistent_lsn, init),
     125            1 :         last_record_lsn: disk_consistent_lsn,
     126            1 :         ancestor_lsn: Lsn(0),
     127            1 :         current_exact_logical_size: Some(logical_size),
     128            1 :         pitr_enabled: true,
     129            1 :         pitr_cutoff: Some(pitr_cutoff),
     130            1 :     };
     131              : 
     132            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
     133              : 
     134            1 :     assert_eq!(
     135              :         metrics,
     136            1 :         &[
     137            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(just_before, now, 0),
     138            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(now, disk_consistent_lsn.0),
     139            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id)
     140            1 :                 .at(now, disk_consistent_lsn.0),
     141            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id)
     142            1 :                 .at(now, disk_consistent_lsn.0 - pitr_cutoff.0),
     143            1 :             MetricsKey::timeline_logical_size(tenant_id, timeline_id).at(now, logical_size)
     144            1 :         ]
     145              :     );
     146            1 : }
     147              : 
     148              : /// Tests that written sizes do not regress across restarts.
     149              : #[test]
     150            1 : fn post_restart_written_sizes_with_rolled_back_last_record_lsn() {
     151            1 :     let tenant_id = TenantId::generate();
     152            1 :     let timeline_id = TimelineId::generate();
     153              : 
     154            1 :     let [later, now, at_restart] = time_backwards();
     155              : 
     156              :     // FIXME: tests would be so much easier if we did not need to juggle back and forth
     157              :     // SystemTime and DateTime::<Utc> ... Could do the conversion only at upload time?
     158            1 :     let now = DateTime::<Utc>::from(now);
     159            1 :     let later = DateTime::<Utc>::from(later);
     160            1 :     let before_restart = at_restart - std::time::Duration::from_secs(5 * 60);
     161            1 :     let way_before = before_restart - std::time::Duration::from_secs(10 * 60);
     162            1 :     let before_restart = DateTime::<Utc>::from(before_restart);
     163            1 :     let way_before = DateTime::<Utc>::from(way_before);
     164              : 
     165            1 :     let snap = TimelineSnapshot {
     166            1 :         loaded_at: (Lsn(50), at_restart),
     167            1 :         last_record_lsn: Lsn(50),
     168            1 :         ancestor_lsn: Lsn(0),
     169            1 :         current_exact_logical_size: None,
     170            1 :         pitr_enabled: true,
     171            1 :         pitr_cutoff: Some(Lsn(20)),
     172            1 :     };
     173              : 
     174            1 :     let mut cache = HashMap::from([
     175            1 :         MetricsKey::written_size(tenant_id, timeline_id)
     176            1 :             .at(before_restart, 100)
     177            1 :             .to_kv_pair(),
     178            1 :         MetricsKey::written_size_delta(tenant_id, timeline_id)
     179            1 :             .from_until(
     180            1 :                 way_before,
     181            1 :                 before_restart,
     182            1 :                 // not taken into account, but the timestamps are important
     183            1 :                 999_999_999,
     184            1 :             )
     185            1 :             .to_kv_pair(),
     186            1 :     ]);
     187              : 
     188            1 :     let mut metrics = Vec::new();
     189            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
     190              : 
     191            1 :     assert_eq!(
     192              :         metrics,
     193            1 :         &[
     194            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(
     195            1 :                 before_restart,
     196            1 :                 now,
     197            1 :                 0
     198            1 :             ),
     199            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(now, 100),
     200            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id).at(now, 100),
     201            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at(now, 80),
     202            1 :         ]
     203              :     );
     204              : 
     205              :     // now if we cache these metrics, and re-run while "still in recovery"
     206            4 :     cache.extend(metrics.drain(..).map(|x| x.to_kv_pair()));
     207              : 
     208              :     // "still in recovery", because our snapshot did not change
     209            1 :     snap.to_metrics(tenant_id, timeline_id, later, &mut metrics, &cache);
     210              : 
     211            1 :     assert_eq!(
     212              :         metrics,
     213            1 :         &[
     214            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(now, later, 0),
     215            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(later, 100),
     216            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id).at(later, 100),
     217            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at(later, 80),
     218            1 :         ]
     219              :     );
     220            1 : }
     221              : 
     222              : /// Tests that written sizes do not regress across restarts, even on child branches.
     223              : #[test]
     224            1 : fn post_restart_written_sizes_with_rolled_back_last_record_lsn_and_ancestor_lsn() {
     225            1 :     let tenant_id = TenantId::generate();
     226            1 :     let timeline_id = TimelineId::generate();
     227              : 
     228            1 :     let [later, now, at_restart] = time_backwards();
     229              : 
     230              :     // FIXME: tests would be so much easier if we did not need to juggle back and forth
     231              :     // SystemTime and DateTime::<Utc> ... Could do the conversion only at upload time?
     232            1 :     let now = DateTime::<Utc>::from(now);
     233            1 :     let later = DateTime::<Utc>::from(later);
     234            1 :     let before_restart = at_restart - std::time::Duration::from_secs(5 * 60);
     235            1 :     let way_before = before_restart - std::time::Duration::from_secs(10 * 60);
     236            1 :     let before_restart = DateTime::<Utc>::from(before_restart);
     237            1 :     let way_before = DateTime::<Utc>::from(way_before);
     238              : 
     239            1 :     let snap = TimelineSnapshot {
     240            1 :         loaded_at: (Lsn(50), at_restart),
     241            1 :         last_record_lsn: Lsn(50),
     242            1 :         ancestor_lsn: Lsn(40),
     243            1 :         current_exact_logical_size: None,
     244            1 :         pitr_enabled: true,
     245            1 :         pitr_cutoff: Some(Lsn(20)),
     246            1 :     };
     247              : 
     248            1 :     let mut cache = HashMap::from([
     249            1 :         MetricsKey::written_size(tenant_id, timeline_id)
     250            1 :             .at(before_restart, 100)
     251            1 :             .to_kv_pair(),
     252            1 :         MetricsKey::written_size_delta(tenant_id, timeline_id)
     253            1 :             .from_until(
     254            1 :                 way_before,
     255            1 :                 before_restart,
     256            1 :                 // not taken into account, but the timestamps are important
     257            1 :                 999_999_999,
     258            1 :             )
     259            1 :             .to_kv_pair(),
     260            1 :     ]);
     261              : 
     262            1 :     let mut metrics = Vec::new();
     263            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
     264              : 
     265            1 :     assert_eq!(
     266              :         metrics,
     267            1 :         &[
     268            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(
     269            1 :                 before_restart,
     270            1 :                 now,
     271            1 :                 0
     272            1 :             ),
     273            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(now, 100),
     274            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id).at(now, 60),
     275            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at(now, 60),
     276            1 :         ]
     277              :     );
     278              : 
     279              :     // now if we cache these metrics, and re-run while "still in recovery"
     280            4 :     cache.extend(metrics.drain(..).map(|x| x.to_kv_pair()));
     281              : 
     282              :     // "still in recovery", because our snapshot did not change
     283            1 :     snap.to_metrics(tenant_id, timeline_id, later, &mut metrics, &cache);
     284              : 
     285            1 :     assert_eq!(
     286              :         metrics,
     287            1 :         &[
     288            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(now, later, 0),
     289            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(later, 100),
     290            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id).at(later, 60),
     291            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at(later, 60),
     292            1 :         ]
     293              :     );
     294            1 : }
     295              : 
     296              : /// Tests that written sizes do not regress across restarts, even on child branches and
     297              : /// with a PITR cutoff after the branch point.
     298              : #[test]
     299            1 : fn post_restart_written_sizes_with_rolled_back_last_record_lsn_and_ancestor_lsn_and_pitr_cutoff() {
     300            1 :     let tenant_id = TenantId::generate();
     301            1 :     let timeline_id = TimelineId::generate();
     302              : 
     303            1 :     let [later, now, at_restart] = time_backwards();
     304              : 
     305              :     // FIXME: tests would be so much easier if we did not need to juggle back and forth
     306              :     // SystemTime and DateTime::<Utc> ... Could do the conversion only at upload time?
     307            1 :     let now = DateTime::<Utc>::from(now);
     308            1 :     let later = DateTime::<Utc>::from(later);
     309            1 :     let before_restart = at_restart - std::time::Duration::from_secs(5 * 60);
     310            1 :     let way_before = before_restart - std::time::Duration::from_secs(10 * 60);
     311            1 :     let before_restart = DateTime::<Utc>::from(before_restart);
     312            1 :     let way_before = DateTime::<Utc>::from(way_before);
     313              : 
     314            1 :     let snap = TimelineSnapshot {
     315            1 :         loaded_at: (Lsn(50), at_restart),
     316            1 :         last_record_lsn: Lsn(50),
     317            1 :         ancestor_lsn: Lsn(30),
     318            1 :         current_exact_logical_size: None,
     319            1 :         pitr_enabled: true,
     320            1 :         pitr_cutoff: Some(Lsn(40)),
     321            1 :     };
     322              : 
     323            1 :     let mut cache = HashMap::from([
     324            1 :         MetricsKey::written_size(tenant_id, timeline_id)
     325            1 :             .at(before_restart, 100)
     326            1 :             .to_kv_pair(),
     327            1 :         MetricsKey::written_size_delta(tenant_id, timeline_id)
     328            1 :             .from_until(
     329            1 :                 way_before,
     330            1 :                 before_restart,
     331            1 :                 // not taken into account, but the timestamps are important
     332            1 :                 999_999_999,
     333            1 :             )
     334            1 :             .to_kv_pair(),
     335            1 :     ]);
     336              : 
     337            1 :     let mut metrics = Vec::new();
     338            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
     339              : 
     340            1 :     assert_eq!(
     341              :         metrics,
     342            1 :         &[
     343            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(
     344            1 :                 before_restart,
     345            1 :                 now,
     346            1 :                 0
     347            1 :             ),
     348            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(now, 100),
     349            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id).at(now, 70),
     350            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at(now, 60),
     351            1 :         ]
     352              :     );
     353              : 
     354              :     // now if we cache these metrics, and re-run while "still in recovery"
     355            4 :     cache.extend(metrics.drain(..).map(|x| x.to_kv_pair()));
     356              : 
     357              :     // "still in recovery", because our snapshot did not change
     358            1 :     snap.to_metrics(tenant_id, timeline_id, later, &mut metrics, &cache);
     359              : 
     360            1 :     assert_eq!(
     361              :         metrics,
     362            1 :         &[
     363            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(now, later, 0),
     364            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(later, 100),
     365            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id).at(later, 70),
     366            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at(later, 60),
     367            1 :         ]
     368              :     );
     369            1 : }
     370              : 
     371              : #[test]
     372            1 : fn post_restart_current_exact_logical_size_uses_cached() {
     373            1 :     let tenant_id = TenantId::generate();
     374            1 :     let timeline_id = TimelineId::generate();
     375              : 
     376            1 :     let [now, at_restart] = time_backwards();
     377              : 
     378            1 :     let now = DateTime::<Utc>::from(now);
     379            1 :     let before_restart = at_restart - std::time::Duration::from_secs(5 * 60);
     380            1 :     let before_restart = DateTime::<Utc>::from(before_restart);
     381              : 
     382            1 :     let snap = TimelineSnapshot {
     383            1 :         loaded_at: (Lsn(50), at_restart),
     384            1 :         last_record_lsn: Lsn(50),
     385            1 :         ancestor_lsn: Lsn(0),
     386            1 :         current_exact_logical_size: None,
     387            1 :         pitr_enabled: true,
     388            1 :         pitr_cutoff: None,
     389            1 :     };
     390              : 
     391            1 :     let cache = HashMap::from([MetricsKey::timeline_logical_size(tenant_id, timeline_id)
     392            1 :         .at(before_restart, 100)
     393            1 :         .to_kv_pair()]);
     394              : 
     395            1 :     let mut metrics = Vec::new();
     396            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
     397              : 
     398            4 :     metrics.retain(|item| item.key.metric == Name::LogicalSize);
     399              : 
     400            1 :     assert_eq!(
     401              :         metrics,
     402            1 :         &[MetricsKey::timeline_logical_size(tenant_id, timeline_id).at(now, 100)]
     403              :     );
     404            1 : }
     405              : 
     406              : #[test]
     407            1 : fn post_restart_synthetic_size_uses_cached_if_available() {
     408            1 :     let tenant_id = TenantId::generate();
     409              : 
     410            1 :     let ts = TenantSnapshot {
     411            1 :         remote_size: 1000,
     412            1 :         // not yet calculated
     413            1 :         synthetic_size: 0,
     414            1 :     };
     415              : 
     416            1 :     let now = SystemTime::now();
     417            1 :     let before_restart = DateTime::<Utc>::from(now - std::time::Duration::from_secs(5 * 60));
     418            1 :     let now = DateTime::<Utc>::from(now);
     419              : 
     420            1 :     let cached = HashMap::from([MetricsKey::synthetic_size(tenant_id)
     421            1 :         .at(before_restart, 1000)
     422            1 :         .to_kv_pair()]);
     423              : 
     424            1 :     let mut metrics = Vec::new();
     425            1 :     ts.to_metrics(tenant_id, now, &cached, &mut metrics);
     426              : 
     427            1 :     assert_eq!(
     428              :         metrics,
     429            1 :         &[
     430            1 :             MetricsKey::remote_storage_size(tenant_id).at(now, 1000),
     431            1 :             MetricsKey::synthetic_size(tenant_id).at(now, 1000),
     432            1 :         ]
     433              :     );
     434            1 : }
     435              : 
     436              : #[test]
     437            1 : fn post_restart_synthetic_size_is_not_sent_when_not_cached() {
     438            1 :     let tenant_id = TenantId::generate();
     439              : 
     440            1 :     let ts = TenantSnapshot {
     441            1 :         remote_size: 1000,
     442            1 :         // not yet calculated
     443            1 :         synthetic_size: 0,
     444            1 :     };
     445              : 
     446            1 :     let now = SystemTime::now();
     447            1 :     let now = DateTime::<Utc>::from(now);
     448              : 
     449            1 :     let cached = HashMap::new();
     450              : 
     451            1 :     let mut metrics = Vec::new();
     452            1 :     ts.to_metrics(tenant_id, now, &cached, &mut metrics);
     453              : 
     454            1 :     assert_eq!(
     455              :         metrics,
     456            1 :         &[
     457            1 :             MetricsKey::remote_storage_size(tenant_id).at(now, 1000),
     458            1 :             // no synthetic size here
     459            1 :         ]
     460              :     );
     461            1 : }
     462              : 
     463            6 : fn time_backwards<const N: usize>() -> [std::time::SystemTime; N] {
     464            6 :     let mut times = [std::time::SystemTime::UNIX_EPOCH; N];
     465            6 :     times[0] = std::time::SystemTime::now();
     466           18 :     for behind in 1..N {
     467           12 :         times[behind] = times[0] - std::time::Duration::from_secs(behind as u64);
     468           12 :     }
     469              : 
     470            6 :     times
     471            6 : }
     472              : 
     473              : /// Tests that disabled PITR history does not yield any history size, even when the PITR cutoff
     474              : /// indicates otherwise.
     475              : #[test]
     476            1 : fn pitr_disabled_yields_no_history_size() {
     477            1 :     let tenant_id = TenantId::generate();
     478            1 :     let timeline_id = TimelineId::generate();
     479              : 
     480            1 :     let mut metrics = Vec::new();
     481            1 :     let cache = HashMap::new();
     482              : 
     483            1 :     let initdb_lsn = Lsn(0x10000);
     484            1 :     let pitr_cutoff = Lsn(0x11000);
     485            1 :     let disk_consistent_lsn = Lsn(initdb_lsn.0 * 2);
     486              : 
     487            1 :     let snap = TimelineSnapshot {
     488            1 :         loaded_at: (disk_consistent_lsn, SystemTime::now()),
     489            1 :         last_record_lsn: disk_consistent_lsn,
     490            1 :         ancestor_lsn: Lsn(0),
     491            1 :         current_exact_logical_size: None,
     492            1 :         pitr_enabled: false,
     493            1 :         pitr_cutoff: Some(pitr_cutoff),
     494            1 :     };
     495              : 
     496            1 :     let now = DateTime::<Utc>::from(SystemTime::now());
     497              : 
     498            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
     499              : 
     500            1 :     assert_eq!(
     501              :         metrics,
     502            1 :         &[
     503            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(
     504            1 :                 snap.loaded_at.1.into(),
     505            1 :                 now,
     506            1 :                 0
     507            1 :             ),
     508            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(now, disk_consistent_lsn.0),
     509            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id)
     510            1 :                 .at(now, disk_consistent_lsn.0),
     511            1 :             MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at(now, 0),
     512            1 :         ]
     513              :     );
     514            1 : }
     515              : 
     516              : /// Tests that uninitialized PITR cutoff does not emit any history size metric at all.
     517              : #[test]
     518            1 : fn pitr_uninitialized_does_not_emit_history_size() {
     519            1 :     let tenant_id = TenantId::generate();
     520            1 :     let timeline_id = TimelineId::generate();
     521              : 
     522            1 :     let mut metrics = Vec::new();
     523            1 :     let cache = HashMap::new();
     524              : 
     525            1 :     let initdb_lsn = Lsn(0x10000);
     526            1 :     let disk_consistent_lsn = Lsn(initdb_lsn.0 * 2);
     527              : 
     528            1 :     let snap = TimelineSnapshot {
     529            1 :         loaded_at: (disk_consistent_lsn, SystemTime::now()),
     530            1 :         last_record_lsn: disk_consistent_lsn,
     531            1 :         ancestor_lsn: Lsn(0),
     532            1 :         current_exact_logical_size: None,
     533            1 :         pitr_enabled: true,
     534            1 :         pitr_cutoff: None,
     535            1 :     };
     536              : 
     537            1 :     let now = DateTime::<Utc>::from(SystemTime::now());
     538              : 
     539            1 :     snap.to_metrics(tenant_id, timeline_id, now, &mut metrics, &cache);
     540              : 
     541            1 :     assert_eq!(
     542              :         metrics,
     543            1 :         &[
     544            1 :             MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(
     545            1 :                 snap.loaded_at.1.into(),
     546            1 :                 now,
     547            1 :                 0
     548            1 :             ),
     549            1 :             MetricsKey::written_size(tenant_id, timeline_id).at(now, disk_consistent_lsn.0),
     550            1 :             MetricsKey::written_size_since_parent(tenant_id, timeline_id)
     551            1 :                 .at(now, disk_consistent_lsn.0),
     552            1 :         ]
     553              :     );
     554            1 : }
     555              : 
     556            1 : pub(crate) const fn metric_examples_old(
     557            1 :     tenant_id: TenantId,
     558            1 :     timeline_id: TimelineId,
     559            1 :     now: DateTime<Utc>,
     560            1 :     before: DateTime<Utc>,
     561            1 : ) -> [RawMetric; 7] {
     562            1 :     [
     563            1 :         MetricsKey::written_size(tenant_id, timeline_id).at_old_format(now, 0),
     564            1 :         MetricsKey::written_size_delta(tenant_id, timeline_id)
     565            1 :             .from_until_old_format(before, now, 0),
     566            1 :         MetricsKey::written_size_since_parent(tenant_id, timeline_id).at_old_format(now, 0),
     567            1 :         MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at_old_format(now, 0),
     568            1 :         MetricsKey::timeline_logical_size(tenant_id, timeline_id).at_old_format(now, 0),
     569            1 :         MetricsKey::remote_storage_size(tenant_id).at_old_format(now, 0),
     570            1 :         MetricsKey::synthetic_size(tenant_id).at_old_format(now, 1),
     571            1 :     ]
     572            1 : }
     573              : 
     574            4 : pub(crate) const fn metric_examples(
     575            4 :     tenant_id: TenantId,
     576            4 :     timeline_id: TimelineId,
     577            4 :     now: DateTime<Utc>,
     578            4 :     before: DateTime<Utc>,
     579            4 : ) -> [NewRawMetric; 7] {
     580            4 :     [
     581            4 :         MetricsKey::written_size(tenant_id, timeline_id).at(now, 0),
     582            4 :         MetricsKey::written_size_delta(tenant_id, timeline_id).from_until(before, now, 0),
     583            4 :         MetricsKey::written_size_since_parent(tenant_id, timeline_id).at(now, 0),
     584            4 :         MetricsKey::pitr_history_size_since_parent(tenant_id, timeline_id).at(now, 0),
     585            4 :         MetricsKey::timeline_logical_size(tenant_id, timeline_id).at(now, 0),
     586            4 :         MetricsKey::remote_storage_size(tenant_id).at(now, 0),
     587            4 :         MetricsKey::synthetic_size(tenant_id).at(now, 1),
     588            4 :     ]
     589            4 : }
        

Generated by: LCOV version 2.1-beta