1*d57664e9SAndroid Build Coastguard Worker# ProtoLogTool 2*d57664e9SAndroid Build Coastguard Worker 3*d57664e9SAndroid Build Coastguard WorkerCode transformation tool and viewer for ProtoLog. 4*d57664e9SAndroid Build Coastguard Worker 5*d57664e9SAndroid Build Coastguard Worker## What does it do? 6*d57664e9SAndroid Build Coastguard Worker 7*d57664e9SAndroid Build Coastguard WorkerProtoLogTool incorporates three different modes of operation: 8*d57664e9SAndroid Build Coastguard Worker 9*d57664e9SAndroid Build Coastguard Worker### Code transformation 10*d57664e9SAndroid Build Coastguard Worker 11*d57664e9SAndroid Build Coastguard WorkerCommand: `protologtool transform-protolog-calls 12*d57664e9SAndroid Build Coastguard Worker --protolog-class <protolog class name> 13*d57664e9SAndroid Build Coastguard Worker --loggroups-class <protolog groups class name> 14*d57664e9SAndroid Build Coastguard Worker --loggroups-jar <config jar path> 15*d57664e9SAndroid Build Coastguard Worker --viewer-config-file-path <protobuf viewer config file path> 16*d57664e9SAndroid Build Coastguard Worker --legacy-viewer-config-file-path <legacy json.gz viewer config file path> 17*d57664e9SAndroid Build Coastguard Worker --legacy-output-file-path <.winscope file path to write the legacy trace to> 18*d57664e9SAndroid Build Coastguard Worker --output-srcjar <output.srcjar> 19*d57664e9SAndroid Build Coastguard Worker [<input.java>]` 20*d57664e9SAndroid Build Coastguard Worker 21*d57664e9SAndroid Build Coastguard WorkerIn this mode ProtoLogTool transforms every ProtoLog logging call in form of: 22*d57664e9SAndroid Build Coastguard Worker```java 23*d57664e9SAndroid Build Coastguard WorkerProtoLog.x(ProtoLogGroup.GROUP_NAME, "Format string %d %s", value1, value2); 24*d57664e9SAndroid Build Coastguard Worker``` 25*d57664e9SAndroid Build Coastguard Workerinto: 26*d57664e9SAndroid Build Coastguard Worker```java 27*d57664e9SAndroid Build Coastguard Workerif (ProtoLogImpl.isEnabled(GROUP_NAME)) { 28*d57664e9SAndroid Build Coastguard Worker int protoLogParam0 = value1; 29*d57664e9SAndroid Build Coastguard Worker String protoLogParam1 = String.valueOf(value2); 30*d57664e9SAndroid Build Coastguard Worker ProtoLogImpl.x(ProtoLogGroup.GROUP_NAME, 123456, 0b0100, "Format string %d %s or null", protoLogParam0, protoLogParam1); 31*d57664e9SAndroid Build Coastguard Worker} 32*d57664e9SAndroid Build Coastguard Worker``` 33*d57664e9SAndroid Build Coastguard Workerwhere `ProtoLog`, `ProtoLogImpl` and `ProtoLogGroup` are the classes provided as arguments 34*d57664e9SAndroid Build Coastguard Worker (can be imported, static imported or full path, wildcard imports are not allowed) and, `x` is the 35*d57664e9SAndroid Build Coastguard Worker logging method. The transformation is done on the source level. A hash is generated from the format 36*d57664e9SAndroid Build Coastguard Worker string, log level and log group name and inserted after the `ProtoLogGroup` argument. After the hash 37*d57664e9SAndroid Build Coastguard Worker we insert a bitmask specifying the types of logged parameters. The format string is replaced 38*d57664e9SAndroid Build Coastguard Worker by `null` if `ProtoLogGroup.GROUP_NAME.isLogToLogcat()` returns false. If `ProtoLogGroup.GROUP_NAME.isEnabled()` 39*d57664e9SAndroid Build Coastguard Worker returns false the log statement is removed entirely from the resultant code. The real generated code is inlined 40*d57664e9SAndroid Build Coastguard Worker and a number of new line characters is added as to preserve line numbering in file. 41*d57664e9SAndroid Build Coastguard Worker 42*d57664e9SAndroid Build Coastguard WorkerInput is provided as a list of java source file names. Transformed source is saved to a single 43*d57664e9SAndroid Build Coastguard Workersource jar file. The ProtoLogGroup class with all dependencies should be provided as a compiled 44*d57664e9SAndroid Build Coastguard Workerjar file (config.jar). 45*d57664e9SAndroid Build Coastguard Worker 46*d57664e9SAndroid Build Coastguard Worker### Viewer config generation 47*d57664e9SAndroid Build Coastguard Worker 48*d57664e9SAndroid Build Coastguard WorkerCommand: `generate-viewer-config 49*d57664e9SAndroid Build Coastguard Worker --protolog-class <protolog class name> 50*d57664e9SAndroid Build Coastguard Worker --loggroups-class <protolog groups class name> 51*d57664e9SAndroid Build Coastguard Worker --loggroups-jar <config jar path> 52*d57664e9SAndroid Build Coastguard Worker --viewer-config-type <proto|json> 53*d57664e9SAndroid Build Coastguard Worker --viewer-config <viewer.json> 54*d57664e9SAndroid Build Coastguard Worker [<input.java>]` 55*d57664e9SAndroid Build Coastguard Worker 56*d57664e9SAndroid Build Coastguard WorkerThis command is similar in it's syntax to the previous one, only instead of creating a processed source jar 57*d57664e9SAndroid Build Coastguard Workerit writes a viewer configuration file with following schema: 58*d57664e9SAndroid Build Coastguard Worker```json 59*d57664e9SAndroid Build Coastguard Worker{ 60*d57664e9SAndroid Build Coastguard Worker "version": "1.0.0", 61*d57664e9SAndroid Build Coastguard Worker "messages": { 62*d57664e9SAndroid Build Coastguard Worker "123456": { 63*d57664e9SAndroid Build Coastguard Worker "message": "Format string %d %s", 64*d57664e9SAndroid Build Coastguard Worker "level": "ERROR", 65*d57664e9SAndroid Build Coastguard Worker "group": "GROUP_NAME", 66*d57664e9SAndroid Build Coastguard Worker "at": "com\/android\/server\/example\/Class.java" 67*d57664e9SAndroid Build Coastguard Worker } 68*d57664e9SAndroid Build Coastguard Worker }, 69*d57664e9SAndroid Build Coastguard Worker "groups": { 70*d57664e9SAndroid Build Coastguard Worker "GROUP_NAME": { 71*d57664e9SAndroid Build Coastguard Worker "tag": "TestLog" 72*d57664e9SAndroid Build Coastguard Worker } 73*d57664e9SAndroid Build Coastguard Worker } 74*d57664e9SAndroid Build Coastguard Worker} 75*d57664e9SAndroid Build Coastguard Worker 76*d57664e9SAndroid Build Coastguard Worker``` 77*d57664e9SAndroid Build Coastguard Worker 78*d57664e9SAndroid Build Coastguard Worker### Binary log viewing 79*d57664e9SAndroid Build Coastguard Worker 80*d57664e9SAndroid Build Coastguard WorkerCommand: `read-log --viewer-config <viewer.json> <wm_log.pb>` 81*d57664e9SAndroid Build Coastguard Worker 82*d57664e9SAndroid Build Coastguard WorkerReads the binary ProtoLog log file and outputs a human-readable LogCat-like text log. 83*d57664e9SAndroid Build Coastguard Worker 84*d57664e9SAndroid Build Coastguard Worker## What is ProtoLog? 85*d57664e9SAndroid Build Coastguard Worker 86*d57664e9SAndroid Build Coastguard WorkerProtoLog is a generic logging system created for the WindowManager project. It allows both binary and text logging 87*d57664e9SAndroid Build Coastguard Workerand is tunable in runtime. It consists of 3 different submodules: 88*d57664e9SAndroid Build Coastguard Worker* logging system built-in the Android app, 89*d57664e9SAndroid Build Coastguard Worker* log viewer for reading binary logs, 90*d57664e9SAndroid Build Coastguard Worker* a code processing tool. 91*d57664e9SAndroid Build Coastguard Worker 92*d57664e9SAndroid Build Coastguard WorkerProtoLog is designed to reduce both application size (and by that memory usage) and amount of resources needed 93*d57664e9SAndroid Build Coastguard Workerfor logging. This is achieved by replacing log message strings with their hashes and only loading to memory/writing 94*d57664e9SAndroid Build Coastguard Workerfull log messages when necessary. 95*d57664e9SAndroid Build Coastguard Worker 96*d57664e9SAndroid Build Coastguard Worker### Text logging 97*d57664e9SAndroid Build Coastguard Worker 98*d57664e9SAndroid Build Coastguard WorkerFor text-based logs Android LogCat is used as a backend. Message strings are loaded from a viewer config 99*d57664e9SAndroid Build Coastguard Workerlocated on the device when needed. 100*d57664e9SAndroid Build Coastguard Worker 101*d57664e9SAndroid Build Coastguard Worker### Binary logging 102*d57664e9SAndroid Build Coastguard Worker 103*d57664e9SAndroid Build Coastguard WorkerBinary logs are saved as Protocol Buffers file. They can be read using the ProtoLog tool or specialised 104*d57664e9SAndroid Build Coastguard Workerviewer like Winscope. 105*d57664e9SAndroid Build Coastguard Worker 106*d57664e9SAndroid Build Coastguard Worker## How to use ProtoLog? 107*d57664e9SAndroid Build Coastguard Worker 108*d57664e9SAndroid Build Coastguard Worker### Adding a new logging group or log statement 109*d57664e9SAndroid Build Coastguard Worker 110*d57664e9SAndroid Build Coastguard WorkerTo add a new ProtoLogGroup simple create a new enum ProtoLogGroup member with desired parameters. 111*d57664e9SAndroid Build Coastguard Worker 112*d57664e9SAndroid Build Coastguard WorkerTo add a new logging statement just add a new call to ProtoLog.x where x is a log level. 113*d57664e9SAndroid Build Coastguard Worker 114*d57664e9SAndroid Build Coastguard WorkerAfter doing any changes to logging groups or statements you should build the project and follow instructions printed by the tool. 115*d57664e9SAndroid Build Coastguard Worker 116*d57664e9SAndroid Build Coastguard Worker## How to change settings on device in runtime? 117*d57664e9SAndroid Build Coastguard WorkerUse the `adb shell su root cmd window logging` command. To get help just type 118*d57664e9SAndroid Build Coastguard Worker`adb shell su root cmd window logging help`. 119*d57664e9SAndroid Build Coastguard Worker 120*d57664e9SAndroid Build Coastguard Worker 121*d57664e9SAndroid Build Coastguard Worker 122*d57664e9SAndroid Build Coastguard Worker 123