mirror of
https://github.com/neondatabase/neon.git
synced 2025-12-23 06:09:59 +00:00
[proxy]: dont log user errors from postgres (#12412)
## Problem #8843 User initiated sql queries are being classified as "postgres" errors, whereas they're really user errors. ## Summary of changes Classify user-initiated postgres errors as user errors if they are related to a sql query that we ran on their behalf. Do not log those errors.
This commit is contained in:
@@ -78,16 +78,6 @@ pub(crate) trait ReportableError: fmt::Display + Send + 'static {
|
|||||||
fn get_error_kind(&self) -> ErrorKind;
|
fn get_error_kind(&self) -> ErrorKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReportableError for postgres_client::error::Error {
|
|
||||||
fn get_error_kind(&self) -> ErrorKind {
|
|
||||||
if self.as_db_error().is_some() {
|
|
||||||
ErrorKind::Postgres
|
|
||||||
} else {
|
|
||||||
ErrorKind::Compute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Flattens `Result<Result<T>>` into `Result<T>`.
|
/// Flattens `Result<Result<T>>` into `Result<T>`.
|
||||||
pub fn flatten_err<T>(r: Result<anyhow::Result<T>, JoinError>) -> anyhow::Result<T> {
|
pub fn flatten_err<T>(r: Result<anyhow::Result<T>, JoinError>) -> anyhow::Result<T> {
|
||||||
r.context("join error").and_then(|x| x)
|
r.context("join error").and_then(|x| x)
|
||||||
|
|||||||
@@ -404,7 +404,15 @@ impl ReportableError for HttpConnError {
|
|||||||
fn get_error_kind(&self) -> ErrorKind {
|
fn get_error_kind(&self) -> ErrorKind {
|
||||||
match self {
|
match self {
|
||||||
HttpConnError::ConnectionClosedAbruptly(_) => ErrorKind::Compute,
|
HttpConnError::ConnectionClosedAbruptly(_) => ErrorKind::Compute,
|
||||||
HttpConnError::PostgresConnectionError(p) => p.get_error_kind(),
|
HttpConnError::PostgresConnectionError(p) => {
|
||||||
|
if p.as_db_error().is_some() {
|
||||||
|
// postgres rejected the connection
|
||||||
|
ErrorKind::Postgres
|
||||||
|
} else {
|
||||||
|
// couldn't even reach postgres
|
||||||
|
ErrorKind::Compute
|
||||||
|
}
|
||||||
|
}
|
||||||
HttpConnError::LocalProxyConnectionError(_) => ErrorKind::Compute,
|
HttpConnError::LocalProxyConnectionError(_) => ErrorKind::Compute,
|
||||||
HttpConnError::ComputeCtl(_) => ErrorKind::Service,
|
HttpConnError::ComputeCtl(_) => ErrorKind::Service,
|
||||||
HttpConnError::JwtPayloadError(_) => ErrorKind::User,
|
HttpConnError::JwtPayloadError(_) => ErrorKind::User,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use serde_json::Value;
|
|||||||
use serde_json::value::RawValue;
|
use serde_json::value::RawValue;
|
||||||
use tokio::time::{self, Instant};
|
use tokio::time::{self, Instant};
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::{debug, error, info};
|
use tracing::{Level, debug, error, info};
|
||||||
use typed_json::json;
|
use typed_json::json;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@@ -390,12 +390,35 @@ pub(crate) async fn handle(
|
|||||||
let line = get(db_error, |db| db.line().map(|l| l.to_string()));
|
let line = get(db_error, |db| db.line().map(|l| l.to_string()));
|
||||||
let routine = get(db_error, |db| db.routine());
|
let routine = get(db_error, |db| db.routine());
|
||||||
|
|
||||||
tracing::info!(
|
match &e {
|
||||||
kind=error_kind.to_metric_label(),
|
SqlOverHttpError::Postgres(e)
|
||||||
error=%e,
|
if e.as_db_error().is_some() && error_kind == ErrorKind::User =>
|
||||||
msg=message,
|
{
|
||||||
"forwarding error to user"
|
// this error contains too much info, and it's not an error we care about.
|
||||||
);
|
if tracing::enabled!(Level::DEBUG) {
|
||||||
|
tracing::debug!(
|
||||||
|
kind=error_kind.to_metric_label(),
|
||||||
|
error=%e,
|
||||||
|
msg=message,
|
||||||
|
"forwarding error to user"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
tracing::info!(
|
||||||
|
kind = error_kind.to_metric_label(),
|
||||||
|
error = "bad query",
|
||||||
|
"forwarding error to user"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
tracing::info!(
|
||||||
|
kind=error_kind.to_metric_label(),
|
||||||
|
error=%e,
|
||||||
|
msg=message,
|
||||||
|
"forwarding error to user"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
json_response(
|
json_response(
|
||||||
e.get_http_status_code(),
|
e.get_http_status_code(),
|
||||||
@@ -460,7 +483,15 @@ impl ReportableError for SqlOverHttpError {
|
|||||||
SqlOverHttpError::ConnInfo(e) => e.get_error_kind(),
|
SqlOverHttpError::ConnInfo(e) => e.get_error_kind(),
|
||||||
SqlOverHttpError::ResponseTooLarge(_) => ErrorKind::User,
|
SqlOverHttpError::ResponseTooLarge(_) => ErrorKind::User,
|
||||||
SqlOverHttpError::InvalidIsolationLevel => ErrorKind::User,
|
SqlOverHttpError::InvalidIsolationLevel => ErrorKind::User,
|
||||||
SqlOverHttpError::Postgres(p) => p.get_error_kind(),
|
// customer initiated SQL errors.
|
||||||
|
SqlOverHttpError::Postgres(p) => {
|
||||||
|
if p.as_db_error().is_some() {
|
||||||
|
ErrorKind::User
|
||||||
|
} else {
|
||||||
|
ErrorKind::Compute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// proxy initiated SQL errors.
|
||||||
SqlOverHttpError::InternalPostgres(p) => {
|
SqlOverHttpError::InternalPostgres(p) => {
|
||||||
if p.as_db_error().is_some() {
|
if p.as_db_error().is_some() {
|
||||||
ErrorKind::Service
|
ErrorKind::Service
|
||||||
@@ -468,6 +499,7 @@ impl ReportableError for SqlOverHttpError {
|
|||||||
ErrorKind::Compute
|
ErrorKind::Compute
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// postgres returned a bad row format that we couldn't parse.
|
||||||
SqlOverHttpError::JsonConversion(_) => ErrorKind::Postgres,
|
SqlOverHttpError::JsonConversion(_) => ErrorKind::Postgres,
|
||||||
SqlOverHttpError::Cancelled(c) => c.get_error_kind(),
|
SqlOverHttpError::Cancelled(c) => c.get_error_kind(),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user