1/* 2 * Copyright 2020, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import viewerConfig from "ProtoLogJsonSafePath/services.core.protolog.json" 18 19import { nanos_to_string } from './transform.js' 20 21const PROTOLOG_VERSION = "1.0.0" 22 23class FormatStringMismatchError extends Error { 24 constructor(message) { 25 super(message); 26 } 27} 28 29function get_param(arr, idx) { 30 if (arr.length <= idx) { 31 throw new FormatStringMismatchError('No param for format string conversion'); 32 } 33 return arr[idx]; 34} 35 36function format_text(messageFormat, data) { 37 let out = "" 38 const strParams = data.strParams; 39 let strParamsIdx = 0; 40 const sint64Params = data.sint64Params; 41 let sint64ParamsIdx = 0; 42 const doubleParams = data.doubleParams; 43 let doubleParamsIdx = 0; 44 const booleanParams = data.booleanParams; 45 let booleanParamsIdx = 0; 46 for (let i = 0; i < messageFormat.length;) { 47 if (messageFormat[i] == '%') { 48 if (i + 1 >= messageFormat.length) { 49 // Should never happen - protologtool checks for that 50 throw new Error("Invalid format string") 51 } 52 switch (messageFormat[i + 1]) { 53 case '%': 54 out += '%'; 55 break; 56 case 'd': 57 out += get_param(sint64Params, sint64ParamsIdx++).toString(10); 58 break; 59 case 'o': 60 out += get_param(sint64Params, sint64ParamsIdx++).toString(8); 61 break; 62 case 'x': 63 out += get_param(sint64Params, sint64ParamsIdx++).toString(16); 64 break; 65 case 'f': 66 out += get_param(doubleParams, doubleParamsIdx++).toFixed(6); 67 break; 68 case 'e': 69 out += get_param(doubleParams, doubleParamsIdx++).toExponential(); 70 break; 71 case 'g': 72 out += get_param(doubleParams, doubleParamsIdx++).toString(); 73 break; 74 case 's': 75 out += get_param(strParams, strParamsIdx++); 76 break; 77 case 'b': 78 out += get_param(booleanParams, booleanParamsIdx++).toString(); 79 break; 80 default: 81 // Should never happen - protologtool checks for that 82 throw new Error("Invalid format string conversion: " + messageFormat[i + 1]); 83 } 84 i += 2; 85 } else { 86 out += messageFormat[i]; 87 i += 1; 88 } 89 } 90 return out; 91} 92 93function transform_unformatted(entry) { 94 return { 95 text: (entry.messageHash.toString() + ' - [' + entry.strParams.toString() + 96 '] [' + entry.sint64Params.toString() + '] [' + entry.doubleParams.toString() + 97 '] [' + entry.booleanParams.toString() + ']'), 98 time: nanos_to_string(entry.elapsedRealtimeNanos), 99 tag: "INVALID", 100 at: "", 101 timestamp: entry.elapsedRealtimeNanos, 102 }; 103} 104 105function transform_formatted(entry, message) { 106 return { 107 text: format_text(message.message, entry), 108 time: nanos_to_string(entry.elapsedRealtimeNanos), 109 tag: viewerConfig.groups[message.group].tag, 110 at: message.at, 111 timestamp: entry.elapsedRealtimeNanos, 112 }; 113} 114 115function transform_message(entry) { 116 let message = viewerConfig.messages[entry.messageHash] 117 if (message === undefined) { 118 return transform_unformatted(entry); 119 } else { 120 try { 121 return transform_formatted(entry, message); 122 } catch (err) { 123 if (err instanceof FormatStringMismatchError) { 124 return transform_unformatted(entry); 125 } 126 throw err; 127 } 128 } 129} 130 131function transform_protolog(log) { 132 if (log.version !== PROTOLOG_VERSION) { 133 throw new Error('Unsupported log version'); 134 } 135 if (viewerConfig.version !== PROTOLOG_VERSION) { 136 throw new Error('Unsupported viewer config version'); 137 } 138 139 let data = log.log.map(entry => (transform_message(entry))) 140 data.sort(function(a, b) { return a.timestamp - b.timestamp }) 141 let transformed = { 142 children: data 143 } 144 return transformed 145} 146 147export { transform_protolog }; 148