blob: 025ca3267a7f9e0a865da16484d26e7269c2af01 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:logging/logging.dart';
import 'sl4f_client.dart';
enum InspectPipeline {
none,
feedback,
legacyMetrics,
}
extension ServiceNameExtension on InspectPipeline {
String get serviceName {
switch (this) {
case InspectPipeline.none:
return 'fuchsia.diagnostics.ArchiveAccessor';
case InspectPipeline.feedback:
return 'fuchsia.diagnostics.FeedbackArchiveAccessor';
case InspectPipeline.legacyMetrics:
return 'fuchsia.diagnostics.LegacyMetricsArchiveAccessor';
}
return '';
}
}
/// Read inspect data from components running on the device.
///
/// Inspect (https://fuchsia.dev/fuchsia-src/development/inspect) gives you
/// access to current state information exposed by components.
class Inspect {
final Sl4f sl4f;
/// Construct an [Inspect] object.
Inspect(this.sl4f);
/// Gets the inspect data filtering using the given [selectors].
///
/// The result is a list of deserialized JSON Maps with key value pairs for
/// the matching components and nodes.
///
/// A selector consists of the realm path, component name and a path to a node
/// or property.
/// It accepts wildcards.
/// For example:
/// a/*/test.cmx:path/to/*/node:prop
/// a/*/test.cmx:root
///
/// See: https://fuchsia.googlesource.com/fuchsia/+/HEAD/sdk/fidl/fuchsia.diagnostics/selector.fidl
///
/// Returns an empty list if nothing is found.
Future<List<Map<String, dynamic>>> snapshot(
List<String> selectors, {
InspectPipeline pipeline = InspectPipeline.none,
}) async {
final hierarchyList =
await sl4f.request('diagnostics_facade.SnapshotInspect', {
'selectors': selectors,
'service_name': pipeline.serviceName,
}) ??
[];
return hierarchyList.cast<Map<String, dynamic>>();
}
/// Gets the inspect data for all components currently running in the system.
///
/// Returns an empty list if nothing is found.
Future<List<Map<String, dynamic>>> snapshotAll({
InspectPipeline pipeline = InspectPipeline.none,
}) async {
return await snapshot([], pipeline: pipeline);
}
/// Gets the payload of the first found hierarchy matching the given selectors
/// under root.
///
/// Returns null if no hierarchy was found.
Future<Map<String, dynamic>> snapshotRoot(
String componentSelector, {
InspectPipeline pipeline = InspectPipeline.none,
}) async {
final hierarchies = await snapshot(
['$componentSelector:root'],
pipeline: pipeline,
);
if (hierarchies.isEmpty) {
return null;
}
final resultHierarchy = hierarchies.first;
if (resultHierarchy['payload'] == null) {
_log.warning('Got null payload for "$componentSelector:root". '
'Metadata: ${resultHierarchy['metadata']}');
return null;
}
return resultHierarchy['payload']['root'];
}
}
final _log = Logger('Inspect');