├── varanus ├── src │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── yelp │ │ │ └── android │ │ │ └── varanus │ │ │ ├── shutoff │ │ │ ├── NetworkShutoffLogPersister.kt │ │ │ ├── NetworkShutoffLog.kt │ │ │ ├── CategoryOfTrafficShutoff.kt │ │ │ └── NetworkShutoffManager.kt │ │ │ ├── util │ │ │ └── JobBasedScope.kt │ │ │ ├── EndpointKeyExtractor.kt │ │ │ ├── NetworkTrafficLog.kt │ │ │ ├── NetworkTrafficLogPersister.kt │ │ │ ├── okhttp │ │ │ ├── ProgressResponseBody.kt │ │ │ └── TrafficMonitorInterceptor.kt │ │ │ ├── NetworkMonitor.kt │ │ │ ├── LogUploadingManager.kt │ │ │ └── EndpointSpecificNetworkTracker.kt │ └── test │ │ └── java │ │ └── com │ │ └── yelp │ │ └── android │ │ └── varanus │ │ ├── TestClock.kt │ │ ├── shutoff │ │ ├── TestConfig.kt │ │ ├── TestNetworkShutoffLogPersister.kt │ │ ├── NetworkShutoffManagerTest.kt │ │ ├── PerEndpointNetworkShutoffManagerTest.kt │ │ └── GlobalNetworkShutoffManagerTest.kt │ │ ├── TestLogUploader.kt │ │ ├── EndpointSpecificNetworkTrackerTest.kt │ │ └── LogUploadingManagerTest.kt └── build.gradle ├── VARANUS-LIZARD.png ├── settings.gradle ├── documentation └── images │ ├── overview.png │ ├── network_logging.png │ ├── network_shutoff.png │ └── network_shutoff_states.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── sampleapp ├── src │ └── main │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── styles.xml │ │ │ └── strings.xml │ │ ├── menu │ │ │ └── menu_monitor_lizard.xml │ │ ├── layout │ │ │ ├── activity_monitor_lizard.xml │ │ │ └── content_monitor_lizard.xml │ │ └── drawable │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ └── com │ │ │ └── yelp │ │ │ └── varanussampleapp │ │ │ ├── AppEndpointKeyExtractor.kt │ │ │ ├── persistence │ │ │ ├── RealmNetworkShutoffLog.kt │ │ │ ├── RealmNetworkLog.kt │ │ │ ├── PersistentDataRepo.kt │ │ │ ├── AppNetworkTrafficLogPersister.kt │ │ │ └── AppNetworkShutoffLogPersister.kt │ │ │ ├── LogUploader.kt │ │ │ ├── FakeCdnInterceptor.kt │ │ │ ├── MonitorLizardOkhttpClientFactory.kt │ │ │ └── MonitorLizardActivity.kt │ │ └── AndroidManifest.xml ├── README.md ├── proguard-rules.pro └── build.gradle ├── CHANGELOG.md ├── .travis.yml ├── module.gradle ├── gradle.properties ├── LICENSE ├── .gitignore ├── publishing.gradle ├── static_analysis_config ├── checkstyle_config.xml ├── pmd_ruleset_config.xml └── detekt_config.yml ├── gradlew.bat ├── gradlew └── README.md /varanus/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /VARANUS-LIZARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/VARANUS-LIZARD.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':sampleapp' 2 | include ':varanus' 3 | include ':varanus-testing' 4 | -------------------------------------------------------------------------------- /documentation/images/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/documentation/images/overview.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /documentation/images/network_logging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/documentation/images/network_logging.png -------------------------------------------------------------------------------- /documentation/images/network_shutoff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/documentation/images/network_shutoff.png -------------------------------------------------------------------------------- /documentation/images/network_shutoff_states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/documentation/images/network_shutoff_states.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sampleapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/android-varanus/HEAD/sampleapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Varanus releases 2 | 3 | # Version 3.0.0 4 | * Bump OkHTTP to 4.5.0 5 | * Bump Java to 1.8 6 | 7 | # Version 2.0.2 8 | * First official public Varanus release 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /sampleapp/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /varanus/src/test/java/com/yelp/android/varanus/TestClock.kt: -------------------------------------------------------------------------------- 1 | package com.yelp.android.varanus 2 | 3 | import com.google.android.gms.common.util.Clock 4 | 5 | class TestClock : Clock { 6 | var time = 10L 7 | private var nanoTime = 10_000L 8 | override fun currentTimeMillis() = time 9 | override fun elapsedRealtime() = time 10 | override fun currentThreadTimeMillis() = time 11 | override fun nanoTime() = nanoTime 12 | } 13 | -------------------------------------------------------------------------------- /sampleapp/README.md: -------------------------------------------------------------------------------- 1 | This activity demonstrates the functionality of Varanus as follows. 2 | 3 | The app is a simple game where you feed a monitor lizard three different types of food, of different 4 | sizes. This "food" actually sends network requests of different sizes. No more than every 10 5 | seconds, the monitor lizard "wakes up" and "eats" the food, thus logging how much has been eaten 6 | and displaying it to the user. The amount of food eaten persists. -------------------------------------------------------------------------------- /varanus/src/test/java/com/yelp/android/varanus/shutoff/TestConfig.kt: -------------------------------------------------------------------------------- 1 | package com.yelp.android.varanus.shutoff 2 | 3 | import java.util.concurrent.TimeUnit 4 | 5 | object TestConfig { 6 | 7 | val config = NetworkShutoffManager.Config( 8 | TimeUnit.MINUTES.toMillis(5), 9 | 8, // 8 * 5 = 40 minute, 10 | 10, // drop 9 in 10 requests when trying again, 11 | 556, 12 | 555, 13 | TimeUnit.MINUTES.toMillis(5)) 14 | } 15 | -------------------------------------------------------------------------------- /sampleapp/src/main/res/menu/menu_monitor_lizard.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /varanus/src/main/java/com/yelp/android/varanus/shutoff/NetworkShutoffLogPersister.kt: -------------------------------------------------------------------------------- 1 | package com.yelp.android.varanus.shutoff 2 | 3 | /** 4 | * Interface for a persistent database that stores a log of all [EndpointSpecificShutoff] states so 5 | * that if the app is killed the state of the [EndpointSpecificShutoff] can be restored. 6 | */ 7 | interface NetworkShutoffLogPersister { 8 | 9 | fun addAndUpdateLog(log: NetworkShutoffLog) 10 | 11 | fun getLog(endpoint: String): NetworkShutoffLog 12 | 13 | fun getAll(): List 14 | 15 | fun clear(endpoint: String) 16 | } 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | dist: trusty 3 | 4 | android: 5 | components: 6 | - tools 7 | - platform-tools 8 | - build-tools-27.0.3 9 | - build-tools-28.0.3 10 | - android-27 11 | - android-28 12 | 13 | before_cache: 14 | - rm -f ${HOME}/.gradle/caches/modules-2/modules-2.lock 15 | - rm -fr ${HOME}/.gradle/caches/*/plugin-resolution/ 16 | 17 | cache: 18 | directories: 19 | - ${HOME}/.gradle/caches/ 20 | - ${HOME}/.gradle/wrapper/ 21 | - ${HOME}/.m2 22 | - ${HOME}/.android/build-cache 23 | 24 | script: 25 | - ./gradlew build 26 | - ./gradlew publishToMavenLocal 27 | - ./gradlew assembleDebug 28 | - ./gradlew check 29 | -------------------------------------------------------------------------------- /module.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'kotlin-android' 2 | apply plugin: 'io.gitlab.arturbosch.detekt' 3 | 4 | detekt { 5 | toolVersion = Versions.DETEKT 6 | input = files("$projectDir/src") 7 | config = files("$rootDir/static_analysis_config/detekt_config.yml") 8 | } 9 | 10 | dependencies { 11 | // Kotlin 12 | implementation Libs.KOTLIN 13 | implementation Libs.KOTLIN_REFLECT 14 | testImplementation TestLibs.KOTLIN_JUNIT 15 | androidTestImplementation TestLibs.KOTLIN_JUNIT 16 | 17 | // Detekt 18 | detekt Libs.DETEKT 19 | 20 | // Mockito-Kotlin 21 | testImplementation TestLibs.MOCKITO_KOTLIN_2 22 | } 23 | 24 | -------------------------------------------------------------------------------- /varanus/src/test/java/com/yelp/android/varanus/TestLogUploader.kt: -------------------------------------------------------------------------------- 1 | package com.yelp.android.varanus 2 | 3 | import com.yelp.android.varanus.LogUploadingManager.LogUploaderBase 4 | 5 | class TestLogUploader : LogUploaderBase { 6 | var sentLogs = ArrayList() 7 | 8 | override suspend fun uploadTrafficLogSummaryForInterval( 9 | data: Long, 10 | requests: Int, 11 | time_interval: Long, 12 | endpoint: String) { 13 | sentLogs.add(PeriodicLog(data, requests, endpoint)) 14 | } 15 | 16 | data class PeriodicLog(val data: Long, val requests: Int, val endpoint: String) 17 | } 18 | -------------------------------------------------------------------------------- /varanus/src/main/java/com/yelp/android/varanus/shutoff/NetworkShutoffLog.kt: -------------------------------------------------------------------------------- 1 | package com.yelp.android.varanus.shutoff 2 | 3 | /** 4 | * The state of [CategoryOfTrafficShutoff] , containing all the information needed to decide 5 | * whether or not to block an endpoint. 6 | * 7 | * @param state The state of CategoryOfTrafficShutoff, which could be Inactive, Shutoff, 8 | * or Attempting. 9 | * @param backoffSize How much we've been backing off. 10 | * @param shutOffUntil How long we've backed off until. 11 | * @param endpoint The key used to decide which EndpointSpecificShutoff to use. 12 | */ 13 | data class NetworkShutoffLog( 14 | var state: String, 15 | var backoffSize: Int, 16 | var shutOffUntil: Long, 17 | var endpoint: String 18 | ) 19 | -------------------------------------------------------------------------------- /sampleapp/src/main/java/com/yelp/varanussampleapp/AppEndpointKeyExtractor.kt: -------------------------------------------------------------------------------- 1 | package com.yelp.varanussampleapp 2 | 3 | import com.yelp.android.varanus.EndpointKeyExtractor 4 | import okhttp3.Request 5 | 6 | /** 7 | * Based on the network request that was sent, we determine the associate endpoint (or whatever 8 | * other useful category). We keep track of statistics about that endpoint. 9 | */ 10 | class AppEndpointKeyExtractor: EndpointKeyExtractor { 11 | 12 | companion object { 13 | const val FOOD_LABEL = 3 14 | const val SERVICE = 2 15 | } 16 | 17 | override fun getEndpoint(request: Request) = request.url.encodedPathSegments[FOOD_LABEL] 18 | 19 | override fun getType(request: Request) = request.url.encodedPathSegments[SERVICE] 20 | } 21 | 22 | -------------------------------------------------------------------------------- /sampleapp/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |