Skip to content

Commit

Permalink
feat: add feature pprof
Browse files Browse the repository at this point in the history
  • Loading branch information
evenyag committed Jun 5, 2023
1 parent e7f1260 commit df393fb
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 66 deletions.
5 changes: 5 additions & 0 deletions src/common/pprof/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Profiling CPU

## Build GreptimeDB with `pprof` feature

```bash
cargo build --features=pprof
```

## HTTP API
Sample at 99 Hertz, for 5 seconds, output report in protobuf format.
Expand Down
3 changes: 2 additions & 1 deletion src/servers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition.workspace = true
license.workspace = true

[features]
pprof = ["dep:common-pprof"]
mem-prof = ["dep:common-mem-prof"]
dashboard = []

Expand All @@ -25,7 +26,7 @@ common-error = { path = "../common/error" }
common-grpc = { path = "../common/grpc" }
common-grpc-expr = { path = "../common/grpc-expr" }
common-mem-prof = { path = "../common/mem-prof", optional = true }
common-pprof = { path = "../common/pprof" }
common-pprof = { path = "../common/pprof", optional = true }
common-query = { path = "../common/query" }
common-recordbatch = { path = "../common/recordbatch" }
common-runtime = { path = "../common/runtime" }
Expand Down
2 changes: 2 additions & 0 deletions src/servers/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ pub enum Error {
location: Location,
},

#[cfg(feature = "pprof")]
#[snafu(display("Failed to dump pprof data, source: {}", source))]
DumpPprof {
#[snafu(backtrace)]
Expand Down Expand Up @@ -348,6 +349,7 @@ impl ErrorExt for Error {
}
}

#[cfg(feature = "pprof")]
DumpPprof { source, .. } => source.status_code(),
}
}
Expand Down
14 changes: 0 additions & 14 deletions src/servers/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,20 +503,6 @@ impl HttpServer {
);
}

// prof routers
// router = router.nest(
// &format!("/{HTTP_API_VERSION}/prof"),
// Router::new()
// .route(
// "/cpu",
// routing::get(pprof::pprof_handler).post(pprof::pprof_handler),
// )
// .route(
// "/mem",
// routing::get(mem_prof::mem_prof_handler).post(mem_prof::mem_prof_handler),
// ),
// );

if let Some(metrics_handler) = self.metrics_handler {
router = router.nest("", self.route_metrics(metrics_handler));
}
Expand Down
123 changes: 72 additions & 51 deletions src/servers/src/http/pprof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,66 +12,87 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::num::NonZeroI32;
use std::time::Duration;
#[cfg(feature = "pprof")]
pub mod handler {
use std::num::NonZeroI32;
use std::time::Duration;

use axum::extract::Query;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use common_pprof::Profiling;
use common_telemetry::logging;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use snafu::ResultExt;
use axum::extract::Query;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use common_pprof::Profiling;
use common_telemetry::logging;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use snafu::ResultExt;

use crate::error::{DumpPprofSnafu, Result};
use crate::error::{DumpPprofSnafu, Result};

/// Output format.
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Output {
/// google’s pprof format report in protobuf.
Proto,
/// Simple text format.
Text,
/// svg flamegraph.
Flamegraph,
}
/// Output format.
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Output {
/// google’s pprof format report in protobuf.
Proto,
/// Simple text format.
Text,
/// svg flamegraph.
Flamegraph,
}

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(default)]
pub struct PprofQuery {
seconds: u64,
frequency: NonZeroI32,
output: Output,
}
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(default)]
pub struct PprofQuery {
seconds: u64,
frequency: NonZeroI32,
output: Output,
}

impl Default for PprofQuery {
fn default() -> PprofQuery {
PprofQuery {
seconds: 5,
// Safety: 99 is non zero.
frequency: NonZeroI32::new(99).unwrap(),
output: Output::Proto,
impl Default for PprofQuery {
fn default() -> PprofQuery {
PprofQuery {
seconds: 5,
// Safety: 99 is non zero.
frequency: NonZeroI32::new(99).unwrap(),
output: Output::Proto,
}
}
}
}

#[axum_macros::debug_handler]
pub async fn pprof_handler(Query(req): Query<PprofQuery>) -> Result<impl IntoResponse> {
logging::info!("start pprof, request: {:?}", req);
#[axum_macros::debug_handler]
pub async fn pprof_handler(Query(req): Query<PprofQuery>) -> Result<impl IntoResponse> {
logging::info!("start pprof, request: {:?}", req);

let profiling = Profiling::new(Duration::from_secs(req.seconds), req.frequency.into());
let body = match req.output {
Output::Proto => profiling.dump_proto().await.context(DumpPprofSnafu)?,
Output::Text => {
let report = profiling.report().await.context(DumpPprofSnafu)?;
format!("{:?}", report).into_bytes()
}
Output::Flamegraph => profiling.dump_flamegraph().await.context(DumpPprofSnafu)?,
};
let profiling = Profiling::new(Duration::from_secs(req.seconds), req.frequency.into());
let body = match req.output {
Output::Proto => profiling.dump_proto().await.context(DumpPprofSnafu)?,
Output::Text => {
let report = profiling.report().await.context(DumpPprofSnafu)?;
format!("{:?}", report).into_bytes()
}
Output::Flamegraph => profiling.dump_flamegraph().await.context(DumpPprofSnafu)?,
};

logging::info!("finish pprof");
logging::info!("finish pprof");

Ok((StatusCode::OK, body))
Ok((StatusCode::OK, body))
}
}

#[cfg(not(feature = "pprof"))]
pub mod handler {
use axum::http::StatusCode;
use axum::response::IntoResponse;

use crate::error::Result;

#[axum_macros::debug_handler]
pub async fn pprof_handler() -> Result<impl IntoResponse> {
Ok((
StatusCode::NOT_IMPLEMENTED,
"The 'pprof' feature is disabled",
))
}
}

pub use handler::pprof_handler;

0 comments on commit df393fb

Please sign in to comment.