Observability reference¶
The operator surfaces of AWC are the awcd health HTTP endpoints, the /metrics scrape, structured logs, traces, and the audit-event log.
Health HTTP endpoints¶
awcd serves three HTTP/1.1 routes on a separate loopback listener. The host API stays on its Unix-domain gRPC socket; only health and metrics use this listener.
| Route | Method | Returns | HTTP 200 |
HTTP 503 |
|---|---|---|---|---|
/healthz |
GET |
Liveness plus the full report body | The process is up and the base filesystem is serving. | A foundational component is hard-down. |
/readyz |
GET |
Readiness for new writable mounts plus the full report body | The host can accept a new writable mount. | The host cannot accept a new writable mount. Warm reads may still be served. |
/metrics |
GET |
Prometheus text exposition | Always, when the listener is up. | Never. |
Any other method returns 405. Any other path returns 404. Both /healthz and /readyz return the same JSON body, a HealthReport. Only the status code differs.
The listener is opt-in. When health_http_listen is unset, the HTTP server does not start and GetHostStatus is the only host-status surface (over gRPC).
| Knob | Where | Value |
|---|---|---|
| Config key | health_http_listen |
A loopback host:port, for example 127.0.0.1:9100. |
| Env var | AWC_HEALTH_HTTP_LISTEN |
Same format. |
| Type | Option<SocketAddr> |
The listener address is optional. |
| Default | unset | The listener is not started. |
The value must parse as a host:port or awcd returns a config error. It should be a loopback address so the endpoints are not exposed broadly. See configuration and environment variables.
Health report body¶
/healthz and /readyz return a JSON HealthReport.
| Field | Type | Meaning |
|---|---|---|
live |
bool | Liveness. The process is up and its event loop makes progress. |
ready_for_new_mounts |
bool | The host can accept a new writable mount. |
warm_read_ready |
bool | The host can keep serving existing warm reads. |
components |
array | One object per component. See components. |
Each components entry has three fields:
| Field | Type | Meaning |
|---|---|---|
name |
string | A canonical component name. See components. |
state |
string | One of ok, degraded, down, unknown. See component states. |
detail |
string or null | A closed-set, non-sensitive verdict, for example active_mounts=2. |
Health components¶
awcd derives the report from seven components.
| Component | name |
State in the current build |
|---|---|---|
| Base filesystem | base_fuse |
ok when mounted, degraded while mounting or unmounting, down otherwise |
| Cache | cache |
ok |
| Kernel compatibility | kernel_compat |
ok, degraded, or unknown |
| Mounts and leases | mounts_leases |
ok |
| Control plane | control_plane |
unknown |
| Object store | object_store |
unknown |
| Disk pressure | disk_pressure |
ok, degraded, down, or unknown |
Component states¶
Each component state has one of four values. They serialize in snake_case.
| State | Meaning |
|---|---|
ok |
Healthy or nominal. |
degraded |
Serving but impaired. For example, elevated disk pressure. |
down |
Required for readiness and currently failing. |
unknown |
Not yet probed. The transport for this build is not wired. |
Readiness model¶
A host may stay ready for existing warm reads while it is unready for new writable mounts. The report preserves that distinction.
| Flag | Derived rule |
|---|---|
live |
base_fuse is not down. |
warm_read_ready |
base_fuse and cache are ok or degraded. |
ready_for_new_mounts |
warm_read_ready and kernel_compat is ok or degraded, and mounts_leases, disk_pressure, control_plane, and object_store are not down. |
/healthz returns 200 when live is true. /readyz returns 200 only when ready_for_new_mounts is true. For kernel_compat, unknown fails readiness closed: an unverified kernel is not admitted. The mounts_leases, disk_pressure, control_plane, and object_store gates fail readiness only when down, not when unknown.
Because the readiness rule for control_plane and object_store is not_down, their unknown state does not by itself fail /readyz. In the shipped binary kernel_compat is wired to the live probe, so on a schedulable, non-pressured host /readyz returns 200 even while those two components report unknown. A real down connectivity verdict cannot be asserted until the probes are wired. Warm reads still return 200 on the liveness probe.
Disk pressure states¶
The disk_pressure component maps a pressure state to a component state. States escalate monotonically by severity rank.
| Rank | State string | Component state | Effect |
|---|---|---|---|
0 |
NORMAL |
ok |
No containment. |
1 |
CACHE_EVICTION |
degraded |
Disposable cache is evicted. |
2 |
PREFETCH_DISABLED |
degraded |
Speculative prefetch yields. |
3 |
NEW_MOUNTS_DISABLED |
down |
New writable mounts are rejected. |
4 |
UPPER_WRITES_AT_RISK |
down |
Existing uppers may hit ENOSPC. |
5 |
EMERGENCY |
down |
Only warm reads continue. |
The detail string for disk_pressure is state=<STATE>; uncheckpointed_upper_bytes=<n>. The monitor never silently deletes uncheckpointed upper data to relieve pressure. The rank is also exported as the awc_host_disk_pressure_state metric. See metrics.
Metrics¶
GET /metrics returns a Prometheus-style text exposition. The registry caps distinct label-sets per instrument at 128. Recordings beyond the cap roll into the synthetic value cardinality_overflow. Do not put a path, digest, workspace ID, or tenant ID in a label.
awcd serves /metrics on its health HTTP listener (see above). awc-control serves /metrics on its REST listener, alongside /v1/health; that route is unauthenticated, so bind the listener to a private interface.
The full metric catalog, the label sets, the emitted-versus-declared split, and the histogram buckets are on the metrics reference page.
Structured logs¶
Logs are structured JSON lines that carry a request or operation ID.
| Field | Type | Meaning |
|---|---|---|
op_id |
string | The request or operation id. |
level |
string | One of INFO, WARN, ERROR. |
message |
string | A short event summary. |
fields |
object | Closed-set, non-sensitive facts. For example, a stage name or a count. |
ts |
string | The event timestamp, RFC 3339, UTC. |
A deployment wires an event sink for the events. Two sinks ship: one writes a JSON line per event to standard error; one collects lines in memory for in-process tests. Logs should record state transitions, not every successful file read.
Under systemd, all three units send standard output and standard error to journald (StandardOutput=journal, StandardError=journal). Tail with journalctl -u awcd -f. See systemd units.
The following must never appear in a log line:
- file contents;
- access tokens;
- object-store credentials;
- raw secret-bearing paths.
Redact a path before you log it. See tracing and redaction.
Tracing¶
A trace should connect the workspace operation to the object-store request and the publication transaction.
workspace operation
-> mount ticket
-> host mount preparation
-> FUSE lookup/read
-> cache lookup
-> singleflight wait
-> object-store request
-> checkpoint quiesce
-> object upload
-> publication transaction
Trace attributes may include tenant, project, host, snapshot digest, workspace ID, cache outcome, object size, and error class. File paths must be redacted or hashed by default because they may contain sensitive information.
The redaction behavior is as follows.
| Operation | Input | Output |
|---|---|---|
| Path redaction | A path and a keep_depth |
awc:<head>:<hash>. The first keep_depth components are kept; the rest collapses to a short SHA-256 hash. |
| Secret redaction | Any secret-bearing string | The fixed placeholder awc:redacted:secret. |
| ID hashing | Any text | sha256: plus the first eight bytes of the SHA-256 digest, in lower-case hex. |
An OpenTelemetry-compatible OTLP exporter is not layered on. The metrics registry render path is the integration point for one. See Current scope.
Audit events¶
The control plane records immutable audit events for privileged mutations. Each event is one row in the append-only audit_events table. The action and resource_type columns use a fixed set of values so the log stays greppable by category.
audit_events table¶
The table schema is as follows.
| Column | Type | Meaning |
|---|---|---|
id |
bigserial |
Row primary key. |
tenant_id |
TEXT |
The tenant the event belongs to. |
principal_id |
TEXT, nullable |
The actor. A system principal for background passes. |
action |
TEXT |
The action string. See actions. |
resource_type |
TEXT |
The resource family. See resource types. |
resource_id |
TEXT |
The resource identifier. |
request_id |
TEXT, nullable |
The inbound request id, when one is in scope. |
detail |
jsonb |
Actor, resource, request, and state-transition facts. |
created_at |
timestamptz |
The event time. |
The detail column records only identifiers, digests, counts, and enum verdicts. It must not contain object contents, byte payloads, manifest bodies, file names from user data, credentials, tokens, or keys.
Audit actions¶
Every action follows the <resource>.<verb> shape. The table below lists each action constant and its string value.
| Constant | action value |
|---|---|
CHECKPOINT_PUBLISH |
checkpoint.publish |
WORKSPACE_EXPIRE |
workspace.expire |
WORKSPACE_DELETE |
workspace.delete |
SNAPSHOT_MARK_DELETING |
snapshot.mark_deleting |
SNAPSHOT_CREATE |
snapshot.create |
SNAPSHOT_TRANSITION |
snapshot.transition |
SNAPSHOT_SCRUB |
snapshot.scrub |
GC_SWEEP |
gc.sweep |
HOST_REGISTER |
host.register |
HOST_REVOKE |
host.revoke |
HOST_ROTATE |
host.rotate |
HOST_COMPATIBILITY |
host.compatibility |
IMPORT_SESSION_CREATE |
import_session.create |
SIGNING_KEY_ROTATE |
signing_key.rotate |
SIGNING_KEY_RETIRE |
signing_key.retire |
SIGNING_KEY_REVOKE |
signing_key.revoke |
OBJECT_CREDENTIAL_ISSUE |
object_credential.issue |
Audit resource types¶
The resource_type column takes these values.
| Constant | resource_type value |
Status |
|---|---|---|
WORKSPACE |
workspace |
Emitted. |
SNAPSHOT |
snapshot |
Emitted. |
IMPORT_SESSION |
import_session |
Emitted. |
HOST |
host |
Emitted. |
GC_RUN |
gc_run |
Emitted. |
SIGNING_KEY |
signing_key |
Emitted. |
OBJECT_CREDENTIAL |
object_credential |
Emitted. |
LEASE |
lease |
Reserved. No action is emitted. |
MOUNT_SESSION |
mount_session |
Reserved. No action is emitted. |
EXPORT |
export |
Reserved. No action is emitted. |
System principals¶
Background passes record a system principal in principal_id.
| Constant | principal_id value |
Pass |
|---|---|---|
RETENTION |
system:retention |
The retention and TTL pass. |
GC |
system:gc |
The durable garbage collector. |
VALIDATION |
system:validation |
The closure-validation job. |
SCRUB |
system:scrub |
The durable-object integrity scrub. |
Current scope¶
What the current build does not yet do:
- Connectivity probes are not wired. The
control_planeandobject_storecomponents reportunknown. Their readiness gate isnot_down, sounknowndoes not by itself fail/readyz; on a schedulable, non-pressured host/readyzstill returns200. A realdownverdict for connectivity cannot be asserted until the probes are wired. The cache reportsokwith the detailcorruption probe not wired. - Tracing is not exported. The redaction helpers are available, and the span chain is the target shape, but no OTLP exporter is wired. The metrics render path is the integration point.
- Several audit categories have no emit site. The reserved
LEASE,MOUNT_SESSION, andEXPORTresource types have no actions. Events are required for writer lease acquisition, revocation, and expiration; mount ticket issuance; mount and unmount; export; retention-policy changes; administrative recovery; and authorization failures for privileged operations. None of these are emitted yet. Workspace creation and fork also have no dedicated action. - Two histograms are recorded.
awc_snapshot_validation_duration_secondsis recorded byawc-worker(no HTTP listener, so not scrapeable).awc_fuse_request_duration_secondsis recorded byawcdper served FUSE request (fusefeature). See metrics. - Many metrics are declared but not emitted. See the declared-not-emitted table on the metrics reference page.