示例#1
0
        /// <summary>
        /// Check if another instance of trace_processor_shell is running on this port
        /// </summary>
        /// <param name="port"></param>
        /// <returns></returns>
        private bool IsPortAvailable(int port)
        {
            try
            {
                TraceProcessorRpc rpc = new TraceProcessorRpc
                {
                    Request = TraceProcessorRpc.Types.TraceProcessorMethod.TpmGetStatus
                };

                // Send the request
                var rpcResult = SendRpcRequest(rpc);

                if (rpcResult.Msg.Count != 1 || rpcResult.Msg[0].Status == null)
                {
                    throw new Exception("Invalid RPC stream result from trace_processor_shell");
                }
                else
                {
                    // If the response contains Perfetto, trace_processor_shell is already running on this port
                    return(!rpcResult.Msg[0].Status.HumanReadableVersion.Contains("Perfetto"));
                }
            }
            catch (HttpRequestException)
            {
                // Exception here is the connection refused message, meaning the RPC server has not been initialized
                // Which means this port is not being used by another trace_processor_shell
                return(true);
            }
        }
示例#2
0
        /// <summary>
        /// Perform a SQL query against trace_processor_shell to gather Perfetto trace data.
        /// </summary>
        /// <param name="sqlQuery">The query to perform against the loaded trace in trace_processor_shell</param>
        /// <returns>List of RPC objects that contain the QueryResults</returns>
        public RepeatedField <TraceProcessorRpc> QueryTrace(string sqlQuery)
        {
            // Make sure ShellProcess is running
            if (ShellProcess == null || ShellProcess.HasExited)
            {
                throw new Exception("The trace_process_shell is not running");
            }

            int cnt = 0;

            // Check if the trace is loaded
            // We know the shell is running, so the trace could still be in the loading process. Give it a little while to finish loading
            // before we error out.
            while (!CheckIfTraceIsLoaded())
            {
                if (cnt++ > MaxRetryLimit)
                {
                    throw new Exception("Unable to query Perfetto trace because trace_processor_shell.exe does not appear to have loaded it");
                }
            }

            TraceProcessorRpc rpc = new TraceProcessorRpc
            {
                Request   = TraceProcessorRpc.Types.TraceProcessorMethod.TpmQueryStreaming,
                QueryArgs = new QueryArgs()
            };

            rpc.QueryArgs.SqlQuery = sqlQuery;
            var rpcResult = SendRpcRequest(rpc);

            return(rpcResult.Msg);
        }
示例#3
0
        /// <summary>
        /// Sends an RPC request to trace_processor_shell. This utilizies the bidirectional pipe that exists with the /rpc endpoint.
        /// TraceProcessorRpcStream objects get passed back and forth
        /// </summary>
        /// <param name="rpc">RPC stream object that contains the request</param>
        /// <returns>RPC stream object that contains the response</returns>
        private TraceProcessorRpcStream SendRpcRequest(TraceProcessorRpc rpc)
        {
            TraceProcessorRpcStream rpcStream = new TraceProcessorRpcStream();

            rpcStream.Msg.Add(rpc);

            TraceProcessorRpcStream returnStream = null;

            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Connection", "keep-alive");
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-protobuf")); //ACCEPT header

                HttpContent sc = new ByteArrayContent(rpcStream.ToByteArray());

                var response  = client.PostAsync($"http://localhost:{HttpPort}/rpc", sc).GetAwaiter().GetResult();
                var byteArray = response.Content.ReadAsByteArrayAsync().Result;
                returnStream = TraceProcessorRpcStream.Parser.ParseFrom(byteArray);
            }
            if (returnStream == null)
            {
                throw new Exception("Problem with the RPC stream returned from trace_processor_shell.exe");
            }
            return(returnStream);
        }
示例#4
0
        /// <summary>
        /// Check if the trace_processor_shell has a loaded trace. Assumes the shell executable is already running. Will throw otherwise.
        /// </summary>
        /// <returns></returns>
        private bool CheckIfTraceIsLoaded()
        {
            if (ShellProcess == null || ShellProcess.HasExited)
            {
                throw new Exception("The trace_process_shell is not running");
            }

            try
            {
                TraceProcessorRpc rpc = new TraceProcessorRpc
                {
                    Request = TraceProcessorRpc.Types.TraceProcessorMethod.TpmGetStatus
                };

                // Send the request
                var rpcResult = SendRpcRequest(rpc);

                if (rpcResult.Msg.Count != 1 || rpcResult.Msg[0].Status == null)
                {
                    throw new Exception("Invalid RPC stream result from trace_processor_shell");
                }
                else
                {
                    return(rpcResult.Msg[0].Status.HasLoadedTraceName);
                }
            }
            catch (HttpRequestException)
            {
                // Exception here is the connection refused message, meaning the RPC server has not been initialized
                return(false);
            }
        }