decisions / R /status.R
fmegahed's picture
Deploy 71faef1 from GitHub
39181ba verified
Raw History Blame Contribute Delete
2.15 kB
# Uptime record. A GitHub workflow adds a row to status/status.csv twice a day.
# The app reads this file from GitHub and shows the days in service (chip) and
# the last checks (Uptime tab).
# The columns of status.csv
STATUS_COLUMNS <- c("time_utc", "http_status", "seconds", "answered", "app_version")
# Read the status file. A failed read gives an empty tibble: the chip then
# shows "new" and the app does not crash. All columns are read as text, so
# that an odd value cannot stop the read.
read_status <- function(url = STATUS_URL,
read_fn = \(u) readr::read_csv(
u, col_types = readr::cols(.default = "c")
)) {
empty <- tibble::tibble(
time_utc = character(), http_status = character(), seconds = character(),
answered = character(), app_version = character()
)
tryCatch(
read_fn(url),
error = \(e) empty
)
}
# Days in service, checks answered, checks made, and the last 60 checks.
# A row with a time that cannot be read is ignored. A check counts as answered
# only when its value is true (in any case).
status_summary <- function(status, now = Sys.time()) {
checks <- status |>
dplyr::mutate(
time = as.POSIXct(
as.character(.data$time_utc), format = "%Y-%m-%dT%H:%M:%SZ", tz = "UTC"
),
ok = stringr::str_to_lower(as.character(.data$answered)) %in% "true"
) |>
dplyr::filter(!is.na(.data$time)) |>
dplyr::arrange(.data$time)
first_ok <- checks |>
dplyr::filter(.data$ok) |>
dplyr::slice_head(n = 1)
days <- if (nrow(first_ok) == 0) {
0
} else {
max(0, floor(as.numeric(difftime(now, first_ok$time, units = "days"))))
}
list(
days = days,
answered = sum(checks$ok),
checks = nrow(checks),
last = checks |>
dplyr::select(-"time", -"ok") |>
utils::tail(60)
)
}
# Short text for the chip: "in service 37 days", "in service 1 day" or "new"
status_chip <- function(summary) {
if (summary$days < 1) {
return("new")
}
stringr::str_glue(
"in service {summary$days} {if (summary$days == 1) 'day' else 'days'}"
) |>
as.character()
}