get_procs() @return docs don't match returned columns, and pid column is the row index

Aperta Adatta ai principianti
#532 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

@jmwoliver ci sta già lavorando.

Dal 6/11/2026.

  • #533 di @jmwoliver — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
67/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
r

Direzione di ricerca

Inizia da R/get.R e segui come get_procs() trasforma l’elenco restituito da procs() prima di analizzarlo; la riproduzione mostra dove viene perso il pid effettivo. Poi controlla tests/integrated/test-get.R e aggiorna le asserzioni sulle colonne affinché usino snake_case. Il lavoro è terminato quando le colonne restituite e la documentazione @return corrispondono, il PID del server viene preservato e start_time e heartbeat vengono analizzati come date.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

get_procs() has two related problems. The @return docs don't match the columns it returns, and the pid column holds the row index instead of the real process ID.

Found while reviewing #530 (review comment).

1. @return docs don't match the returned columns

get_procs() (R/get.R) documents these columns: pid, appId, appGuid, appName, appUrl, appRunAs, type, cpuCurrent, cpuTotal, ram.

GET __api__/metrics/procs returns a JSON array of detailedProcInfo objects. In current Connect (src/connect/api/metrics/metrics.go), those objects have these fields:

Field Notes
app_id Int64 serialized as string
app_guid
app_name
app_url
app_run_as
type
cpu_current nullable
ram nullable (bytes)
hostname
job_key
image
start_time
heartbeat nullable
pid "only matters in local"

parse_connectapi_typed() keeps column names as they are, so:

  • The docs use camelCase (appId, cpuCurrent, ...), but the returned columns are snake_case (app_id, cpu_current, ...).
  • cpuTotal is documented, but the server doesn't send it.
  • hostname, job_key, image, start_time, and heartbeat are returned but not documented.

The integration test in tests/integrated/test-get.R checks for appId and appGuid. It only does that when rows come back, which almost never happens on a fresh test server, so the mismatch goes unnoticed.

Smaller point: start_time and heartbeat come back as character, not POSIXct, because get_procs() passes no datetime_cols.

2. pid is the row index, not the process ID

procs() calls GET with the default simplify = FALSE, so the response is an unnamed list of objects. Each object already has a pid. get_procs() then does this:

purrr::imap(raw_proc_data, function(x, y) c(list(pid = y), x))

That code expects a map keyed by PID. With an unnamed list, y is the position (1, 2, ...), so every row gets two pid entries. parse_connectapi() collects columns with unique(names) plus .subset2(), and .subset2() returns the first match. The result has a single pid column holding the index, and the server's real PID is silently dropped.

Reproduction

I built a stub Connect subclass whose procs() returns the server's array shape, parsed the same way Connect$request() does, and ran it through the real get_procs():

devtools::load_all()
json <- '[{"app_id":"12","app_guid":"aaaa-1111","app_name":"shiny-a","app_url":"http://c/a/","app_run_as":"rstudio-connect","type":"shiny","cpu_current":0.05,"ram":104857600,"hostname":"node-1","job_key":"jk1","image":"","start_time":"2026-11-06T10:00:00Z","heartbeat":"2026-11-06T10:05:00Z","pid":4321},
 {"app_id":"34","app_guid":"bbbb-2222","app_name":"api-b","app_url":"http://c/b/","app_run_as":"rstudio-connect","type":"api","cpu_current":null,"ram":null,"hostname":"node-2","job_key":"jk2","image":"ghcr.io/x:1","start_time":"2026-11-06T10:01:00Z","heartbeat":null,"pid":0}]'
Stub <- R6::R6Class("Stub", inherit = Connect, public = list(
  initialize = function() {},
  procs = function() jsonlite::fromJSON(json, simplifyVector = FALSE, simplifyDataFrame = FALSE)
))
out <- get_procs(Stub$new())
out[, c("pid", "app_id", "app_name", "hostname", "start_time", "heartbeat")]

Output:

# A tibble: 2 × 6
    pid app_id app_name hostname start_time           heartbeat
  <int> <chr>  <chr>    <chr>    <chr>                <chr>
1     1 12     shiny-a  node-1   2026-11-06T10:00:00Z 2026-11-06T10:05:00Z
2     2 34     api-b    node-2   2026-11-06T10:01:00Z <NA>

The server sent PIDs 4321 and 0, but pid is 1, 2.

All the returned columns are: pid, app_id, app_guid, app_name, app_url, app_run_as, type, cpu_current, ram, hostname, job_key, image, start_time, heartbeat.

Possible fix

  • Drop the imap() step and pass raw_proc_data straight to parse_connectapi_typed(), with datetime_cols = c("start_time", "heartbeat").
  • Update the @return list to match the fields above.
  • Make the integration test check snake_case names.

Related

#531 (adding get_processes() on GET /v1/system/processes and deprecating get_procs()) is underway. It may fix this as part of the fallback path to __api__/metrics/procs on older servers. If get_procs() stays around in any form, it needs these fixes.

Lingua principale
R
Stelle
54
Fork
27
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di posit-dev/connectapi

Tutte le issue di posit-dev/connectapi

Issue simili

Altre issue su R

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.