Skip to content

Add Telemetry#23

Merged
andres-ixpantia merged 8 commits intoixpantia:mainfrom
manuel-ixpantia:T21
Feb 11, 2026
Merged

Add Telemetry#23
andres-ixpantia merged 8 commits intoixpantia:mainfrom
manuel-ixpantia:T21

Conversation

@manuel-ixpantia
Copy link
Contributor

No description provided.

Copy link
Member

@andyquinterom andyquinterom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En general lo veo super bien!

Creo que los dos puntos principales que tengo son:

  1. Agregar una llave de particion a las tablas y agregar mas parametros para la creacion.

  2. Organizar los schemas de las tablas en un archivo aparte. Así sera facil consultar como se ve la estructura de las tablas.

  3. Utilizar Enums en vez de Strings donde sea posible. Esto nos ayudara a optimizar espacio y hacer las consultas mas rapidas.


Le pedi a gemini que me buscara esos types que podriamos tener como un dictionary type y me dio estos.

Table Field Current Type Recommended Enum Source / Variants
Deployments restart_policy String Maps to crate::service::file::Restart (Always, No, OnFailure, UnlessStopped).
Deployments trigger_type String New TriggerType enum: startup, cron, image_update, manual_reload.
Status state String Based on bollard::config::ContainerStateStatusEnum, extended with not_found and unknown.
Status health_status String Based on bollard::config::HealthStatusEnum (healthy, unhealthy, starting, none).


impl ServiceInstance {
pub async fn run_container(&self) -> Result<(), ServiceConfigError> {
pub async fn run_container(&self, trigger_type: &str) -> Result<(), ServiceConfigError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creo que trigger_type debería ser un Enum. Esto haría un poco mas robusta la implementación, evitaría la posibilidad de equivocarnos en el futuro.

.and_then(|s| s.health.as_ref())
.and_then(|h| h.status.map(|st| st.to_string()))
.unwrap_or_else(|| "none".to_string());
let exit_code = state.and_then(|s| s.exit_code).map(|c| c as i32);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Veo que estos dos campos, tanto health como status son enums.

https://docs.rs/bollard/latest/bollard/config/enum.HealthStatusEnum.html

https://docs.rs/bollard/latest/bollard/config/enum.ContainerStateStatusEnum.html

Dada la naturaleza de estos Enums, creo que seria interesante utilizar estos enums directamente. (O convertir los enums a un enum propio interno de Dispenser).

Esto lo digo por que creo que seria beneficioso escribir estas columnas a las tablas en forma de Enum directamente (en Arrow esto seria un Dictorionary type o en Categorical / Enum en polars)

Que opinas?

telemetry.track_status(
self.config.service.name.clone(),
String::new(),
"not_found".to_string(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creo que si vamos a necesitar nuestro propio enum para incluir estos variantes como NotFound

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creo que para simplificar esto deberiamos tener un archivo llamado schema.rs donde definimos los schemas.

Tambien pienso que todos lo que es un enum dentro de dispenser deberiamos escribirlo como un dictionary type.

Por ejemplo.

#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub enum Restart {
#[serde(alias = "always")]
Always,
#[default]
#[serde(alias = "no", alias = "never")]
No,
#[serde(alias = "on-failure", alias = "on_failure", alias = "onfailure")]
OnFailure,
#[serde(
alias = "unless-stopped",
alias = "unless_stopped",
alias = "unlessstopped"
)]
UnlessStopped,
}

Esto deberia caber en un byte, mientras que un string siempre va a consumir un byte por character.

Ahora le hago un pregunta a gemini para que consolide todos estos tipos.

) -> Result<(), DeltaTableError> {
let table = match deltalake::open_table(table_uri).await {
Ok(table) => table,
Err(DeltaTableError::NotATable(_)) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creo que aqui al crear la tabla necesitamos agregar una llave de particion. Creo que en este caso seria por date. Creo que en este caso seria por date.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Este es un ejemplo de una tabla que creamos para otro servicio de este estilo.

En el ejemplo de abajo hay algunos parametros importantes que creo que tenemos que tomar encuenta.

No digo que tengan que ser asi tal cual, de hecho creo que para este caso AutoOptimizeAutoCompact, AutoOptimizeOptimizeWrite, CheckpointInterval no son tan importantes. Pero puede ser que algunos de los otros sean muy relevantes.

Si te recomiendo 100% crear una funcion de este estilo para tener un lugar para el schema y la creacion de la tabla. Asi esta seria nuestro fuente de la verdad de como se ve la tabla y como se comporta. Esto pienso que iria en ese schema.rs

pub async fn create_table_if_not_exists(
    location: &str,
) -> Result<DeltaTable, deltalake::DeltaTableError> {
    log::info!("create_table_if_not_exists: checking location {}", location);
    let columns = [
        StructField::new("date", DataType::DATE, false),
        StructField::new("timestamp", DataType::TIMESTAMP, false),
        StructField::new("server_id", DataType::STRING, false),
        StructField::new("event_id", DataType::STRING, false),
        StructField::new("script", DataType::STRING, false),
        StructField::new("message", DataType::STRING, true),
    ];
    let result = CreateBuilder::new()
        .with_location(location)
        .with_columns(columns)
        .with_partition_columns(["date"])
        .with_save_mode(SaveMode::Ignore)
        .with_configuration_property(TableProperty::DeletedFileRetentionDuration, Some("1d"))
        .with_configuration_property(TableProperty::LogRetentionDuration, Some("6h"))
        .with_configuration_property(TableProperty::AutoOptimizeAutoCompact, Some("true"))
        .with_configuration_property(TableProperty::AutoOptimizeOptimizeWrite, Some("true"))
        .with_configuration_property(TableProperty::CheckpointInterval, Some("20"))
        .with_configuration_property(TableProperty::TargetFileSize, Some("128MB"))
        .with_configuration_property(
            TableProperty::DataSkippingStatsColumns,
            Some("timestamp,server_id,script,event_id"),
        )
        .await;

    match &result {
        Ok(_) => log::info!("create_table_if_not_exists: success"),
        Err(e) => log::error!("create_table_if_not_exists: failed: {}", e),
    }
    result
}

@andres-ixpantia andres-ixpantia merged commit 0685887 into ixpantia:main Feb 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants