Skip to content

Commit

Permalink
editoast: log stdcm requests
Browse files Browse the repository at this point in the history
Signed-off-by: hamz2a <[email protected]>
  • Loading branch information
hamz2a committed Nov 29, 2024
1 parent 990c8fa commit ea2b2c7
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 9 deletions.
17 changes: 17 additions & 0 deletions editoast/editoast_models/src/tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,21 @@ diesel::table! {
}
}

diesel::table! {
use diesel::sql_types::*;
use postgis_diesel::sql_types::*;

stdcm_logs (id) {
id -> Int8,
#[max_length = 32]
trace_id -> Varchar,
request -> Jsonb,
response -> Jsonb,
created -> Timestamptz,
user_id -> Int8,
}
}

diesel::table! {
use diesel::sql_types::*;
use postgis_diesel::sql_types::*;
Expand Down Expand Up @@ -798,6 +813,7 @@ diesel::joinable!(search_project -> project (id));
diesel::joinable!(search_scenario -> scenario (id));
diesel::joinable!(search_signal -> infra_object_signal (id));
diesel::joinable!(search_study -> study (id));
diesel::joinable!(stdcm_logs -> authn_user (user_id));
diesel::joinable!(stdcm_search_environment -> electrical_profile_set (electrical_profile_set_id));
diesel::joinable!(stdcm_search_environment -> infra (infra_id));
diesel::joinable!(stdcm_search_environment -> temporary_speed_limit_group (temporary_speed_limit_group_id));
Expand Down Expand Up @@ -851,6 +867,7 @@ diesel::allow_tables_to_appear_in_same_query!(
search_signal,
search_study,
search_track,
stdcm_logs,
stdcm_search_environment,
study,
temporary_speed_limit,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE stdcm_logs;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE TABLE stdcm_logs (
id int8 PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
trace_id VARCHAR(32) UNIQUE NOT NULL,
request jsonb NOT NULL,
response jsonb NOT NULL,
created timestamptz NOT NULL DEFAULT NOW(),
user_id bigint NOT NULL REFERENCES authn_user ON DELETE CASCADE
);
64 changes: 64 additions & 0 deletions editoast/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8622,6 +8622,45 @@ components:
type: integer
format: int64
nullable: true
Response:
oneOf:
- type: object
required:
- simulation
- path
- departure_time
- status
properties:
departure_time:
type: string
format: date-time
path:
$ref: '#/components/schemas/PathfindingResultSuccess'
simulation:
$ref: '#/components/schemas/SimulationResponse'
status:
type: string
enum:
- success
- type: object
required:
- status
properties:
status:
type: string
enum:
- path_not_found
- type: object
required:
- error
- status
properties:
error:
$ref: '#/components/schemas/SimulationResponse'
status:
type: string
enum:
- preprocessing_simulation_error
RjsPowerRestrictionRange:
type: object
description: A range along the train path where a power restriction is applied.
Expand Down Expand Up @@ -10228,6 +10267,31 @@ components:
type: array
items:
$ref: '#/components/schemas/RangeAllowance'
StdcmLog:
type: object
required:
- id
- trace_id
- request
- response
- created
- user_id
properties:
created:
type: string
format: date-time
id:
type: integer
format: int64
request:
$ref: '#/components/schemas/Request'
response:
$ref: '#/components/schemas/Response'
trace_id:
type: string
user_id:
type: integer
format: int64
StdcmSearchEnvironment:
type: object
required:
Expand Down
2 changes: 1 addition & 1 deletion editoast/src/core/conflict_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct ConflictDetectionRequest {
pub work_schedules: Option<WorkSchedulesRequest>,
}

#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrainRequirements {
pub start_time: DateTime<Utc>,
pub spacing_requirements: Vec<SpacingRequirement>,
Expand Down
1 change: 1 addition & 0 deletions editoast/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ editoast_common::schemas! {
simulation::schemas(),
pathfinding::schemas(),
conflict_detection::schemas(),
stdcm::schemas(),
}

#[derive(Debug, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion editoast/src/core/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ editoast_common::schemas! {
SimulationResponse,
}

#[derive(Debug, Serialize, Derivative)]
#[derive(Debug, Clone, Serialize, Deserialize, Derivative)]
#[derivative(Hash)]
pub struct PhysicsConsist {
pub effort_curves: EffortCurves,
Expand Down
16 changes: 10 additions & 6 deletions editoast/src/core/stdcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ use super::simulation::SimulationResponse;
use crate::core::AsCoreRequest;
use crate::core::Json;

#[derive(Debug, Serialize)]
editoast_common::schemas! {
Response,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Request {
/// Infrastructure id
pub infra: i64,
Expand Down Expand Up @@ -61,7 +65,7 @@ pub struct Request {
pub temporary_speed_limits: Vec<TemporarySpeedLimit>,
}

#[derive(Debug, Serialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PathItem {
/// The track offsets of the path item
pub locations: Vec<TrackOffset>,
Expand All @@ -72,7 +76,7 @@ pub struct PathItem {
}

/// Contains the data of a step timing, when it is specified
#[derive(Debug, Serialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StepTimingData {
/// Time the train should arrive at this point
pub arrival_time: DateTime<Utc>,
Expand All @@ -83,7 +87,7 @@ pub struct StepTimingData {
}

/// Lighter description of a work schedule, with only the relevant information for core
#[derive(Debug, Serialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkSchedule {
/// Start time as a time delta from the stdcm start time in ms
pub start_time: u64,
Expand All @@ -94,7 +98,7 @@ pub struct WorkSchedule {
}

/// Lighter description of a work schedule with only the relevant information for core
#[derive(Debug, Serialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemporarySpeedLimit {
/// Speed limitation in m/s
pub speed_limit: f64,
Expand All @@ -114,7 +118,7 @@ pub struct UndirectedTrackRange {
pub end: u64,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, ToSchema)]
#[serde(tag = "status", rename_all = "snake_case")]
// We accepted the difference of memory size taken by variants
// Since there is only on success and others are error cases
Expand Down
2 changes: 2 additions & 0 deletions editoast/src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod fixtures;
pub mod infra;
pub mod infra_objects;
pub mod layers;
pub mod stdcm_log;
// We allow unused until models is moved to a separate crate
pub mod auth;
pub mod pagination;
Expand Down Expand Up @@ -41,6 +42,7 @@ editoast_common::schemas! {
infra::schemas(),
projects::schemas(),
rolling_stock_model::schemas(),
stdcm_log::schemas(),
}

#[cfg(test)]
Expand Down
27 changes: 27 additions & 0 deletions editoast/src/models/stdcm_log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use chrono::DateTime;
use chrono::Utc;
use editoast_derive::Model;
use serde::Deserialize;
use serde::Serialize;
use utoipa::ToSchema;

use crate::core::stdcm::Request;
use crate::core::stdcm::Response;

editoast_common::schemas! {
StdcmLog,
}

#[derive(Clone, Debug, Serialize, Deserialize, Model, ToSchema)]
#[model(table = editoast_models::tables::stdcm_logs)]
#[model(gen(ops = c))]
pub struct StdcmLog {
pub id: i64,
pub trace_id: String,
#[model(json)]
pub request: Request,
#[model(json)]
pub response: Response,
created: DateTime<Utc>,
user_id: i64,
}
50 changes: 49 additions & 1 deletion editoast/src/views/timetable/stdcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,24 @@ use chrono::Utc;
use chrono::{DateTime, Duration};
use editoast_authz::BuiltinRole;
use editoast_derive::EditoastError;
use editoast_models::DbConnection;
use editoast_models::DbConnectionPoolV2;
use editoast_schemas::primitives::PositiveDuration;
use editoast_schemas::train_schedule::MarginValue;
use editoast_schemas::train_schedule::Margins;
use editoast_schemas::train_schedule::ReceptionSignal;
use editoast_schemas::train_schedule::ScheduleItem;
use failure_handler::SimulationFailureHandler;
use opentelemetry::trace::TraceContextExt;
use request::convert_steps;
use request::Request;
use serde::Deserialize;
use serde::Serialize;
use std::collections::HashMap;
use std::sync::Arc;
use thiserror::Error;
use tracing::Instrument;
use tracing_opentelemetry::OpenTelemetrySpanExt;
use utoipa::IntoParams;
use utoipa::ToSchema;

Expand All @@ -36,6 +40,7 @@ use crate::core::simulation::{RoutingRequirement, SimulationResponse, SpacingReq
use crate::core::AsCoreRequest;
use crate::core::CoreClient;
use crate::error::Result;
use crate::models::stdcm_log::StdcmLog;
use crate::models::timetable::TimetableWithTrains;
use crate::models::train_schedule::TrainSchedule;
use crate::models::Infra;
Expand All @@ -46,10 +51,14 @@ use crate::views::train_schedule::train_simulation_batch;
use crate::views::AuthenticationExt;
use crate::views::AuthorizationError;
use crate::AppState;
use crate::Model;
use crate::Retrieve;
use crate::RetrieveBatch;
use crate::ValkeyClient;

use super::Changeset;
use super::Create;

editoast_common::schemas! {
request::schemas(),
}
Expand Down Expand Up @@ -251,7 +260,39 @@ async fn stdcm(

let stdcm_response = stdcm_request.fetch(core_client.as_ref()).await?;

// 6. Handle STDCM Core Response
// 6. Check if the current tracing level is debug or lower, and if so, log STDCM request and response
if tracing::level_filters::LevelFilter::current() >= tracing::Level::DEBUG {
let user_id = auth.authorizer()?.user_id();
let stdcm_response_for_spawn = stdcm_response.clone();
let _ = tokio::spawn(
// We intentionally don't bubble up errors here because the spawned task
// runs asynchronously and is not expected to directly affect the caller.
// If errors were propagated, it could introduce unnecessary complexity
// and require additional error handling logic that is not needed in this context.
async move {
match &mut db_pool.get().await {
Ok(conn) => {
let trace_id = tracing::Span::current()
.context()
.span()
.span_context()
.trace_id();
let stdcm_log_changeset = StdcmLog::changeset()
.trace_id(trace_id.to_string())
.request(stdcm_request)
.response(stdcm_response_for_spawn)
.user_id(user_id);
log_stdcm(conn, stdcm_log_changeset).await;
}
Err(_) => tracing::warn!("Database connection failed during log operation."),
}
}
.in_current_span(),
)
.await;
}

// 7. Handle STDCM Core Response
match stdcm_response {
crate::core::stdcm::Response::Success {
simulation,
Expand Down Expand Up @@ -283,6 +324,13 @@ async fn stdcm(
}
}

async fn log_stdcm(conn: &mut DbConnection, stdcm_log_changeset: Changeset<StdcmLog>) {
let _ = stdcm_log_changeset
.create(conn)
.await
.map_err(|e| tracing::error!("Failed during log operation: {e}"));
}

/// Build the list of scheduled train requirements, only including requirements
/// that overlap with the possible simulation times.
fn build_train_requirements(
Expand Down

0 comments on commit ea2b2c7

Please sign in to comment.