-
Couldn't load subscription status.
- Fork 104
feat(ourlog): Add vercel log drain endpoint #5212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d25fc99
a3db213
8879201
488f625
9b82fa6
04d7f39
a5c492f
84b2224
797693a
e901b67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| pub mod otlp; | ||
| pub mod vercel; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| use axum::extract::DefaultBodyLimit; | ||
| use axum::http::StatusCode; | ||
| use axum::response::IntoResponse; | ||
| use axum::routing::{MethodRouter, post}; | ||
| use relay_config::Config; | ||
| use relay_dynamic_config::Feature; | ||
|
|
||
| use crate::endpoints::common; | ||
| use crate::envelope::ContentType; | ||
| use crate::extractors::{IntegrationBuilder, RawContentType}; | ||
| use crate::integrations::{LogsIntegration, VercelLogDrainFormat}; | ||
| use crate::service::ServiceState; | ||
|
|
||
| /// All routes configured for the Vercel integration. | ||
| /// | ||
| /// The integration currently supports the following endpoints: | ||
| /// - Vercel Log Drain | ||
| pub fn routes(config: &Config) -> axum::Router<ServiceState> { | ||
| axum::Router::new() | ||
| .route("/logs", logs::route(config)) | ||
| .route("/logs/", logs::route(config)) | ||
| } | ||
|
|
||
| mod logs { | ||
| use super::*; | ||
|
|
||
| async fn handle( | ||
| content_type: RawContentType, | ||
| state: ServiceState, | ||
| builder: IntegrationBuilder, | ||
| ) -> axum::response::Result<impl IntoResponse> { | ||
| let format = match ContentType::from(content_type.as_ref()) { | ||
| ContentType::Json => VercelLogDrainFormat::Json, | ||
| ContentType::NdJson => VercelLogDrainFormat::NdJson, | ||
| _ => return Ok(StatusCode::UNSUPPORTED_MEDIA_TYPE), | ||
| }; | ||
|
|
||
| let envelope = builder | ||
| .with_type(LogsIntegration::VercelDrainLog { format }) | ||
| .with_required_feature(Feature::VercelLogDrainEndpoint) | ||
| .build(); | ||
|
|
||
| common::handle_envelope(&state, envelope).await?; | ||
|
|
||
| Ok(StatusCode::ACCEPTED) | ||
| } | ||
|
|
||
| pub fn route(config: &Config) -> MethodRouter<ServiceState> { | ||
| post(handle).route_layer(DefaultBodyLimit::max(config.max_envelope_size())) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| use relay_event_schema::protocol::OurLog; | ||
| use relay_ourlogs::VercelLog; | ||
|
|
||
| use crate::integrations::VercelLogDrainFormat; | ||
| use crate::processing::logs::{Error, Result}; | ||
| use crate::services::outcome::DiscardReason; | ||
|
|
||
| /// Expands Vercel logs into the [`OurLog`] format. | ||
| pub fn expand<F>(format: VercelLogDrainFormat, payload: &[u8], mut produce: F) -> Result<()> | ||
| where | ||
| F: FnMut(OurLog), | ||
| { | ||
| let mut count: i32 = 0; | ||
|
|
||
| match format { | ||
| VercelLogDrainFormat::Json => { | ||
| let logs = serde_json::from_slice::<Vec<VercelLog>>(payload).map_err(|e| { | ||
| relay_log::debug!( | ||
| error = &e as &dyn std::error::Error, | ||
| "Failed to parse logs data as JSON" | ||
| ); | ||
| Error::Invalid(DiscardReason::InvalidJson) | ||
| })?; | ||
|
|
||
| for log in logs { | ||
| count += 1; | ||
| let ourlog = relay_ourlogs::vercel_log_to_sentry_log(log); | ||
| produce(ourlog); | ||
| } | ||
| } | ||
| VercelLogDrainFormat::NdJson => { | ||
| for line in payload.split(|&b| b == b'\n') { | ||
| if line.is_empty() { | ||
| continue; | ||
| } | ||
|
|
||
| if let Ok(log) = serde_json::from_slice::<VercelLog>(line) { | ||
| count += 1; | ||
| let ourlog = relay_ourlogs::vercel_log_to_sentry_log(log); | ||
| produce(ourlog); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
| } | ||
| } | ||
|
|
||
| if count == 0 { | ||
| relay_log::debug!("Failed to parse any logs from vercel log drain payload"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does output when you get empty arrays, but this is unexpected from the log drain endpoint. After implementing this I also realized that we could return the |
||
| return Err(Error::Invalid(DiscardReason::InvalidJson)); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.