capture
APIs of SnippetstartCapture
and endCapture
APIs
+ * Example usage with Snippet.capture
:
+ *
+ * {@code + * Snippet.capture(() -> { + * final ActionBar actionBar = getSupportActionBar(); + * if (actionBar != null && actionBar.isShowing()) { + * if (mToolbar != null) { + * ViewCompat.setElevation((View) mToolbar.getParent(), 0F); + * mToolbar.animate() + * .translationY(-mToolbar.getHeight()) + * .setInterpolator(new AccelerateDecelerateInterpolator()) + * .withEndAction(new Runnable() { + * {@literal}Override + * public void run() { + * actionBar.hide(); + * if (mToolbarTranslateYListener != null) { + * mToolbarTranslateYListener.onAnimationFinished(); + * } + * } + * }) + * .start(); + * } else { + * actionBar.hide(); + * } + * } + * }); + * } + *+ * Here library is going to measure time used to execute the code represented by the underlying lambda. + *
+ * When you intent to measure the execution times for code which is not spread across multiple + * methods and classes, capture APIs can be used. There is one caveat though, while capturing, we pass + * a lambda for the closure representing the code snippet, this might be a problem if we want to capture + * some non final variables outside the scope of lambda(Java does not support that). For that use, {@link Final} to create a + * wrapper around your variable and use {@link Final#get()} and {@link Final#set(Object)}()} methods. + *
+ * Another approach is through {@link Snippet#startCapture()} & {@link LogToken#endCapture()} APIs.
+ * startCapture
is going to return a token representing your execution it can be passed
+ * from one component to another. The moment you call endCapture()
it will measure the
+ * time and print the logs.
+ *
+ * Example usage of Snippet.startCapture()
and LogToken.endCapture()
:
+ *
+ * {@code + * Snippet.LogToken token = Snippet.startCapture(); // start the measurement + * getEditText().setOnTouchListener((v, event) -> { + * mIsQueryTextFromVoiceInput = false; + * if (!TextUtils.isEmpty(getEditText().getText())) { + * updateClearIconAndVoiceEntryVisibility(VISIBLE, GONE); + * } + * + * if (mOnEditTextTouchListener != null) { + * return mOnEditTextTouchListener.onTouch(v, event); + * } + * + * return false; + * }); + * + * initVoiceInputEntry(context); + * token.endCapture(); // end measurement and print logs. + * } + *+ * We can use
startCapture()
method with a TAG also. This is particularly useful when
+ * the execution is spread across multiple classes. We can use, {@link Snippet#find(String)} to find
+ * the log token that was created with this tag. The logtoken received can be then used normally.
+ * {@link LogToken} objects are internally obtained through a pool so, Snippet tries it best to
+ * recycle the objects again and again.
+ * + * There is concept of filter, which can be used to filter the logcat output. You can set the filter + * using {@link Snippet#newFilter(String)}. Default filter is Snippet + * While this is global filter for all the logs, you can still choose to have a different filter for a + * particular LogToken using {@link LogToken#overrideFilter(String)} which will override the global filter. + *
+ * Snippet can print Class, Method and Line number information in the logs as a part of execution + * context. By default it prints class and method name. You can choose to have your combination of + * details through {@link Snippet#addFlag(int)} + * Valid options are: + *
+ * While these information should be enough but if you need to add some more information to the logs + * like variable values, states etc then use {@link Snippet#capture(String, Closure)} and + * {@link LogToken#endCapture(String)} overloads for adding custom messages to the logcat + * output. + *
+ * Snippet also supports the concept of ThreadLocks. ThreadLocks is a feature where a log token + * can declare the thread creating the log token would only be able to call endCapture(). If other + * thread tries to call endCapture(). It will log an error. To enable thread locks one should + * call {@link LogToken#enableThreadLock()} and to check if the ThreadLock is enabled or not + * {@link LogToken#isThreadLockEnabled()} can be used. + *
+ * + *+ * There are times while you are measuring a sequence of code and you would like to measure how + * much time some steps take within that sequence. As an example, while you are measuring some + * method that takes 300ms to execute, it could have multiple areas inside it that could be adding up + * to that number. So, to measure that {@link LogToken#addSplit()} and {@link LogToken#addSplit(String)} + * could be used. Each call to add split print the time takes since the last addSplit() was called. + * If addSplit() is called for the first time, then it would measure the time from startCapture(). + *
+ * + * @author vishalratna + */ +public final class Snippet { + private static final String TAG = LogToken.class.getSimpleName(); + static final AttenuatedLogToken NO_OP_TOKEN = new AttenuatedLogToken(); + + public static final int FLAG_METADATA_CLASS = 1 << 31; + public static final int FLAG_METADATA_METHOD = 1 << 30; + public static final int FLAG_METADATA_LINE = 1 << 29; + public static final int FLAG_METADATA_THREAD_INFO = 1 << 28; + public static final int FLAG_NONE = 0; + + private static String primaryFilter = Snippet.class.getSimpleName(); + private static final LogTokenPool OBJECT_POOL; + private static String packageNameFilter = "com.microsoft"; + private static StackAnalyser stackAnalyser = new StackAnalyser(packageNameFilter); + private static final TagHelper TAG_HELPER; + private static int mFlags = FLAG_METADATA_CLASS | FLAG_METADATA_METHOD; + private static final String SEPARATOR = "|::::|"; + private static final OneShot