1use crate::error_from_metrics_error;
6use anyhow::Result;
7use attribution_processing::digest::{BucketDefinition, Digest};
8use attribution_processing::AttributionDataProvider;
9use cobalt_client::traits::{AsEventCode, AsEventCodes};
10use futures::stream::StreamExt;
11use futures::{try_join, TryFutureExt};
12use memory_metrics_registry::cobalt_registry;
13use std::collections::HashMap;
14use std::sync::Arc;
15
16use cobalt_registry::MemoryLeakMigratedMetricDimensionTimeSinceBoot as TimeSinceBoot;
17use {fidl_fuchsia_kernel as fkernel, fidl_fuchsia_metrics as fmetrics};
18
19const UPTIME_LEVEL_INDEX: &[(zx::BootDuration, TimeSinceBoot)] = &[
21 (zx::BootDuration::from_minutes(1), TimeSinceBoot::Up),
22 (zx::BootDuration::from_minutes(30), TimeSinceBoot::UpOneMinute),
23 (zx::BootDuration::from_hours(1), TimeSinceBoot::UpThirtyMinutes),
24 (zx::BootDuration::from_hours(6), TimeSinceBoot::UpOneHour),
25 (zx::BootDuration::from_hours(12), TimeSinceBoot::UpSixHours),
26 (zx::BootDuration::from_hours(24), TimeSinceBoot::UpTwelveHours),
27 (zx::BootDuration::from_hours(48), TimeSinceBoot::UpOneDay),
28 (zx::BootDuration::from_hours(72), TimeSinceBoot::UpTwoDays),
29 (zx::BootDuration::from_hours(144), TimeSinceBoot::UpThreeDays),
30];
31
32fn get_uptime_event_code(capture_time: zx::BootInstant) -> TimeSinceBoot {
34 let uptime = zx::Duration::from_nanos(capture_time.into_nanos());
35 UPTIME_LEVEL_INDEX
36 .into_iter()
37 .find(|&&(time, _)| uptime < time)
38 .map(|(_, code)| *code)
39 .unwrap_or(TimeSinceBoot::UpSixDays)
40}
41
42fn kmem_events(kmem_stats: &fkernel::MemoryStats) -> impl Iterator<Item = fmetrics::MetricEvent> {
43 use cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown as Breakdown;
44 let make_event = |code: Breakdown, value| {
45 Some(fmetrics::MetricEvent {
46 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
47 event_codes: vec![code.as_event_code()],
48 payload: fmetrics::MetricEventPayload::IntegerValue(value? as i64),
49 })
50 };
51 vec![
52 make_event(Breakdown::TotalBytes, kmem_stats.total_bytes),
53 make_event(
54 Breakdown::UsedBytes,
55 (|| Some((kmem_stats.total_bytes? as i64 - kmem_stats.free_bytes? as i64) as u64))(),
56 ),
57 make_event(Breakdown::FreeBytes, kmem_stats.free_bytes),
58 make_event(Breakdown::VmoBytes, kmem_stats.vmo_bytes),
59 make_event(Breakdown::KernelFreeHeapBytes, kmem_stats.free_heap_bytes),
60 make_event(Breakdown::MmuBytes, kmem_stats.mmu_overhead_bytes),
61 make_event(Breakdown::IpcBytes, kmem_stats.ipc_bytes),
62 make_event(Breakdown::KernelTotalHeapBytes, kmem_stats.total_heap_bytes),
63 make_event(Breakdown::WiredBytes, kmem_stats.wired_bytes),
64 make_event(Breakdown::OtherBytes, kmem_stats.other_bytes),
65 ]
66 .into_iter()
67 .flatten()
68}
69
70fn kmem_events_with_uptime(
71 kmem_stats: &fkernel::MemoryStats,
72 capture_time: zx::BootInstant,
73) -> impl Iterator<Item = fmetrics::MetricEvent> {
74 use cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown as Breakdown;
75 let make_event = |code: Breakdown, value| {
76 Some(fmetrics::MetricEvent {
77 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
78 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
79 general_breakdown: code,
80 time_since_boot: get_uptime_event_code(capture_time),
81 }
82 .as_event_codes(),
83 payload: fmetrics::MetricEventPayload::IntegerValue(value? as i64),
84 })
85 };
86 vec![
87 make_event(Breakdown::TotalBytes, kmem_stats.total_bytes),
88 make_event(
89 Breakdown::UsedBytes,
90 (|| Some((kmem_stats.total_bytes? as i64 - kmem_stats.free_bytes? as i64) as u64))(),
91 ),
92 make_event(Breakdown::FreeBytes, kmem_stats.free_bytes),
93 make_event(Breakdown::VmoBytes, kmem_stats.vmo_bytes),
94 make_event(Breakdown::KernelFreeHeapBytes, kmem_stats.free_heap_bytes),
95 make_event(Breakdown::MmuBytes, kmem_stats.mmu_overhead_bytes),
96 make_event(Breakdown::IpcBytes, kmem_stats.ipc_bytes),
97 make_event(Breakdown::KernelTotalHeapBytes, kmem_stats.total_heap_bytes),
98 make_event(Breakdown::WiredBytes, kmem_stats.wired_bytes),
99 make_event(Breakdown::OtherBytes, kmem_stats.other_bytes),
100 ]
101 .into_iter()
102 .flatten()
103}
104
105fn digest_events<'a>(
106 digest: Digest,
107 bucket_name_to_code: &'a HashMap<String, u32>,
108) -> impl 'a + Iterator<Item = fmetrics::MetricEvent> {
109 digest.buckets.into_iter().filter_map(|bucket| {
110 Some(fmetrics::MetricEvent {
111 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
112 event_codes: vec![*bucket_name_to_code.get(&bucket.name)?],
113 payload: fmetrics::MetricEventPayload::IntegerValue(bucket.size as i64),
114 })
115 })
116}
117
118pub async fn collect_metrics_forever(
120 attribution_data_service: Arc<impl AttributionDataProvider + 'static>,
121 kernel_stats_proxy: fkernel::StatsProxy,
122 metric_event_logger: fmetrics::MetricEventLoggerProxy,
123 bucket_definitions: Arc<[BucketDefinition]>,
124) {
125 let mut bucket_name_to_code = HashMap::from([
126 (
127 "TotalBytes".to_string(),
128 cobalt_registry::MemoryMigratedMetricDimensionBucket::TotalBytes.as_event_code(),
129 ),
130 (
131 "Free".to_string(),
132 cobalt_registry::MemoryMigratedMetricDimensionBucket::Free.as_event_code(),
133 ),
134 (
135 "Kernel".to_string(),
136 cobalt_registry::MemoryMigratedMetricDimensionBucket::Kernel.as_event_code(),
137 ),
138 (
139 "Orphaned".to_string(),
140 cobalt_registry::MemoryMigratedMetricDimensionBucket::Orphaned.as_event_code(),
141 ),
142 (
143 "Undigested".to_string(),
144 cobalt_registry::MemoryMigratedMetricDimensionBucket::Undigested.as_event_code(),
145 ),
146 (
147 "[Addl]PagerTotal".to_string(),
148 cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_PagerTotal.as_event_code(),
149 ),
150 (
151 "[Addl]PagerNewest".to_string(),
152 cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_PagerNewest
153 .as_event_code(),
154 ),
155 (
156 "[Addl]PagerOldest".to_string(),
157 cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_PagerOldest
158 .as_event_code(),
159 ),
160 (
161 "[Addl]DiscardableLocked".to_string(),
162 cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_DiscardableLocked
163 .as_event_code(),
164 ),
165 (
166 "[Addl]DiscardableUnlocked".to_string(),
167 cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_DiscardableUnlocked
168 .as_event_code(),
169 ),
170 (
171 "[Addl]ZramCompressedBytes".to_string(),
172 cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_ZramCompressedBytes
173 .as_event_code(),
174 ),
175 ]);
176 bucket_definitions.iter().for_each(|bucket_definition| {
177 bucket_name_to_code
178 .entry(bucket_definition.name.clone())
179 .or_insert(bucket_definition.event_code as u32);
180 });
181 let mut timer = fuchsia_async::Interval::new(zx::Duration::from_minutes(5));
182 loop {
183 timer.next().await;
184
185 let result = collect_metrics_once(
186 &*attribution_data_service,
187 &kernel_stats_proxy,
188 &metric_event_logger,
189 &bucket_definitions,
190 &bucket_name_to_code,
191 )
192 .await;
193
194 if let Err(e) = result {
195 log::error!("Metrics collection failed: {e}");
196 }
197 }
198}
199
200async fn collect_metrics_once(
201 attribution_data_service: &impl AttributionDataProvider,
202 kernel_stats_proxy: &fkernel::StatsProxy,
203 metric_event_logger: &fmetrics::MetricEventLoggerProxy,
204 bucket_definitions: &[BucketDefinition],
205 bucket_name_to_code: &HashMap<String, u32>,
206) -> Result<()> {
207 let timestamp = zx::BootInstant::get();
208 let (kmem_stats, kmem_stats_compression) = try_join!(
209 kernel_stats_proxy.get_memory_stats().map_err(anyhow::Error::from),
210 kernel_stats_proxy.get_memory_stats_compression().map_err(anyhow::Error::from)
211 )?;
212 let digest = Digest::compute(
213 &*attribution_data_service,
214 &kmem_stats,
215 &kmem_stats_compression,
216 &bucket_definitions,
217 )?;
218
219 let events = kmem_events(&kmem_stats)
220 .chain(kmem_events_with_uptime(&kmem_stats, timestamp))
221 .chain(digest_events(digest, &bucket_name_to_code));
222 metric_event_logger
223 .log_metric_events(&events.collect::<Vec<fmetrics::MetricEvent>>())
224 .await?
225 .map_err(error_from_metrics_error)?;
226 Ok(())
227}
228
229#[cfg(test)]
230mod tests {
231 use super::*;
232 use anyhow::anyhow;
233 use attribution_processing::testing::FakeAttributionDataProvider;
234 use attribution_processing::{
235 Attribution, AttributionData, Principal, PrincipalDescription, PrincipalIdentifier,
236 PrincipalType, Resource, ResourceReference, ZXName,
237 };
238 use futures::task::Poll;
239 use futures::TryStreamExt;
240 use regex::bytes::Regex;
241 use std::time::Duration;
242 use {fidl_fuchsia_memory_attribution_plugin as fplugin, fuchsia_async as fasync};
243
244 fn get_attribution_data_provider() -> Arc<impl AttributionDataProvider + 'static> {
245 let attribution_data = AttributionData {
246 principals_vec: vec![Principal {
247 identifier: PrincipalIdentifier(1),
248 description: PrincipalDescription::Component("principal".to_owned()),
249 principal_type: PrincipalType::Runnable,
250 parent: None,
251 }],
252 resources_vec: vec![
253 Resource {
255 koid: 10,
256 name_index: 0,
257 resource_type: fplugin::ResourceType::Vmo(fplugin::Vmo {
258 parent: None,
259 private_committed_bytes: Some(1024),
260 private_populated_bytes: Some(2048),
261 scaled_committed_bytes: Some(1024),
262 scaled_populated_bytes: Some(2048),
263 total_committed_bytes: Some(1024),
264 total_populated_bytes: Some(2048),
265 ..Default::default()
266 }),
267 },
268 Resource {
270 koid: 20,
271 name_index: 1,
272 resource_type: fplugin::ResourceType::Vmo(fplugin::Vmo {
273 parent: None,
274 private_committed_bytes: Some(1024),
275 private_populated_bytes: Some(2048),
276 scaled_committed_bytes: Some(1024),
277 scaled_populated_bytes: Some(2048),
278 total_committed_bytes: Some(1024),
279 total_populated_bytes: Some(2048),
280 ..Default::default()
281 }),
282 },
283 Resource {
285 koid: 30,
286 name_index: 1,
287 resource_type: fplugin::ResourceType::Process(fplugin::Process {
288 vmos: Some(vec![20]),
289 ..Default::default()
290 }),
291 },
292 ],
293 resource_names: vec![
294 ZXName::from_string_lossy("resource"),
295 ZXName::from_string_lossy("bucket1_resource"),
296 ],
297 attributions: vec![Attribution {
298 source: PrincipalIdentifier(1),
299 subject: PrincipalIdentifier(1),
300 resources: vec![ResourceReference::KernelObject(10)],
301 }],
302 };
303 Arc::new(FakeAttributionDataProvider { attribution_data })
304 }
305
306 async fn serve_kernel_stats(
307 mut request_stream: fkernel::StatsRequestStream,
308 ) -> Result<(), fidl::Error> {
309 while let Some(request) = request_stream.try_next().await? {
310 match request {
311 fkernel::StatsRequest::GetMemoryStats { responder } => {
312 responder
313 .send(&fkernel::MemoryStats {
314 total_bytes: Some(1),
315 free_bytes: Some(2),
316 wired_bytes: Some(3),
317 total_heap_bytes: Some(4),
318 free_heap_bytes: Some(5),
319 vmo_bytes: Some(6),
320 mmu_overhead_bytes: Some(7),
321 ipc_bytes: Some(8),
322 other_bytes: Some(9),
323 free_loaned_bytes: Some(10),
324 cache_bytes: Some(11),
325 slab_bytes: Some(12),
326 zram_bytes: Some(13),
327 vmo_reclaim_total_bytes: Some(14),
328 vmo_reclaim_newest_bytes: Some(15),
329 vmo_reclaim_oldest_bytes: Some(16),
330 vmo_reclaim_disabled_bytes: Some(17),
331 vmo_discardable_locked_bytes: Some(18),
332 vmo_discardable_unlocked_bytes: Some(19),
333 ..Default::default()
334 })
335 .unwrap();
336 }
337 fkernel::StatsRequest::GetMemoryStatsExtended { responder: _ } => {
338 unimplemented!("Deprecated call, should not be used")
339 }
340 fkernel::StatsRequest::GetMemoryStatsCompression { responder } => {
341 responder
342 .send(&fkernel::MemoryStatsCompression {
343 uncompressed_storage_bytes: Some(20),
344 compressed_storage_bytes: Some(21),
345 compressed_fragmentation_bytes: Some(22),
346 compression_time: Some(23),
347 decompression_time: Some(24),
348 total_page_compression_attempts: Some(25),
349 failed_page_compression_attempts: Some(26),
350 total_page_decompressions: Some(27),
351 compressed_page_evictions: Some(28),
352 eager_page_compressions: Some(29),
353 memory_pressure_page_compressions: Some(30),
354 critical_memory_page_compressions: Some(31),
355 pages_decompressed_unit_ns: Some(32),
356 pages_decompressed_within_log_time: Some([
357 40, 41, 42, 43, 44, 45, 46, 47,
358 ]),
359 ..Default::default()
360 })
361 .unwrap();
362 }
363 fkernel::StatsRequest::GetCpuStats { responder: _ } => unimplemented!(),
364 fkernel::StatsRequest::GetCpuLoad { duration: _, responder: _ } => unimplemented!(),
365 }
366 }
367 Ok(())
368 }
369
370 #[test]
371 fn test_periodic_metrics_collection() -> anyhow::Result<()> {
372 let mut exec = fasync::TestExecutor::new_with_fake_time();
374
375 let data_provider = get_attribution_data_provider();
377 let (stats_provider, stats_request_stream) =
378 fidl::endpoints::create_proxy_and_stream::<fkernel::StatsMarker>();
379 fasync::Task::spawn(async move {
380 serve_kernel_stats(stats_request_stream).await.unwrap();
381 })
382 .detach();
383 let bucket_definitions = Arc::new([BucketDefinition {
385 name: "bucket1".to_string(),
386 vmo: Some(Regex::new("bucket1.*")?),
387 event_code: 1,
388 process: None,
389 }]);
390
391 let (metric_event_logger, metric_event_request_stream) =
393 fidl::endpoints::create_proxy_and_stream::<fmetrics::MetricEventLoggerMarker>();
394
395 let mut metrics_collector = fuchsia_async::Task::spawn(collect_metrics_forever(
397 data_provider,
398 stats_provider,
399 metric_event_logger,
400 bucket_definitions,
401 ));
402
403 assert!(
405 exec.run_until_stalled(&mut metrics_collector).is_pending(),
406 "Metrics collection service returned unexpectedly early"
407 );
408
409 let mut metric_event_request_future = metric_event_request_stream.into_future();
411 assert!(
412 exec.run_until_stalled(&mut metric_event_request_future).is_pending(),
413 "Metrics collection service returned unexpectedly early"
414 );
415
416 assert!(
418 exec.run_until_stalled(&mut std::pin::pin!(fasync::TestExecutor::advance_to(
419 exec.now() + Duration::from_secs(5 * 60).into()
420 )))
421 .is_ready(),
422 "Failed to advance time"
423 );
424 let uptime = get_uptime_event_code(zx::BootInstant::get());
425
426 let Poll::Ready((event, metric_event_request_stream)) =
428 exec.run_until_stalled(&mut metric_event_request_future)
429 else {
430 panic!("Failed to receive metrics")
431 };
432 let event = event.ok_or_else(|| anyhow!("Metrics stream unexpectedly closed"))??;
433 match event {
434 fmetrics::MetricEventLoggerRequest::LogMetricEvents { events, .. } => {
435 assert_eq!(
437 &events[0..10],
438 vec![
439 fmetrics::MetricEvent {
440 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
441 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::TotalBytes.as_event_code()],
442 payload: fmetrics::MetricEventPayload::IntegerValue(1)
443 },
444 fmetrics::MetricEvent {
445 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
446 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::UsedBytes.as_event_code()],
447 payload: fmetrics::MetricEventPayload::IntegerValue(-1)
448 },
449 fmetrics::MetricEvent {
450 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
451 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::FreeBytes.as_event_code()],
452 payload: fmetrics::MetricEventPayload::IntegerValue(2)
453 },
454 fmetrics::MetricEvent {
455 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
456 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::VmoBytes.as_event_code()],
457 payload: fmetrics::MetricEventPayload::IntegerValue(6)
458 },
459 fmetrics::MetricEvent {
460 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
461 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::KernelFreeHeapBytes.as_event_code()],
462 payload: fmetrics::MetricEventPayload::IntegerValue(5)
463 },
464 fmetrics::MetricEvent {
465 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
466 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::MmuBytes.as_event_code()],
467 payload: fmetrics::MetricEventPayload::IntegerValue(7)
468 },
469 fmetrics::MetricEvent {
470 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
471 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::IpcBytes.as_event_code()],
472 payload: fmetrics::MetricEventPayload::IntegerValue(8)
473 },
474 fmetrics::MetricEvent {
475 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
476 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::KernelTotalHeapBytes.as_event_code()],
477 payload: fmetrics::MetricEventPayload::IntegerValue(4)
478 },
479 fmetrics::MetricEvent {
480 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
481 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::WiredBytes.as_event_code()],
482 payload: fmetrics::MetricEventPayload::IntegerValue(3)
483 },
484 fmetrics::MetricEvent {
485 metric_id: cobalt_registry::MEMORY_GENERAL_BREAKDOWN_MIGRATED_METRIC_ID,
486 event_codes: vec![cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown::OtherBytes.as_event_code()],
487 payload: fmetrics::MetricEventPayload::IntegerValue(9)
488 },]);
489 assert_eq!(
491 &events[10..20],
492 vec![
493 fmetrics::MetricEvent {
494 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
495 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
496 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::TotalBytes, time_since_boot: uptime}.as_event_codes(),
497 payload: fmetrics::MetricEventPayload::IntegerValue(1)
498 },
499 fmetrics::MetricEvent {
500 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
501 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
502 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::UsedBytes, time_since_boot:uptime}.as_event_codes(),
503 payload: fmetrics::MetricEventPayload::IntegerValue(-1)
504 },
505 fmetrics::MetricEvent {
506 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
507 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
508 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::FreeBytes, time_since_boot:uptime}.as_event_codes(), payload: fmetrics::MetricEventPayload::IntegerValue(2)
509 },
510 fmetrics::MetricEvent {
511 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
512 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
513 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::VmoBytes, time_since_boot:uptime}.as_event_codes(),
514 payload: fmetrics::MetricEventPayload::IntegerValue(6)
515 },
516 fmetrics::MetricEvent {
517 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
518 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
519 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::KernelFreeHeapBytes, time_since_boot:uptime}.as_event_codes(),
520 payload: fmetrics::MetricEventPayload::IntegerValue(5)
521 },
522 fmetrics::MetricEvent {
523 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
524 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
525 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::MmuBytes, time_since_boot:uptime}.as_event_codes(),
526 payload: fmetrics::MetricEventPayload::IntegerValue(7)
527 },
528 fmetrics::MetricEvent {
529 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
530 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
531 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::IpcBytes, time_since_boot:uptime}.as_event_codes(),
532 payload: fmetrics::MetricEventPayload::IntegerValue(8)
533 },
534 fmetrics::MetricEvent {
535 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
536 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
537 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::KernelTotalHeapBytes, time_since_boot:uptime}.as_event_codes(),
538 payload: fmetrics::MetricEventPayload::IntegerValue(4)
539 },
540 fmetrics::MetricEvent {
541 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
542 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
543 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::WiredBytes, time_since_boot:uptime}.as_event_codes(),
544 payload: fmetrics::MetricEventPayload::IntegerValue(3)
545 },
546 fmetrics::MetricEvent {
547 metric_id: cobalt_registry::MEMORY_LEAK_MIGRATED_METRIC_ID,
548 event_codes: cobalt_registry::MemoryLeakMigratedEventCodes {
549 general_breakdown: cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown::OtherBytes, time_since_boot:uptime}.as_event_codes(),
550 payload: fmetrics::MetricEventPayload::IntegerValue(9)
551 },
552 ]
553 );
554 assert_eq!(
556 &events[20..],
557 vec![
558 fmetrics::MetricEvent {
560 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
561 event_codes: vec![1], payload: fmetrics::MetricEventPayload::IntegerValue(1024)
563 },
564 fmetrics::MetricEvent {
566 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
567 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::Undigested.as_event_code()],
568 payload: fmetrics::MetricEventPayload::IntegerValue(1024)
569 },
570 fmetrics::MetricEvent {
571 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
572 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::Orphaned.as_event_code()],
573 payload: fmetrics::MetricEventPayload::IntegerValue(0)
574 },
575 fmetrics::MetricEvent {
576 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
577 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::Kernel.as_event_code()],
578 payload: fmetrics::MetricEventPayload::IntegerValue(31)
579 },
580 fmetrics::MetricEvent {
581 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
582 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::Free.as_event_code()],
583 payload: fmetrics::MetricEventPayload::IntegerValue(2)
584 },
585 fmetrics::MetricEvent {
586 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
587 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_PagerTotal.as_event_code()],
588 payload: fmetrics::MetricEventPayload::IntegerValue(14)
589 },
590 fmetrics::MetricEvent {
591 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
592 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_PagerNewest.as_event_code()],
593 payload: fmetrics::MetricEventPayload::IntegerValue(15)
594 },
595 fmetrics::MetricEvent {
596 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
597 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_PagerOldest.as_event_code()],
598 payload: fmetrics::MetricEventPayload::IntegerValue(16)
599 },
600 fmetrics::MetricEvent {
601 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
602 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_DiscardableLocked.as_event_code()],
603 payload: fmetrics::MetricEventPayload::IntegerValue(18)
604 },
605 fmetrics::MetricEvent {
606 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
607 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_DiscardableUnlocked.as_event_code()],
608 payload: fmetrics::MetricEventPayload::IntegerValue(19)
609 },
610 fmetrics::MetricEvent {
611 metric_id: cobalt_registry::MEMORY_MIGRATED_METRIC_ID,
612 event_codes: vec![cobalt_registry::MemoryMigratedMetricDimensionBucket::__Addl_ZramCompressedBytes.as_event_code()],
613 payload: fmetrics::MetricEventPayload::IntegerValue(21)
614 }
615 ]
616 )
617 }
618 _ => panic!("Unexpected metric event"),
619 }
620
621 assert!(exec
622 .run_until_stalled(&mut metric_event_request_stream.into_future())
623 .is_pending());
624 Ok(())
625 }
626}