diff --git a/docker/dev-full/grafana/dashboards/rivet-sqlite.json b/docker/dev-full/grafana/dashboards/rivet-sqlite.json index 77d5e77232..54ae4f0bc8 100644 --- a/docker/dev-full/grafana/dashboards/rivet-sqlite.json +++ b/docker/dev-full/grafana/dashboards/rivet-sqlite.json @@ -430,7 +430,6 @@ }, "id": 17, "interval": "15s", - "maxDataPoints": 50, "options": { "legend": { "calcs": [ @@ -531,7 +530,6 @@ }, "id": 18, "interval": "15s", - "maxDataPoints": 50, "options": { "legend": { "calcs": [], @@ -630,7 +628,6 @@ }, "id": 19, "interval": "15s", - "maxDataPoints": 50, "options": { "legend": { "calcs": [], @@ -743,7 +740,6 @@ }, "id": 23, "interval": "15s", - "maxDataPoints": 50, "options": { "legend": { "calcs": [ @@ -845,7 +841,6 @@ }, "id": 24, "interval": "15s", - "maxDataPoints": 50, "options": { "legend": { "calcs": [ diff --git a/docker/dev-full/grafana/dashboards/traces.json b/docker/dev-full/grafana/dashboards/traces.json index 63e134a98f..f25e8765b1 100644 --- a/docker/dev-full/grafana/dashboards/traces.json +++ b/docker/dev-full/grafana/dashboards/traces.json @@ -107,7 +107,6 @@ "y": 1 }, "id": 2, - "maxDataPoints": 50, "options": { "legend": { "calcs": [], @@ -252,7 +251,6 @@ "y": 10 }, "id": 7, - "maxDataPoints": 50, "options": { "legend": { "calcs": [], @@ -396,7 +394,6 @@ "y": 19 }, "id": 8, - "maxDataPoints": 50, "options": { "legend": { "calcs": [], diff --git a/packages/common/util/core/src/format.rs b/packages/common/util/core/src/format.rs index 29c44bccff..7b95d1b9a3 100644 --- a/packages/common/util/core/src/format.rs +++ b/packages/common/util/core/src/format.rs @@ -143,3 +143,43 @@ pub fn gen_name_id(s: impl AsRef, default: &str) -> String { .chain(hash) .collect::() } + +pub fn duration(ms: i64, relative: bool) -> String { + let neg = ms < 0; + let ms = ms.abs(); + let mut parts = Vec::with_capacity(5); + + if relative && neg { + parts.push("in".to_string()); + } + + if ms == 0 { + parts.push("0ms".to_string()); + } else if ms < 1000 { + parts.push(format!("{ms}ms")); + } else { + let days = ms / 86_400_000; + let hours = (ms % 86_400_000) / 3_600_000; + let minutes = (ms % 3_600_000) / 60_000; + let seconds = (ms % 60_000) / 1_000; + + if days > 0 { + parts.push(format!("{days}d")); + } + if hours > 0 { + parts.push(format!("{hours}h")); + } + if minutes > 0 { + parts.push(format!("{minutes}m")); + } + if ms < 60_000 && seconds > 0 { + parts.push(format!("{seconds}s")); + } + } + + if relative && !neg { + parts.push("ago".to_string()); + } + + parts.join(" ") +} diff --git a/packages/core/services/cluster/src/ops/server/get.rs b/packages/core/services/cluster/src/ops/server/get.rs index 1264f2ef62..8152f28a1a 100644 --- a/packages/core/services/cluster/src/ops/server/get.rs +++ b/packages/core/services/cluster/src/ops/server/get.rs @@ -25,6 +25,7 @@ pub(crate) struct ServerRow { provider_server_id: Option, vlan_ip: Option, public_ip: Option, + create_ts: i64, cloud_destroy_ts: Option, state: i64, } @@ -40,6 +41,7 @@ impl TryFrom for Server { provider_server_id: value.provider_server_id, lan_ip: value.vlan_ip, wan_ip: value.public_ip, + create_ts: value.create_ts, cloud_destroy_ts: value.cloud_destroy_ts, state: unwrap!(ServerState::from_repr(value.state.try_into()?)), }) @@ -58,6 +60,7 @@ pub async fn cluster_server_get(ctx: &OperationCtx, input: &Input) -> GlobalResu provider_server_id, vlan_ip, public_ip, + create_ts, cloud_destroy_ts, CASE WHEN cloud_destroy_ts IS NOT NULL THEN 6 -- Destroyed diff --git a/packages/core/services/cluster/src/ops/server/list.rs b/packages/core/services/cluster/src/ops/server/list.rs index 6483e9f240..a3f99e6cc2 100644 --- a/packages/core/services/cluster/src/ops/server/list.rs +++ b/packages/core/services/cluster/src/ops/server/list.rs @@ -30,6 +30,7 @@ pub async fn cluster_server_list(ctx: &OperationCtx, input: &Input) -> GlobalRes s.provider_server_id, s.vlan_ip, s.public_ip, + s.create_ts, s.cloud_destroy_ts, CASE WHEN s.cloud_destroy_ts IS NOT NULL THEN 6 -- Destroyed diff --git a/packages/core/services/cluster/src/ops/server/lost_list.rs b/packages/core/services/cluster/src/ops/server/lost_list.rs index 9d6094e9cf..6051698ba9 100644 --- a/packages/core/services/cluster/src/ops/server/lost_list.rs +++ b/packages/core/services/cluster/src/ops/server/lost_list.rs @@ -143,7 +143,17 @@ async fn run_for_linode_account( s.provider_server_id, s.vlan_ip, s.public_ip, - s.cloud_destroy_ts + s.create_ts, + s.cloud_destroy_ts, + CASE + WHEN s.cloud_destroy_ts IS NOT NULL THEN 6 -- Destroyed + WHEN s.taint_ts IS NOT NULL AND s.drain_ts IS NOT NULL THEN 5 -- TaintedDraining + WHEN s.drain_ts IS NOT NULL THEN 4 -- Draining + WHEN s.taint_ts IS NOT NULL THEN 3 -- Tainted + WHEN s.install_complete_ts IS NOT NULL THEN 2 -- Running + WHEN s.provision_complete_ts IS NOT NULL THEN 1 -- Installing + ELSE 0 -- Provisioning + END AS state FROM db_cluster.servers AS s JOIN db_cluster.datacenters AS d ON s.datacenter_id = d.datacenter_id diff --git a/packages/core/services/cluster/src/types.rs b/packages/core/services/cluster/src/types.rs index 85694a83de..e554d113b1 100644 --- a/packages/core/services/cluster/src/types.rs +++ b/packages/core/services/cluster/src/types.rs @@ -148,6 +148,7 @@ pub struct Server { pub provider_server_id: Option, pub lan_ip: Option, pub wan_ip: Option, + pub create_ts: i64, pub cloud_destroy_ts: Option, pub state: ServerState, } diff --git a/packages/edge/services/pegboard/src/metrics.rs b/packages/edge/services/pegboard/src/metrics.rs index e133c444ef..1dfcdd9c91 100644 --- a/packages/edge/services/pegboard/src/metrics.rs +++ b/packages/edge/services/pegboard/src/metrics.rs @@ -40,7 +40,7 @@ lazy_static::lazy_static! { pub static ref ENV_CPU_USAGE: IntGaugeVec = register_int_gauge_vec_with_registry!( "pegboard_env_cpu_usage", - "Total percent of CPU (per core) used by an environment.", + "Total millicores used by an environment.", &["env_id", "flavor"], *REGISTRY, ).unwrap(); diff --git a/packages/edge/services/pegboard/src/ops/actor/get.rs b/packages/edge/services/pegboard/src/ops/actor/get.rs index a8103c36c6..7d48338802 100644 --- a/packages/edge/services/pegboard/src/ops/actor/get.rs +++ b/packages/edge/services/pegboard/src/ops/actor/get.rs @@ -133,7 +133,7 @@ pub async fn pegboard_actor_get(ctx: &OperationCtx, input: &Input) -> GlobalResu let pool = &pool; let (actor_row, port_ingress_rows, port_host_rows, port_proxied_rows) = tokio::try_join!( - sql_fetch_one!( + sql_fetch_optional!( [ctx, ActorRow, pool] " SELECT @@ -184,6 +184,11 @@ pub async fn pegboard_actor_get(ctx: &OperationCtx, input: &Input) -> GlobalResu ), )?; + let Some(actor_row) = actor_row else { + tracing::error!(?actor_id, ?workflow_id, "actor has no state row"); + return Ok(None); + }; + GlobalResult::Ok(Some(ActorData { actor_id, row: actor_row, diff --git a/packages/edge/services/pegboard/standalone/usage-metrics-publish/src/lib.rs b/packages/edge/services/pegboard/standalone/usage-metrics-publish/src/lib.rs index 1e3681dff6..174af526df 100644 --- a/packages/edge/services/pegboard/standalone/usage-metrics-publish/src/lib.rs +++ b/packages/edge/services/pegboard/standalone/usage-metrics-publish/src/lib.rs @@ -8,7 +8,7 @@ use futures_util::{StreamExt, TryStreamExt}; use pegboard::{keys, protocol}; struct Usage { - // Percent of core. + // Millicores. pub cpu: u64, /// MiB. pub memory: u64, @@ -115,7 +115,7 @@ pub async fn run_from_env( .entry((actor.env_id, client_flavor)) .or_insert(Usage { cpu: 0, memory: 0 }); - env_usage.cpu += (actor.resources.cpu_millicores / 10) as u64; + env_usage.cpu += actor.resources.cpu_millicores as u64; env_usage.memory += actor.resources.memory_mib as u64; }