/* * Copyright (c) 2014-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.stetho.dumpapp; /** * Provides a CLI (command-line interface) facility for {@code fbandroid} modules. * * <p>Binding an instance of this interface allows you to inject custom debug/dumping code * into the app that is accessible when a phone running the app is connected via ADB. To see a * list of current plugins, see: * <pre> * ./scripts/dumpapp --list * </pre> * * <h3>General Utility</h3> * * <p>This system allows for complex components to inform developers of what's been going on * recently (or over the process lifetime) in a simple, human-readable fashion. Good candidates * for this kind of interface are those that are otherwise hard to isolate or visualize such as * the network stack or task runners (BlueService, Executor, etc). It is also possible to create * a kind of simple instrumentation around components that otherwise have no UI. For example, it * may be useful to be able to clear the image cache or delete individual entries on demand as * well as viewing the current state of all cached entries. * * <h3>Implementation Guidelines</h3> * * Almost any kind of simple interface will work however there are some basic guidelines that you * should follow: * * <ol> * <li>Avoid heavy-weight plugins that add significant additional code to the app. While this * code does not ship in katana (proguard strips it out), it is generally a good idea to evaluate * large or complex instrumentation projects in the greater context of tools available at Facebook * (in particular Scuba which can aggregate data for our user base in the wild). 1 or 2 classes * is a good rule of thumb for reasonable plugin size. * <li>Don't implement long-running jobs in {@link #dump}. If the instrumented action takes a * long time, consider a way to "fire-and-forget" so that you can return some message to the * caller quickly. * <li>Don't perform extra up-front initialization not normally needed by the app. Dumpers should * init on demand so that there is no runtime impact to the app. * </ol> * * <h3>Gotchas</h3> * * <p>In order for dumpapp to work the app must currently be running and there is an * initialization overhead of the "dumper" system which may make real-time debug output during * app startup tricky or impossible. However, you can work around this by implementing simple * stat counters that can be pulled and reset within your plugin. After initialization completes * (and thus dumpapp becomes available), you can query for the stats that were being collected * while the app was starting. */ public interface DumperPlugin { /** * Plugin name according to the dumpsys command-line interface. Please be mindful of the * fact that this is part of a command-line interface and should be generally easy to type and * remember. Avoid underscores, capital letters, and plural names. Instead, prefer terse names * like "network", "logging", etc. */ String getName(); /** * Invoked in response to the user running the dumpapp command and specifying your plugin. * <p> * Any output written to {@link DumperContext#getStdout()} will be displayed to the caller. * * @param dumpContext Contains the command-line state (extra arguments, output channel, etc). * @throws DumpException Your plugin can throw this event to easily bail from a dump sequence * on unexpected errors. The message will be displayed directly to the caller and the * dumpapp script will terminate with a non-successful exit code. */ void dump(DumperContext dumpContext) throws DumpException; }