CosmicAC Logo
API reference

Monitor API reference

HTTP routes the CosmicAC monitor serves for job metrics and job logs, with parameters, responses, and status codes.

These routes return the job metrics and job logs that cosmicac-wrk-monitor collects. CosmicAC services send that telemetry over a shared topic. Each route lists its request, response, and errors.

In every path, <monitor-url> is the base URL of the monitor, which listens on port 9110 by default.

The monitor requires no authentication

By default, every route accepts any caller that can reach the port. Job logs and job metrics hold operational detail for every tenant of the deployment. See Restrict access to cosmicac-wrk-monitor.

Endpoints

MethodPathRoute
GET/metricsScrape metrics
GET/metrics/<endpoint-name>Scrape metrics for one endpoint
GET/job-metrics/<job-id>Get current job metrics
GET/endpoint-metrics/<endpoint-name>Get current endpoint metrics
GET/job-metrics/<job-id>/historyGet job metrics history
GET/endpoint-metrics/<endpoint-name>/historyGet endpoint metrics history
GET/job-metrics/<job-id>/streamStream job metrics
GET/endpoint-metrics/<endpoint-name>/streamStream endpoint metrics
GET/logsStream logs
GET/logs/historyGet log history
GET/logs/exportExport logs

Authentication

Only Scrape metrics accepts a credential, and only when your deployment sets metricsScrapeToken in the cosmicac-wrk-monitor configuration. That value is empty by default, which leaves /metrics open to any caller.

Authorization: Bearer <scrape-token>

Scrape metrics

Returns the metrics registry in Prometheus text exposition format.

HTTP request

GET <monitor-url>/metrics

Query parameters

ParameterTypeRequiredDescription
endpointstringNoReturns only the series for this inference endpoint.
job_idstringNoReturns only the series for this job.
componentstringNoReturns only the series for this CosmicAC component.

Request headers

HeaderTypeRequiredDescription
AuthorizationstringNoScrape token as a Bearer token, Bearer <scrape-token>. Required only when the deployment sets metricsScrapeToken.

Response

The response body is Prometheus exposition text.

Content-Type: text/plain; version=0.0.4; charset=utf-8

A filter that matches no series returns 200 with an empty body.

Errors

Failed requests return an error identifier.

{
  "error": "ERR_UNAUTHORIZED"
}
FieldTypeDescription
errorstringIdentifies the error.

The route returns these status codes.

StatusMeaning
401The deployment sets metricsScrapeToken, and the request carries no matching Bearer token. The response carries a WWW-Authenticate: Bearer header.

Scrape metrics for one endpoint

Returns the registry filtered to one inference endpoint, in Prometheus text exposition format.

HTTP request

GET <monitor-url>/metrics/<endpoint-name>

Path parameters

ParameterTypeRequiredDescription
endpoint-namestringYesInference endpoint to return series for.

Query parameters

ParameterTypeRequiredDescription
job_idstringNoReturns only the series for this job.
componentstringNoReturns only the series for this CosmicAC component.

An endpoint query parameter has no effect on this route, because the path value takes precedence.

Request headers

HeaderTypeRequiredDescription
AuthorizationstringNoScrape token as a Bearer token, Bearer <scrape-token>. Required only when the deployment sets metricsScrapeToken.

Response

The response body is Prometheus exposition text, carrying only the series labelled with the named endpoint.

Content-Type: text/plain; version=0.0.4; charset=utf-8

An endpoint with no series returns 200 with an empty body.

Errors

Failed requests return an error identifier.

{
  "error": "ERR_UNAUTHORIZED"
}
FieldTypeDescription
errorstringIdentifies the error.

The route returns these status codes.

StatusMeaning
401The deployment sets metricsScrapeToken, and the request carries no matching Bearer token. The response carries a WWW-Authenticate: Bearer header.

Get current job metrics

Returns one sample of the CPU and GPU values for a job. CosmicAC reads the sample from your Prometheus.

HTTP request

GET <monitor-url>/job-metrics/<job-id>

Path parameters

ParameterTypeRequiredDescription
job-idstringYesJob to sample.

Response

{
  "job_id": "job-4f2a",
  "timestamp": 1783079106559,
  "cpu": {
    "cpu_percent": 42.5,
    "source": "container"
  },
  "gpu": [
    {
      "gpu": "0",
      "uuid": "GPU-1a2b3c",
      "utilization_pct": 96,
      "memory_used_bytes": 74490249216,
      "memory_total_bytes": 85520809984,
      "temp_c": 61,
      "power_w": 412
    }
  ]
}
FieldTypeDescription
job_idstringJob the sample covers.
timestampintegerUnix timestamp in milliseconds, taken when the monitor built the sample.
cpu.cpu_percentnumberProcessor use as a percentage of the job's allocated cores, so it approaches 100 at full use whatever the core count. null when no series matched.
cpu.sourcestringWhere the processor figure came from, either container or agent.
gpuarrayOne entry per device, sorted by gpu.
gpu[].gpustringDevice index.
gpu[].uuidstringDevice identifier reported by the driver.
gpu[].utilization_pctnumberDevice use as a percentage.
gpu[].memory_used_bytesnumberDevice memory in use, in bytes.
gpu[].memory_total_bytesnumberTotal device memory, in bytes.
gpu[].temp_cnumberDevice temperature in degrees Celsius.
gpu[].power_wnumberDevice power draw, in watts.

Errors

Failed requests return an error identifier.

{
  "error": "ERR_JOB_ID_INVALID"
}
FieldTypeDescription
errorstringIdentifies the error.

The route returns these status codes.

StatusMeaning
400The job ID isn't a valid label value. The error is ERR_JOB_ID_INVALID.
503The deployment stores no Prometheus URL. The error is ERR_PROMETHEUS_NOT_CONFIGURED.

Get current endpoint metrics

Returns one sample of the CPU and GPU values for an inference endpoint. CosmicAC resolves the endpoint to its jobs, then reads the sample from your Prometheus.

HTTP request

GET <monitor-url>/endpoint-metrics/<endpoint-name>

Path parameters

ParameterTypeRequiredDescription
endpoint-namestringYesInference endpoint to sample.

Response

{
  "endpoint": "qwen-2-prod",
  "timestamp": 1783079106559,
  "cpu": {
    "cpu_percent": 42.5,
    "source": "container"
  },
  "gpu": [
    {
      "gpu": "0",
      "uuid": "GPU-1a2b3c",
      "utilization_pct": 96,
      "memory_used_bytes": 74490249216,
      "memory_total_bytes": 85520809984,
      "temp_c": 61,
      "power_w": 412
    }
  ]
}
FieldTypeDescription
endpointstringInference endpoint the sample covers.
timestampintegerUnix timestamp in milliseconds, taken when the monitor built the sample.
cpu.cpu_percentnumberProcessor use as a percentage of the job's allocated cores, so it approaches 100 at full use whatever the core count. null when no series matched.
cpu.sourcestringWhere the processor figure came from, either container or agent.
gpuarrayOne entry per device, sorted by gpu.
gpu[].gpustringDevice index.
gpu[].uuidstringDevice identifier reported by the driver.
gpu[].utilization_pctnumberDevice use as a percentage.
gpu[].memory_used_bytesnumberDevice memory in use, in bytes.
gpu[].memory_total_bytesnumberTotal device memory, in bytes.
gpu[].temp_cnumberDevice temperature in degrees Celsius.
gpu[].power_wnumberDevice power draw, in watts.

Errors

Failed requests return an error identifier.

{
  "error": "ERR_ENDPOINT_INVALID"
}
FieldTypeDescription
errorstringIdentifies the error.

The route returns these status codes.

StatusMeaning
400The endpoint name isn't a valid label value. The error is ERR_ENDPOINT_INVALID.
503The deployment stores no Prometheus URL. The error is ERR_PROMETHEUS_NOT_CONFIGURED.

Get job metrics history

Returns metric series for a job over a time range. CosmicAC reads the series from your Prometheus.

HTTP request

GET <monitor-url>/job-metrics/<job-id>/history

Path parameters

ParameterTypeRequiredDescription
job-idstringYesJob to read.

Query parameters

ParameterTypeRequiredDescription
startstringNoStart of the range, as an RFC 3339 timestamp or as a Unix timestamp in nanoseconds. Defaults to one hour before end.
endstringNoEnd of the range, in the same forms. Defaults to now.
stepstringNoResolution, as a duration such as 15s or 1m, or as seconds. Defaults to a step the monitor derives from the range.

Response

{
  "job_id": "job-4f2a",
  "start": 1783075506559,
  "end": 1783079106559,
  "step_ms": 15000,
  "cpu": {
    "source": "container",
    "cpu_percent": [{ "timestamp": 1783075506559, "value": 42.5 }]
  },
  "gpu": [
    {
      "gpu": "0",
      "uuid": "GPU-1a2b3c",
      "utilization_pct": [{ "timestamp": 1783075506559, "value": 96 }],
      "memory_used_bytes": [{ "timestamp": 1783075506559, "value": 74490249216 }],
      "memory_total_bytes": [{ "timestamp": 1783075506559, "value": 85520809984 }],
      "temp_c": [{ "timestamp": 1783075506559, "value": 61 }],
      "power_w": [{ "timestamp": 1783075506559, "value": 412 }]
    }
  ],
  "inference": {
    "traffic": [{ "timestamp": 1783075506559, "value": 120 }],
    "failures": [{ "timestamp": 1783075506559, "value": 2 }]
  }
}
FieldTypeDescription
job_idstringJob the series cover.
startintegerStart of the range, as a Unix timestamp in milliseconds.
endintegerEnd of the range, as a Unix timestamp in milliseconds.
step_msintegerResolution the monitor used, in milliseconds.
cpu.sourcestringOrigin of the processor figures, either container or agent. null when no series matched.
cpu.cpu_percentarrayProcessor use as a percentage of the job's allocated cores, so it approaches 100 at full use whatever the core count.
cpu.cpu_percent[].timestampintegerUnix timestamp in milliseconds.
cpu.cpu_percent[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpuarrayOne entry per device, sorted by gpu.
gpu[].gpustringDevice index.
gpu[].uuidstringDevice identifier reported by the driver.
gpu[].utilization_pctarrayDevice use as a percentage.
gpu[].utilization_pct[].timestampintegerUnix timestamp in milliseconds.
gpu[].utilization_pct[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpu[].memory_used_bytesarrayDevice memory in use, in bytes.
gpu[].memory_used_bytes[].timestampintegerUnix timestamp in milliseconds.
gpu[].memory_used_bytes[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpu[].memory_total_bytesarrayTotal device memory, in bytes.
gpu[].memory_total_bytes[].timestampintegerUnix timestamp in milliseconds.
gpu[].memory_total_bytes[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpu[].temp_carrayDevice temperature in degrees Celsius.
gpu[].temp_c[].timestampintegerUnix timestamp in milliseconds.
gpu[].temp_c[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpu[].power_warrayDevice power draw, in watts.
gpu[].power_w[].timestampintegerUnix timestamp in milliseconds.
gpu[].power_w[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
inferenceobjectRequest and failure counts for each step, or null when the job served no inference traffic.
inference.trafficarrayRequests in each step, as a whole count.
inference.traffic[].timestampintegerUnix timestamp in milliseconds.
inference.traffic[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
inference.failuresarrayFailed requests in each step, as a whole count.
inference.failures[].timestampintegerUnix timestamp in milliseconds.
inference.failures[].valuenumberMeasurement at that timestamp, or null when the step held no sample.

Errors

Failed requests return an error identifier and a message.

{
  "error": "ERR_PROMETHEUS_NOT_CONFIGURED",
  "message": "No Prometheus URL configured; history unavailable"
}
FieldTypeDescription
errorstringIdentifies the error.
messagestringExplains what went wrong.

The route returns these status codes.

StatusMeaning
400The error is ERR_JOB_ID_INVALID for a job ID that isn't a valid label value, ERR_TIME_RANGE_INVALID for a range that doesn't parse or runs backward, or ERR_STEP_INVALID for an unsupported step.
503The deployment stores no Prometheus URL. The error is ERR_PROMETHEUS_NOT_CONFIGURED.

Get endpoint metrics history

Returns metric series for an inference endpoint over a time range. CosmicAC reads the series from your Prometheus.

HTTP request

GET <monitor-url>/endpoint-metrics/<endpoint-name>/history

Path parameters

ParameterTypeRequiredDescription
endpoint-namestringYesInference endpoint to read.

Query parameters

ParameterTypeRequiredDescription
startstringNoStart of the range, as an RFC 3339 timestamp or as a Unix timestamp in nanoseconds. Defaults to one hour before end.
endstringNoEnd of the range, in the same forms. Defaults to now.
stepstringNoResolution, as a duration such as 15s or 1m, or as seconds. Defaults to a step the monitor derives from the range.

Response

{
  "endpoint": "qwen-2-prod",
  "start": 1783075506559,
  "end": 1783079106559,
  "step_ms": 15000,
  "cpu": {
    "source": "container",
    "cpu_percent": [{ "timestamp": 1783075506559, "value": 42.5 }]
  },
  "gpu": [
    {
      "gpu": "0",
      "uuid": "GPU-1a2b3c",
      "utilization_pct": [{ "timestamp": 1783075506559, "value": 96 }],
      "memory_used_bytes": [{ "timestamp": 1783075506559, "value": 74490249216 }],
      "memory_total_bytes": [{ "timestamp": 1783075506559, "value": 85520809984 }],
      "temp_c": [{ "timestamp": 1783075506559, "value": 61 }],
      "power_w": [{ "timestamp": 1783075506559, "value": 412 }]
    }
  ],
  "inference": {
    "traffic": [{ "timestamp": 1783075506559, "value": 120 }],
    "failures": [{ "timestamp": 1783075506559, "value": 2 }]
  }
}
FieldTypeDescription
endpointstringInference endpoint the series cover.
startintegerStart of the range, as a Unix timestamp in milliseconds.
endintegerEnd of the range, as a Unix timestamp in milliseconds.
step_msintegerResolution the monitor used, in milliseconds.
cpu.sourcestringOrigin of the processor figures, either container or agent. null when no series matched.
cpu.cpu_percentarrayProcessor use as a percentage of the job's allocated cores, so it approaches 100 at full use whatever the core count.
cpu.cpu_percent[].timestampintegerUnix timestamp in milliseconds.
cpu.cpu_percent[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpuarrayOne entry per device, sorted by gpu.
gpu[].gpustringDevice index.
gpu[].uuidstringDevice identifier reported by the driver.
gpu[].utilization_pctarrayDevice use as a percentage.
gpu[].utilization_pct[].timestampintegerUnix timestamp in milliseconds.
gpu[].utilization_pct[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpu[].memory_used_bytesarrayDevice memory in use, in bytes.
gpu[].memory_used_bytes[].timestampintegerUnix timestamp in milliseconds.
gpu[].memory_used_bytes[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpu[].memory_total_bytesarrayTotal device memory, in bytes.
gpu[].memory_total_bytes[].timestampintegerUnix timestamp in milliseconds.
gpu[].memory_total_bytes[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpu[].temp_carrayDevice temperature in degrees Celsius.
gpu[].temp_c[].timestampintegerUnix timestamp in milliseconds.
gpu[].temp_c[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
gpu[].power_warrayDevice power draw, in watts.
gpu[].power_w[].timestampintegerUnix timestamp in milliseconds.
gpu[].power_w[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
inferenceobjectRequest and failure counts for each step, or null when the endpoint served no inference traffic.
inference.trafficarrayRequests in each step, as a whole count.
inference.traffic[].timestampintegerUnix timestamp in milliseconds.
inference.traffic[].valuenumberMeasurement at that timestamp, or null when the step held no sample.
inference.failuresarrayFailed requests in each step, as a whole count.
inference.failures[].timestampintegerUnix timestamp in milliseconds.
inference.failures[].valuenumberMeasurement at that timestamp, or null when the step held no sample.

Errors

Failed requests return an error identifier and a message.

{
  "error": "ERR_PROMETHEUS_NOT_CONFIGURED",
  "message": "No Prometheus URL configured; history unavailable"
}
FieldTypeDescription
errorstringIdentifies the error.
messagestringExplains what went wrong.

The route returns these status codes.

StatusMeaning
400The error is ERR_ENDPOINT_INVALID for an endpoint name that isn't a valid label value, ERR_TIME_RANGE_INVALID for a range that doesn't parse or runs backward, or ERR_STEP_INVALID for an unsupported step.
503The deployment stores no Prometheus URL. The error is ERR_PROMETHEUS_NOT_CONFIGURED.

Stream job metrics

Pushes a sample of a job's CPU and GPU values over a WebSocket connection at a fixed interval.

HTTP request

GET <monitor-url>/job-metrics/<job-id>/stream

The route serves WebSocket connections only. A request that isn't a WebSocket handshake returns 426.

Path parameters

ParameterTypeRequiredDescription
job-idstringYesJob to sample.

Query parameters

ParameterTypeRequiredDescription
interval_msintegerNoMilliseconds between samples.

WebSocket frames

{
  "type": "metrics",
  "job_id": "job-4f2a",
  "timestamp": 1783079106559,
  "cpu": {
    "cpu_percent": 42.5,
    "source": "container"
  },
  "gpu": [
    {
      "gpu": "0",
      "uuid": "GPU-1a2b3c",
      "utilization_pct": 96,
      "memory_used_bytes": 74490249216,
      "memory_total_bytes": 85520809984,
      "temp_c": 61,
      "power_w": 412
    }
  ],
  "inference": {
    "traffic": 3,
    "failures": 0
  }
}
FieldTypeDescription
typestringEither metrics for a sample, or error for a failure.
job_idstringJob the sample covers.
timestampintegerUnix timestamp in milliseconds, taken when the monitor built the sample.
cpu.cpu_percentnumberProcessor use as a percentage of the job's allocated cores, so it approaches 100 at full use whatever the core count. null when no series matched.
cpu.sourcestringWhere the processor figure came from, either container or agent.
gpuarrayOne entry per device, sorted by gpu.
gpu[].gpustringDevice index.
gpu[].uuidstringDevice identifier reported by the driver.
gpu[].utilization_pctnumberDevice use as a percentage.
gpu[].memory_used_bytesnumberDevice memory in use, in bytes.
gpu[].memory_total_bytesnumberTotal device memory, in bytes.
gpu[].temp_cnumberDevice temperature in degrees Celsius.
gpu[].power_wnumberDevice power draw, in watts.
inferenceobjectRequests and failures served since the previous frame, or null when the job served no inference traffic. The first frame covers the interval before the connection opened.
inference.trafficnumberRequests served since the previous frame. 0 when neither reading matched a series, and null when only one did, or when the counter decreased.
inference.failuresnumberFailed requests since the previous frame. 0 when neither reading matched a series, and null when only one did, or when the counter decreased.

The monitor sends the first sample when the connection opens, then one every interval.

Errors

Failed requests return an error identifier and a message.

{
  "error": "ERR_UPGRADE_REQUIRED",
  "message": "Connect to this route over WebSocket"
}
FieldTypeDescription
errorstringIdentifies the error.
messagestringExplains what went wrong.

The route returns these status codes.

StatusMeaning
426The request reached the route without a WebSocket upgrade. The error is ERR_UPGRADE_REQUIRED.

When a job ID isn't a valid label value, the monitor sends an ERR_JOB_ID_INVALID frame and closes the connection.


Stream endpoint metrics

Pushes a sample of an inference endpoint's CPU and GPU values over a WebSocket connection at a fixed interval.

HTTP request

GET <monitor-url>/endpoint-metrics/<endpoint-name>/stream

The route serves WebSocket connections only. A request that isn't a WebSocket handshake returns 426.

Path parameters

ParameterTypeRequiredDescription
endpoint-namestringYesInference endpoint to sample.

Query parameters

ParameterTypeRequiredDescription
interval_msintegerNoMilliseconds between samples.

WebSocket frames

{
  "type": "metrics",
  "endpoint": "qwen-2-prod",
  "timestamp": 1783079106559,
  "cpu": {
    "cpu_percent": 42.5,
    "source": "container"
  },
  "gpu": [
    {
      "gpu": "0",
      "uuid": "GPU-1a2b3c",
      "utilization_pct": 96,
      "memory_used_bytes": 74490249216,
      "memory_total_bytes": 85520809984,
      "temp_c": 61,
      "power_w": 412
    }
  ],
  "inference": {
    "traffic": 3,
    "failures": 0
  }
}
FieldTypeDescription
typestringEither metrics for a sample, or error for a failure.
endpointstringInference endpoint the sample covers.
timestampintegerUnix timestamp in milliseconds, taken when the monitor built the sample.
cpu.cpu_percentnumberProcessor use as a percentage of the job's allocated cores, so it approaches 100 at full use whatever the core count. null when no series matched.
cpu.sourcestringWhere the processor figure came from, either container or agent.
gpuarrayOne entry per device, sorted by gpu.
gpu[].gpustringDevice index.
gpu[].uuidstringDevice identifier reported by the driver.
gpu[].utilization_pctnumberDevice use as a percentage.
gpu[].memory_used_bytesnumberDevice memory in use, in bytes.
gpu[].memory_total_bytesnumberTotal device memory, in bytes.
gpu[].temp_cnumberDevice temperature in degrees Celsius.
gpu[].power_wnumberDevice power draw, in watts.
inferenceobjectRequests and failures served since the previous frame, or null when the endpoint served no inference traffic. The first frame covers the interval before the connection opened.
inference.trafficnumberRequests served since the previous frame. 0 when neither reading matched a series, and null when only one did, or when the counter decreased.
inference.failuresnumberFailed requests since the previous frame. 0 when neither reading matched a series, and null when only one did, or when the counter decreased.

The monitor sends the first sample when the connection opens, then one every interval.

Errors

Failed requests return an error identifier and a message.

{
  "error": "ERR_UPGRADE_REQUIRED",
  "message": "Connect to this route over WebSocket"
}
FieldTypeDescription
errorstringIdentifies the error.
messagestringExplains what went wrong.

The route returns these status codes.

StatusMeaning
426The request reached the route without a WebSocket upgrade. The error is ERR_UPGRADE_REQUIRED.

When an endpoint name isn't a valid label value, the monitor sends an ERR_ENDPOINT_INVALID frame and closes the connection.


Stream logs

Pushes job log lines over a WebSocket connection as they arrive.

HTTP request

GET <monitor-url>/logs

The route serves WebSocket connections only. A request that isn't a WebSocket handshake returns 426.

Query parameters

ParameterTypeRequiredDescription
job_idstringYesJob to follow. Required unless the request carries all.
replica_idstringNoSends only lines from this replica.
typestringNoSends only lines of this type, either application or system.
allbooleanNoA value of true follows every component instead of one job.

WebSocket frames

{
  "type": "log",
  "labels": {
    "job_id": "job-4f2a",
    "replica_id": "0",
    "type": "application"
  },
  "message": "Model loaded",
  "level": "info",
  "timestamp": 1783079106559,
  "data": {}
}
FieldTypeDescription
typestringEither log for a line, or error for a failure.
labelsobjectLabels the producer attached to the line.
messagestringThe log line.
levelstringSeverity the producer recorded.
timestampintegerUnix timestamp in milliseconds.
dataobjectStructured fields the producer attached, when it attached any.

Errors

Failed requests return an error identifier and a message.

{
  "error": "ERR_UPGRADE_REQUIRED",
  "message": "Connect to /logs over WebSocket"
}
FieldTypeDescription
errorstringIdentifies the error.
messagestringExplains what went wrong.

The route returns these status codes.

StatusMeaning
426The request reached the route without a WebSocket upgrade. The error is ERR_UPGRADE_REQUIRED.

When a request names no job and omits all, the monitor sends an ERR_JOB_ID_REQUIRED frame and closes the connection.


Get log history

Returns stored log lines for a job. CosmicAC reads them from your Loki.

HTTP request

GET <monitor-url>/logs/history

Query parameters

ParameterTypeRequiredDescription
job_idstringYesJob to read. Required unless the request carries all.
allbooleanNoA value of true reads across every component instead of one job.
replica_idstringNoReturns only lines from this replica.
typestringNoReturns only lines of this type, either application or system.
componentstringNoReturns only lines from this CosmicAC component.
levelstringNoReturns only lines at this severity.
searchstringNoReturns only lines containing this text. Up to 512 characters.
startstringNoStart of the range, as an RFC 3339 timestamp or as a Unix timestamp in nanoseconds.
endstringNoEnd of the range, in the same forms.
limitintegerNoLines per page. Defaults to 200, up to 1000.
directionstringNoEither backward for newest first, or forward. Defaults to backward.
cursorstringNoContinues a previous page. The value comes from next_cursor or newer_cursor in that page.

Response

{
  "total": 200,
  "entries": [
    {
      "labels": { "job_id": "job-4f2a" },
      "timestamp": 1783079106559,
      "timestamp_ns": "1783079106559000000",
      "message": "Model loaded",
      "level": "info"
    }
  ],
  "limit": 200,
  "direction": "backward",
  "has_more": true,
  "next_cursor": "eyJ0cyI6...",
  "newer_cursor": null
}
FieldTypeDescription
totalintegerLines in this page.
entriesarrayThe lines, ordered by direction.
entries[].labelsobjectLabels the producer attached to the line.
entries[].timestampintegerUnix timestamp in milliseconds.
entries[].timestamp_nsstringUnix timestamp in nanoseconds. Cursors build on this value rather than on timestamp.
entries[].messagestringThe log line.
entries[].levelstringSeverity the producer recorded.
limitintegerPage size the monitor applied.
directionstringOrder the monitor applied.
has_morebooleanWhether more lines follow in the same direction.
next_cursorstringCursor for the next page, or null.
newer_cursorstringCursor for the page in the opposite direction, or null.

Errors

Failed requests return an error identifier and a message.

{
  "error": "ERR_LOKI_NOT_CONFIGURED",
  "message": "No Loki URL configured; history unavailable"
}
FieldTypeDescription
errorstringIdentifies the error.
messagestringExplains what went wrong.

The route returns these status codes.

StatusMeaning
400The request names no job and omits all, the search text is too long, a bound doesn't parse, the range runs backward, or the cursor doesn't decode. The error is ERR_JOB_ID_REQUIRED, ERR_SEARCH_TOO_LONG, ERR_START_INVALID, ERR_END_INVALID, ERR_TIME_RANGE_INVALID, or ERR_CURSOR_INVALID.
400Loki rejected the query, often because the range exceeded its max_query_length. The error is ERR_LOKI_QUERY_REJECTED.
502Loki didn't answer. The error is ERR_LOKI_UNAVAILABLE.
503The deployment stores no Loki URL. The error is ERR_LOKI_NOT_CONFIGURED.

Export logs

Returns every stored log line for a job over a time range, as one plain-text file. The monitor reads the lines from your Loki and writes them oldest first.

HTTP request

GET <monitor-url>/logs/export

Query parameters

ParameterTypeRequiredDescription
job_idstringYesJob to export. The ID has up to 200 characters, and uses only letters, digits, and . _ : @ / -.
replica_idstringNoExports only lines from this replica.
typestringNoExports only lines of this type, either application or system.
componentstringNoExports only lines from this CosmicAC component.
levelstringNoExports only lines at this severity. To include more than one severity, separate the values with commas.
searchstringNoExports only lines that contain this text. The match isn't case-sensitive. Up to 512 characters.
startstringNoStart of the range, as an RFC 3339 timestamp or as a Unix timestamp in seconds, milliseconds, or nanoseconds. Defaults to seven days before end.
endstringNoEnd of the range, in the same forms. Defaults to now.

Response

The response is a file download with the following headers.

Content-Type: text/plain; charset=utf-8
Content-Disposition: attachment; filename="<job-id>-logs.log"
Cache-Control: no-store

Each line of the body is one log entry, in the following format.

<timestamp> <replica-id> <LEVEL> <component> <message>

The following example shows two entries.

2026-07-03T10:05:06.559Z 0 INFO Model loaded
2026-07-03T10:05:07.120Z 0 WARN KV cache usage above 90%
FieldDescription
timestampThe time of the entry, as an ISO 8601 timestamp in Coordinated Universal Time, with milliseconds.
replica-idThe replica that wrote the entry. Omitted when the entry has no replica.
LEVELThe severity that the producer recorded, in uppercase. Omitted when the entry has no severity.
componentThe CosmicAC component that wrote the entry. Omitted when the entry has no component.
messageThe log message. A line break inside the message appears as \n, so each entry stays on one line.

If the export stops early, the last line starts with # EXPORT TRUNCATED: or # EXPORT ABORTED:, followed by the reason. The status stays 200.

Errors

Failed requests return an error identifier and a message. An ERR_EXPORT_TOO_LARGE error also returns the line count and the line limit.

{
  "error": "ERR_EXPORT_TOO_LARGE",
  "message": "window holds ~612000 lines, over the 500000 line export limit",
  "lines": 612000,
  "max_lines": 500000
}
FieldTypeDescription
errorstringIdentifies the error.
messagestringExplains what went wrong.
linesintegerThe estimated number of lines in the range. Returned with ERR_EXPORT_TOO_LARGE only.
max_linesintegerThe maximum number of lines that the monitor exports. Returned with ERR_EXPORT_TOO_LARGE only.
rangeobjectThe start and end that the monitor resolved, in Unix nanoseconds. Returned with ERR_TIME_RANGE_TOO_LARGE only.

The route returns these status codes.

StatusMeaning
400The request names no job, the job ID has unsupported characters, or the request carries an unsupported parameter. The error is ERR_JOB_ID_REQUIRED, ERR_JOB_ID_INVALID, or ERR_PARAM_NOT_SUPPORTED.
400The search text is too long, a bound doesn't parse, the range runs backward, or the range is too long. The error is ERR_SEARCH_TOO_LONG, ERR_START_INVALID, ERR_END_INVALID, ERR_TIME_RANGE_INVALID, or ERR_TIME_RANGE_TOO_LARGE.
400Another parameter has an invalid value, such as a type other than application or system. The error is ERR_QUERY_INVALID.
413The range holds more lines than the export limit. The error is ERR_EXPORT_TOO_LARGE.
503The deployment stores no Loki URL. The error is ERR_LOKI_NOT_CONFIGURED.

What's next

On this page