1// Copyright (C) 2018 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {Actions} from '../common/actions'; 16import {TraceSource} from '../common/state'; 17import * as trace_to_text from '../gen/trace_to_text'; 18 19import {globals} from './globals'; 20 21export function ConvertTrace(trace: Blob, truncate?: 'start'|'end') { 22 const mod = trace_to_text({ 23 noInitialRun: true, 24 locateFile: (s: string) => s, 25 print: updateStatus, 26 printErr: updateStatus, 27 onRuntimeInitialized: () => { 28 updateStatus('Converting trace'); 29 const outPath = '/trace.json'; 30 if (truncate === undefined) { 31 mod.callMain(['json', '/fs/trace.proto', outPath]); 32 } else { 33 mod.callMain( 34 ['json', '--truncate', truncate, '/fs/trace.proto', outPath]); 35 } 36 updateStatus('Trace conversion completed'); 37 const fsNode = mod.FS.lookupPath(outPath).node; 38 const data = fsNode.contents.buffer; 39 const size = fsNode.usedBytes; 40 globals.publish('LegacyTrace', {data, size}, /*transfer=*/[data]); 41 mod.FS.unlink(outPath); 42 }, 43 onAbort: () => { 44 console.log('ABORT'); 45 }, 46 }); 47 mod.FS.mkdir('/fs'); 48 mod.FS.mount( 49 mod.FS.filesystems.WORKERFS, 50 {blobs: [{name: 'trace.proto', data: trace}]}, 51 '/fs'); 52 53 // TODO removeme. 54 (self as {} as {mod: {}}).mod = mod; 55} 56 57export async function ConvertTraceToPprof( 58 pid: number, src: TraceSource, ts1: number, ts2?: number) { 59 generateBlob(src).then(result => { 60 const mod = trace_to_text({ 61 noInitialRun: true, 62 locateFile: (s: string) => s, 63 print: updateStatus, 64 printErr: updateStatus, 65 onRuntimeInitialized: () => { 66 updateStatus('Converting trace'); 67 const timestamps = `${ts1}${ts2 === undefined ? '' : `,${ts2}`}`; 68 mod.callMain([ 69 'profile', 70 `--pid`, 71 `${pid}`, 72 `--timestamps`, 73 timestamps, 74 '/fs/trace.proto' 75 ]); 76 updateStatus('Trace conversion completed'); 77 const heapDirName = 78 Object.keys(mod.FS.lookupPath('/tmp/').node.contents)[0]; 79 const heapDirContents = 80 mod.FS.lookupPath(`/tmp/${heapDirName}`).node.contents; 81 const heapDumpFiles = Object.keys(heapDirContents); 82 let fileNum = 0; 83 heapDumpFiles.forEach(heapDump => { 84 const fileContents = 85 mod.FS.lookupPath(`/tmp/${heapDirName}/${heapDump}`) 86 .node.contents; 87 fileNum++; 88 const fileName = `/heap_dump.${fileNum}.${pid}.pb`; 89 downloadFile(new Blob([fileContents]), fileName); 90 }); 91 updateStatus('Profile(s) downloaded'); 92 }, 93 onAbort: () => { 94 console.log('ABORT'); 95 }, 96 }); 97 mod.FS.mkdir('/fs'); 98 mod.FS.mount( 99 mod.FS.filesystems.WORKERFS, 100 {blobs: [{name: 'trace.proto', data: result}]}, 101 '/fs'); 102 }); 103} 104 105async function generateBlob(src: TraceSource) { 106 let blob: Blob = new Blob(); 107 if (src.type === 'URL') { 108 const resp = await fetch(src.url); 109 if (resp.status !== 200) { 110 throw new Error(`fetch() failed with HTTP error ${resp.status}`); 111 } 112 blob = await resp.blob(); 113 } else if (src.type === 'ARRAY_BUFFER') { 114 blob = new Blob([new Uint8Array(src.buffer, 0, src.buffer.byteLength)]); 115 } else if (src.type === 'FILE') { 116 blob = src.file; 117 } else { 118 throw new Error(`Conversion not supported for ${JSON.stringify(src)}`); 119 } 120 return blob; 121} 122 123function downloadFile(file: Blob, name: string) { 124 globals.publish('FileDownload', {file, name}); 125} 126 127function updateStatus(msg: {}) { 128 console.log(msg); 129 globals.dispatch(Actions.updateStatus({ 130 msg: msg.toString(), 131 timestamp: Date.now() / 1000, 132 })); 133} 134