micromegas/servers/perfetto/
perfetto_server.rs

1use crate::client::{
2    flightsql_client_factory::FlightSQLClientFactory, perfetto_trace_client::format_perfetto_trace,
3};
4use anyhow::{Context, Result};
5use chrono::{DateTime, Utc};
6use micromegas_analytics::time::TimeRange;
7use serde::Deserialize;
8use std::sync::Arc;
9
10/// Parameters for fetching a Perfetto trace.
11#[derive(Debug, Deserialize)]
12pub struct FetchTraceParams {
13    pub process_id: String,
14    pub begin: DateTime<Utc>,
15    pub end: DateTime<Utc>,
16}
17
18/// A server for serving Perfetto traces.
19pub struct PerfettoTraceServer {
20    pub client_factory: Arc<dyn FlightSQLClientFactory>,
21}
22
23impl PerfettoTraceServer {
24    /// Creates a new `PerfettoTraceServer`.
25    ///
26    /// # Arguments
27    ///
28    /// * `client_factory` - A factory for creating FlightSQL clients.
29    pub fn new(client_factory: Arc<dyn FlightSQLClientFactory>) -> Self {
30        Self { client_factory }
31    }
32}
33
34/// Shows a Perfetto trace in a web browser.
35///
36/// This function generates an HTML page that embeds the Perfetto UI
37/// and loads the trace data from the `/fetch_trace` endpoint.
38///
39/// # Arguments
40///
41/// * `caller` - The name of the caller, used for display in the HTML.
42/// * `params` - Parameters for fetching the trace, including process ID and time range.
43pub async fn show_trace(caller: &str, params: FetchTraceParams) -> Result<String> {
44    let process_id = params.process_id;
45    let begin = params.begin.to_rfc3339();
46    let end = params.end.to_rfc3339();
47    let content = std::fmt::format(format_args!(
48        include_str!("show_trace.html"),
49        caller = caller,
50        process_id = process_id,
51        begin = begin,
52        end = end
53    ));
54    Ok(content)
55}
56
57/// Fetches a Perfetto trace.
58///
59/// This function retrieves the trace data from the FlightSQL server
60/// and returns it as a `bytes::Bytes` object.
61///
62/// # Arguments
63///
64/// * `server` - The `PerfettoTraceServer` instance.
65/// * `_caller` - The name of the caller (unused in this function).
66/// * `params` - Parameters for fetching the trace, including process ID and time range.
67pub async fn fetch_trace(
68    server: Arc<PerfettoTraceServer>,
69    _caller: &str,
70    params: FetchTraceParams,
71) -> Result<bytes::Bytes> {
72    let process_id = params.process_id;
73    let begin = params.begin;
74    let end = params.end;
75    let mut client = server
76        .client_factory
77        .make_client()
78        .await
79        .with_context(|| "make_client")?;
80    let buffer = format_perfetto_trace(
81        &mut client,
82        &process_id,
83        TimeRange::new(begin, end),
84        crate::client::SpanTypes::Both,
85    )
86    .await
87    .with_context(|| "format_perfetto_trace")?;
88    Ok(buffer.into())
89}