TART: Tracing Action Response Times

Related tags

Networking tart
Overview

Square Tart

Tracing Action Response Times!

This library is not stable for usage beyond Square, the APIs and internals might change anytime.

Tart... ?

Table of contents

We still need a logo! logo_512.png

Usage

Add the tart dependency to your library or app's build.gradle file:

dependencies {
  implementation 'com.squareup.tart:tart:0.1'
}

Then add a new AppLaunch.onAppLaunchListeners. See AppLaunch javadoc for details.

import android.app.Application
import tart.AppLaunch
import tart.PreLaunchState

class ExampleApplication : Application() {
  override fun onCreate() {
    super.onCreate()
    AppLaunch.onAppLaunchListeners += { appLaunch ->
      val startType = when (appLaunch.preLaunchState) {
        NO_PROCESS -> "cold start"
        NO_PROCESS_FIRST_LAUNCH_AFTER_INSTALL -> "cold start"
        NO_PROCESS_FIRST_LAUNCH_AFTER_UPGRADE -> "cold start"
        NO_PROCESS_FIRST_LAUNCH_AFTER_CLEAR_DATA -> "cold start"
        PROCESS_WAS_LAUNCHING_IN_BACKGROUND -> "warm start"
        NO_ACTIVITY_NO_SAVED_STATE -> "warm start"
        NO_ACTIVITY_BUT_SAVED_STATE -> "warm start"
        ACTIVITY_WAS_STOPPED -> "hot start"
      }
      val durationMillis = appLaunch.duration.uptime(MILLISECONDS)
      println("$startType launch: $durationMillis ms")
    }
  }
}

FAQ

It's not really a question, more like a comment..

License

Copyright 2021 Square Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Windowless onCurrentFrame / onNextFrame?

    Windowless onCurrentFrame / onNextFrame?

    Currently these APIs are extension functions on Window because frame metrics are per window.

    Need to experiment with multi window (activity + dialog) to see if the metrics actually differ. All windows are rendered in one go. A possible difference might be if each traversal is measured separately? tbd.

    If there's no difference, then we maybe could come up with a way to grab any or "the best" window and just run with that, removing the need for a window, which is nice when you're in the middle of your navigation code.

    opened by pyricau 3
  • Interaction latency API considerations

    Interaction latency API considerations

    Currently an interaction result includes the start and end event.

    We should consider simply associating a list of events instead. We'll end up with a single event when start & finish are called on the same event, 2 events for normal delayed interactions, 2 events for normal canceled interactions (but 1 for timed out interactions). We could support more than 3 by having a way to pull a running interaction & associate it to the current event, whether that interaction is running or finishing.

    There's separately a question of whether even having an interaction type at all is useful. Since the rules are event based and the events carry all the context needed, an interaction could be defined as a list of events with maybe a name.

    To do this we'd likely also need to provide access to all past events associated with a given running interactions, so that you could look them up and find the ones with start ids related to the id of the current event.

    One consistent feedback is that cancelRunningInteractions() sounds like it would cancel all interactions when in fact it's all interactions local to the rule. Some have expressed the need to actually do that though, i.e. cancel for a bunch of rules, which might be done by handling all sub rules in a single rule.

    opened by pyricau 2
  • Use MessageCompat.setAsynchronous to support API 16+

    Use MessageCompat.setAsynchronous to support API 16+

    opened by jstaahl 2
  • Use async messages pre API 22

    Use async messages pre API 22

    https://github.com/square/papa/blob/main/papa/src/main/java/papa/internal/Handlers.kt

    See this: https://www.zacsweers.dev/rxandroids-new-async-api/#api-16-21-

    opened by pyricau 2
  • More straightforward way to provide end metadata for interactions?

    More straightforward way to provide end metadata for interactions?

    Currently there's an interaction object that can be updated, that works but not convenient as it has to be created early, so the end metadata is typically a lateinit var, which you might forget. We want to make sure we don't forget to provide the data as we call finish.

    opened by pyricau 1
  • CurrentFrameMetricsListener is counting UNKNOWN_DELAY_DURATION duration twice?

    CurrentFrameMetricsListener is counting UNKNOWN_DELAY_DURATION duration twice?

    While browsing some code noticed that

    In class CurrentFrameMetricsListener -- line 47, 48 is double counting UNKNOWN_DELAY_DURATION twice?

      val drawEndNanos =
          frameMetrics.getMetric(INTENDED_VSYNC_TIMESTAMP) +
            frameMetrics.getMetric(FrameMetrics.UNKNOWN_DELAY_DURATION) +
            frameMetrics.getMetric(FrameMetrics.UNKNOWN_DELAY_DURATION) +
    
    opened by snijsure 1
  • Add event system

    Add event system

    Need to create an event recording system that we can hook into to set listeners (otherwise they're lost) and then each app launch sets a listener and provides the list of events once done. The EventRecorder need to be thread safe. We also likely need 2 recorders or a way to duplicate because process start is one and cold app launch is another. Also need to be able to insert events at a specific time. Need to be able to add custom events.

    Once we have that we can migrate a lot of the custom measurements to these events.

    opened by pyricau 1
  • Interaction latency rules

    Interaction latency rules

    Redesigning the API and implementation for tracking interaction latency, with a primary goal of decoupling the code where we send signals (events) from the place where we tie those events together an interaction.

    Example usage code

    interface PosInteractionEvent
    interface PosInteraction
    
    object OpenCheckoutApplet : PosInteraction
    
    class Navigation(val destination: Any) : PosInteractionEvent
    
    class CheckoutApplet : PosInteraction
    
    object TapItem : PosInteractionEvent {
      val itemId = ""
    }
    
    object ItemVisibleInCart : PosInteractionEvent {
      val itemId = ""
    }
    
    class AddItemToCart(val itemId: String) : PosInteraction
    
    object KeypadVisible : PosInteractionEvent
    object UserPressedBack : PosInteractionEvent
    
    fun setup() {
    
      val client = InteractionRuleClient<PosInteractionEvent, PosInteraction>()
    
      client.sendEvent(KeypadVisible)
      client.sendEvent(Navigation(Any()))
    
      val configuredRule = client.addInteractionRule<OpenCheckoutApplet> {
        onEvent<Navigation> { navigation ->
          if (navigation.destination is CheckoutApplet) {
            cancelRunningInteractions()
            startInteraction(OpenCheckoutApplet, onCancel = {
              Log.d("event canceled", it.cancelReason)
            })
          }
        }
        onEvent<UserPressedBack> {
          runningInteractions().singleOrNull()?.cancel("user pressed back")
        }
        onEvent<KeypadVisible> {
          runningInteractions().singleOrNull()?.finishOnFrameRendered { result ->
            logToAnalytics(result)
          }
        }
      }
    
      client.addInteractionRule<AddItemToCart> {
        onEvent<TapItem> { tapItem ->
          startInteraction(AddItemToCart(tapItem.itemId))
        }
        onEvent<ItemVisibleInCart> { itemVisibleInCart ->
          val addItemToCart = runningInteractions().firstOrNull {
            it.interaction.itemId == itemVisibleInCart.itemId
          }
          addItemToCart?.let { interaction ->
            interaction.finishOnFrameRendered { result ->
              logToAnalytics(result)
            }
          }
        }
      }
    
      // when we don't need this rule anymore
      configuredRule.remove()
    }
    
    opened by pyricau 0
  • onCurrentFrameRendered should join multiple calls into a single post

    onCurrentFrameRendered should join multiple calls into a single post

    Current impl:

    internal fun onCurrentFrameRendered(callback: (Long) -> Unit) {
      mainHandler.postAtFrontOfQueueAsync {
        val frameRenderedUptimeMillis = SystemClock.uptimeMillis()
        callback(frameRenderedUptimeMillis)
      }
    }
    

    This should be stateful and aware of any pending calls so that we only register a single call and a single uptime and dispatch to all callbacks

    opened by pyricau 0
  • Split up main UI test into several test methods

    Split up main UI test into several test methods

    We weren't using orchestrator internally so had to run all the tests from a single method. That shouldn't be needed in the OSS version anymore.

    Fixes #11

    opened by pyricau 0
  • FrozenFrameOnTouchDetector frame timestamp

    FrozenFrameOnTouchDetector frame timestamp

    Currently FrozenFrameOnTouchDetector listens to ACTION_DOWN events and schedules a frame callback from there, combined with a post at front of queue, and logs a "frozen frame" if the time from down being issued to the end time is greater than 700. This seems wrong as we're scheduling for another frame instead of relying on "end of current frame" as frame end. We probably don't want to rely on frame metrics here, we just want to know how long things were blocked for. A post at front (not async) from event handling should be enough.

    opened by pyricau 0
  • Naming nits

    Naming nits

    So like the events in TrackedInteraction isn’t super straightforward - events isn’t a good name for that I think sentEvents would make more sense. I had to explain this which is why I’m saying this.

    opened by pyricau 0
  • Cancellation via timeout in LaunchTracker not needed to support trampolining

    Cancellation via timeout in LaunchTracker not needed to support trampolining

    Currently, a launch is considered in-progress until there are 500+ ms between an executed runnable posted from a lifecycle callback and the next lifecycle callback (or we receive our first frame). It seems this timeout-based approach for what is considered a launch still-in-progress is used to support the case of trampoline activities. Outside of the context of trampoline activities, this timeout doesn't really come into play. That's because if you post a runnable during an activity lifecycle event, it will not get executed until after onResume. In the context of trampolining activities, I think a good way to distill this down to what this actually accomplishes is to consider the path to the first frame after onResume as unbroken as long as the distance between the last lifecycle callback of one activity to the first lifecycle callback of the next is less than 500ms. However, I don't believe we need a timeout-based approach like this to support trampoline activities.

    I believe that a more deterministic approach is to allow a launch measurement to continue indefinitely (until the first frame is rendered following onResume), unless the app ever goes from 1+ started activities to 0 started activities. In my testing, under all trampoline configurations, I am unable to get a transition from 1+ started activities to 0 started activities through the trampoline. Through the trampoline, we only ever go from 0 to 1+ started activities, and always remain at 1+ started activities.

    opened by jstaahl 0
  • Easy navigation tracking

    Easy navigation tracking

    Figure out some APIs built on top of our interaction tracking to easily integrate with navigation systems.

    The litmus test will be that it needs to work with our internal nav system as well as Jetpack's nav.

    We also need to figure out inputs to nav and might need to tweak the APIs:

    • Most navs are usually triggers by input
    • Some navs are triggers by async work (e.g. after a loading network call)
    • The first nav is usualled triggers by app launch => this means we can pull up the launch start time. And the end time should be identical. But that'd also mean 2 events (launch + nav), is that right?
    • One simplification we've done internally is that the previous nav is always the previous nav, and that's handled in a centralized way. This might not work if you have several parallel activity tasks and you're switching behind them. Though it might still be interesting to represent it that way.
    opened by pyricau 0
  • Figure out pattern for configuration / setup

    Figure out pattern for configuration / setup

    • Should support init via ContentProvider, direct call, or jetpack startup
    • On init, there's a bunch of work which we want to make it possible to skip / disable as a configuration option. One approach is using XML bool resources. Another approach is to have a "Configurator" class that's defined as an XML string resource and is loaded dynamically. Another option is to make configuration something possible only with manual install, where one passes the config in.
    opened by pyricau 0
Owner
Square
Square
LiteHttp is a simple, intelligent and flexible HTTP framework for Android. With LiteHttp you can make HTTP request with only one line of code! It could convert a java model to the parameter and rander the response JSON as a java model intelligently.

Android network framework: LiteHttp Tags : litehttp2.x-tutorials Website : http://litesuits.com QQgroup : 42960650 , 47357508 Android网络通信为啥子选 lite-htt

马天宇 829 Dec 29, 2022
A small Android project to practice executing network requests and parsing the network response

InspirationalQuotesExercise A small Android project to practice executing network requests and parsing the network response This app uses the ZenQuote

Caren 0 Oct 13, 2021
A tiny tool for syncing times between a local computer and android devices

TimeSync A super tiny tool for syncing times between a local computer and android devices, through adb tool. Screen Shots It uses compose lib and Kotl

DadaaChen 2 Nov 9, 2021
Sandwich was invented for constructing the standardized response interface from the network response

?? A lightweight and standardized Android network response interface for handling successful data and error responses.

Jaewoong Eum 973 Jan 5, 2023
[] Action bar implementation which uses the native action bar on Android 4.0+ and a custom implementation on pre-4.0 through a single API and theme.

DEPRECATED ActionBarSherlock is deprecated. No more development will be taking place. For an up-to-date action bar backport use AppCompat. Thanks for

Jake Wharton 7.1k Dec 24, 2022
Custom view to expand long text with view more,less action , you can customize min lines , action color

ExpandableTextView Custom expadable text view Examples : <mostafa.projects.expandabletextview.ExpandableTextView android:layout_wi

Mostafa Gad 8 Jan 25, 2022
A dual-function menu button that offers a default action as well as the possibility of choosing a different action by selecting from a set of alternatives.

A dual-function menu button that offers a default action as well as the possibility of choosing a different action by selecting from a set of alternatives.

Kojo Fosu Bempa Edue 114 Nov 29, 2022
Akka-in-action-kotlin - Accompanying source code for Akka in Action by Kotlin

Akka実践バイブル Kotlin版サンプルコード ( Accompanying source code for Akka in Action by Kotli

nrs 7 Jul 26, 2022
Automated-build-android-app-with-github-action - CI/CD Automated Build Android App Bundle / APK / Signed With Github Action

Automated Build Android With Using Github Action Project Github Action Script Us

Faisal Amir 34 Dec 19, 2022
Realtime SOS Android Application. Location (GPS + Cellular Network) tracing application by alerting guardians of the User.

WomenSaftey Women Safety Android Application: Realtime SOS Android Application. Designed a Location (GPS + Cellular Network) tracing application by al

jatin kasera 6 Nov 19, 2022
Distributed Tracing for Kotlin

Arrow Tracing Arrow Tracing offers a Entrypoint type, that allows us easily to define a root Span and begin another Span on other services. It provide

ΛRROW 4 Sep 6, 2022
Source++ is an open-source live coding platform. Add breakpoints, logs, metrics, and tracing to live production applications

Source++ is an open-source live coding platform. Add breakpoints, logs, metrics, and distributed tracing to live production software in real-time on-d

Source++ 40 Dec 14, 2022
Android Word/Letter Tracing SDK is a complet solution to build apps for kids learning in pure kotlin

Android Word/Letter Tracing SDK is a complet solution to build apps for kids learning in pure kotlin. It supports all kind of shapes and all language letters e.g. english, arabic, Urdu, hindi etc.

null 9 Oct 16, 2022
An OkHttp interceptor which has pretty logger for request and response. +Mock support

LoggingInterceptor - Interceptor for OkHttp3 with pretty logger Usage val client = OkHttpClient.Builder() client.addInterceptor(LoggingInterceptor

ihsan BAL 1.3k Dec 26, 2022
LiteHttp is a simple, intelligent and flexible HTTP framework for Android. With LiteHttp you can make HTTP request with only one line of code! It could convert a java model to the parameter and rander the response JSON as a java model intelligently.

Android network framework: LiteHttp Tags : litehttp2.x-tutorials Website : http://litesuits.com QQgroup : 42960650 , 47357508 Android网络通信为啥子选 lite-htt

马天宇 829 Dec 29, 2022
A view that makes it easy to debug response data.(一个可以方便调试响应数据的视图。)

JSONRecyclerView 该控件可以方便调试响应数据,如下图所示: 控件的样式参考以下这个网站: JSON在线解析解析及格式化验证 项目的GitHub:JSONRecyclerView 项目Demo的GitHub:JSONRecyclerViewDemo 概述 控件是以RecyclerVie

TanJiaJun 28 Oct 7, 2022
Raccoon is a lightweight response mocking framework that can be easily integrated into the Android UI tests.

Raccoon Medium Articles Checkout these article to get more insights about this library: How to integrate this in your Android Test Why Raccoon? There

Joseph James 52 Aug 15, 2022
Easy Response Mocking for Retrofit using annotations

Response Mocking for Retrofit using annotations. Assume Provides safe and easy way to mock API responses for retrofit-okhttp3.

Aniket Bhoite 25 Nov 16, 2021
A small Android project to practice executing network requests and parsing the network response

InspirationalQuotesExercise A small Android project to practice executing network requests and parsing the network response This app uses the ZenQuote

Caren 0 Oct 13, 2021
An auto IBCS API response status checking tool which test tax, address and account module

IB IBCS API Test Tool An auto IBCS API response status checking tool which test tax, address and account module. Getting Started Cd to the cloned dire

Gabriel Liu 0 Oct 15, 2021