mirror of
https://github.com/railwayapp/cli
synced 2026-04-21 14:07:23 +00:00
Add attribute logging (#455)
This commit is contained in:
parent
2991137013
commit
068b5f472c
7 changed files with 122 additions and 26 deletions
1
config.toml
Normal file
1
config.toml
Normal file
|
|
@ -0,0 +1 @@
|
|||
Commit message: `config - and fix other things` (default-config)
|
||||
|
|
@ -1,9 +1,15 @@
|
|||
use crate::controllers::{
|
||||
deployment::{stream_build_logs, stream_deploy_logs},
|
||||
environment::get_matched_environment,
|
||||
project::get_project,
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
controllers::{
|
||||
deployment::{stream_build_logs, stream_deploy_logs},
|
||||
environment::get_matched_environment,
|
||||
project::get_project,
|
||||
},
|
||||
util::logs::format_attr_log,
|
||||
};
|
||||
use anyhow::bail;
|
||||
use serde_json::Value;
|
||||
|
||||
use super::{
|
||||
queries::deployments::{DeploymentListInput, DeploymentStatus},
|
||||
|
|
@ -108,13 +114,42 @@ pub async fn command(args: Args, json: bool) -> Result<()> {
|
|||
})
|
||||
.await?;
|
||||
} else {
|
||||
stream_deploy_logs(deployment.id.clone(), |log| {
|
||||
if json {
|
||||
println!("{}", serde_json::to_string(&log).unwrap());
|
||||
} else {
|
||||
println!("{}", log.message);
|
||||
}
|
||||
})
|
||||
stream_deploy_logs(
|
||||
deployment.id.clone(),
|
||||
|log: subscriptions::deployment_logs::LogFields| {
|
||||
if json {
|
||||
let mut map: HashMap<String, Value> = HashMap::new();
|
||||
|
||||
// Insert fixed attributes
|
||||
map.insert(
|
||||
"message".to_string(),
|
||||
serde_json::to_value(log.message.clone()).unwrap(),
|
||||
);
|
||||
map.insert(
|
||||
"timestamp".to_string(),
|
||||
serde_json::to_value(log.timestamp.clone()).unwrap(),
|
||||
);
|
||||
|
||||
// Insert dynamic attributes
|
||||
for attribute in log.attributes {
|
||||
// Trim surrounding quotes if present
|
||||
let value = match attribute.value.trim_matches('"').parse::<Value>() {
|
||||
Ok(value) => value,
|
||||
Err(_) => {
|
||||
serde_json::to_value(attribute.value.trim_matches('"')).unwrap()
|
||||
}
|
||||
};
|
||||
map.insert(attribute.key, value);
|
||||
}
|
||||
|
||||
// Convert HashMap to JSON string
|
||||
let json_string = serde_json::to_string(&map).unwrap();
|
||||
println!("{}", json_string);
|
||||
} else {
|
||||
format_attr_log(log);
|
||||
}
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,10 @@ use crate::{
|
|||
project::get_project,
|
||||
},
|
||||
errors::RailwayError,
|
||||
util::prompt::{prompt_select, PromptService},
|
||||
util::{
|
||||
logs::format_attr_log,
|
||||
prompt::{prompt_select, PromptService},
|
||||
},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
|
@ -325,9 +328,7 @@ pub async fn command(args: Args, _json: bool) -> Result<()> {
|
|||
// Stream deploy logs only if ci flag is not set
|
||||
if !args.ci {
|
||||
tasks.push(tokio::task::spawn(async move {
|
||||
if let Err(e) =
|
||||
stream_deploy_logs(deploy_deployment_id, |log| println!("{}", log.message)).await
|
||||
{
|
||||
if let Err(e) = stream_deploy_logs(deploy_deployment_id, format_attr_log).await {
|
||||
eprintln!("Failed to stream deploy logs: {}", e);
|
||||
}
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
subscription DeploymentLogs(
|
||||
$deploymentId: String!
|
||||
$filter: String
|
||||
$limit: Int
|
||||
) {
|
||||
deploymentLogs(deploymentId: $deploymentId, filter: $filter, limit: $limit) {
|
||||
...LogFields
|
||||
}
|
||||
subscription DeploymentLogs($deploymentId: String!, $filter: String, $limit: Int) {
|
||||
deploymentLogs(deploymentId: $deploymentId, filter: $filter, limit: $limit) {
|
||||
...LogFields
|
||||
}
|
||||
}
|
||||
|
||||
fragment LogFields on Log {
|
||||
timestamp
|
||||
message
|
||||
}
|
||||
timestamp
|
||||
message
|
||||
attributes {
|
||||
key
|
||||
value
|
||||
}
|
||||
}
|
||||
58
src/util/logs.rs
Normal file
58
src/util/logs.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use crate::subscriptions;
|
||||
use colored::Colorize;
|
||||
|
||||
pub fn format_attr_log(log: subscriptions::deployment_logs::LogFields) {
|
||||
// we love inconsistencies!
|
||||
if log.attributes.is_empty()
|
||||
|| (log.attributes.len() == 1
|
||||
&& log
|
||||
.attributes
|
||||
.first()
|
||||
.is_some_and(|attr| attr.key == "level"))
|
||||
{
|
||||
println!("{}", log.message);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut level: Option<String> = None;
|
||||
let message = log.message;
|
||||
let mut others = Vec::new();
|
||||
// get attributes using a match
|
||||
for attr in &log.attributes {
|
||||
match attr.key.to_lowercase().as_str() {
|
||||
"level" | "lvl" | "severity" => level = Some(attr.value.clone()),
|
||||
_ => others.push(format!(
|
||||
"{}{}{}",
|
||||
attr.key.clone().magenta(),
|
||||
"=",
|
||||
attr.value
|
||||
.clone()
|
||||
.normal()
|
||||
.replace('"', "\"".dimmed().to_string().as_str())
|
||||
)),
|
||||
}
|
||||
}
|
||||
// get the level and colour it
|
||||
let level = level
|
||||
.map(|level| {
|
||||
// make it uppercase so we dont have to make another variable
|
||||
// for some reason, .uppercase() removes formatting
|
||||
|
||||
match level.replace('"', "").to_lowercase().as_str() {
|
||||
"info" => "[INFO]".blue(),
|
||||
"error" | "err" => "[ERRO]".red(),
|
||||
"warn" => "[WARN]".yellow(),
|
||||
"debug" => "[DBUG]".dimmed(),
|
||||
_ => format!("[{}]", level).normal(),
|
||||
}
|
||||
.bold()
|
||||
})
|
||||
.unwrap();
|
||||
println!(
|
||||
"{} {} {} {}",
|
||||
log.timestamp.replace('"', "").normal(),
|
||||
level,
|
||||
message,
|
||||
others.join(" ")
|
||||
);
|
||||
}
|
||||
|
|
@ -1 +1,2 @@
|
|||
pub mod logs;
|
||||
pub mod prompt;
|
||||
|
|
|
|||
Loading…
Reference in a new issue