February 20, 2026·4 min read·engineeringswiftobservabilityservers

Swift System Metrics makes process monitoring an application concern

Swift System Metrics 1.0 connects process resource measurements to Swift's shared metrics API. Its application-owned setup is as useful as the measurements themselves.

The Swift System Metrics 1.0 announcement on February 20, 2026 gives process monitoring a stable API. The package collects resource measurements on Linux and macOS and reports them through Swift Metrics. It previously had the name swift-metrics-extras. The new name states its purpose more clearly, which helps distinguish process measurements from metrics that an application defines about its own work.

I like Swift's attention to explicit behavior. Its value types and optionals make useful distinctions visible in ordinary code. I want similar clarity when choosing operational libraries. For this release, the question I find interesting is who owns process monitoring and how it fits into application startup. An API stability commitment helps adoption, but its ownership model determines whether a dependency is straightforward to integrate.

Collection belongs in the executable

The 1.0.0 README says the monitor periodically collects process metrics and reports them to the Swift Metrics factory. It explicitly places this package in applications and tools. Libraries that need their own instrumentation should use Swift Metrics directly. That distinction lets a library describe its work without making decisions about monitoring the entire process that hosts it.

I would preserve that boundary in an application design. A package that parses documents should be able to report how many documents it processed without selecting my telemetry destination. Likewise, I would want to choose process monitoring once while assembling the executable. Those are design preferences about responsibility. They reduce the number of places I would need to inspect when reviewing a program's monitoring configuration.

The release announcement lists CPU time, virtual and resident memory, file descriptor counts and process start time. It also states support for musl libc. This is a defined set of process observations, with a common API on the supported operating systems. I would evaluate it for that scope and keep application-specific measurements as a separate part of the monitoring design.

The package dependency declaration shown for this release is small. This fragment belongs in the dependencies array of a package manifest, with the product declaration in the consuming target's dependency list.

.package(url: "https://github.com/apple/swift-system-metrics", from: "1.0.0")
.product(name: "SystemMetrics", package: "swift-system-metrics")

These fragments only declare the dependency. They do not configure a metrics backend or start the monitor. I would make those remaining steps visible in the application's bootstrap code so a reviewer can follow the complete configuration.

The reporting API and destination are separate choices

The Swift Metrics design separates a common metrics API from backend implementations. An application selects its implementation through MetricsSystem.bootstrap. Libraries use the API without installing their own backend. The stated reason is that packages should be able to report into the same destination while application owners retain the choice of storage and aggregation system.

That separation makes sense to me because the destination is a deployment decision. I would not want to choose an otherwise suitable library on the basis of which monitoring product its author preferred. A shared reporting interface allows that choice to remain with the executable. It also gives a code review a definite location for asking what happens to the measurements after collection.

Swift Metrics documents different instruments for different meanings. A counter accumulates a value, while a gauge represents a value that can move in either direction. Recorders and timers describe observations that a backend may aggregate. Those distinctions matter when reviewing exported measurements, even when a common API hides the backend implementation.

The System Metrics README names process_cpu_seconds_total as cumulative CPU time and process_start_time_seconds as the process's start time. It distinguishes resident memory from virtual memory and names separate open and maximum file descriptor measurements. I would retain those names and units when assessing an exporter. A dashboard should make the meaning of each input evident before someone uses it to decide whether a change helped.

My first review would ask what question each graph is supposed to answer. For memory, I would want the author to say which measurement supports the proposed alert. For CPU, I would want the calculation and its time interval to be explicit. These are questions for the monitoring configuration, and I would answer them before treating a screenshot as evidence of a complete operational setup.

I would also ask whether the proposed instrumentation answers a process question or a business question. A count of completed jobs should remain understandable without knowing the operating system. A process resource observation should retain its system meaning. Keeping those descriptions separate would help me review a service whose workload changes over time.

Monitoring has a lifetime

The release example integrates the monitor with Swift Service Lifecycle. The Service Lifecycle README describes a Service protocol whose work runs through an asynchronous throwing run method. A ServiceGroup runs services in child tasks and listens for configured shutdown signals. The library provides startup and shutdown coordination without requiring a particular server framework.

This is the part of the integration I would examine alongside the exporter. Monitoring code needs an understood lifetime, including how it participates in application shutdown. I would prefer its setup to sit beside the other long-running services. That makes it possible to review the intended behavior without searching for a background task that some unrelated initializer created.

My own Swift experience is still modest, and build times remain a source of friction. I therefore value packages whose integration instructions expose the necessary decisions early. Here the application chooses the reporting backend, creates the process monitor, and places its work under a lifecycle manager. I can evaluate those responsibilities separately and then review how they fit together.

For adoption, I would start with a small executable using the same backend intended for deployment. I would verify that its measurements arrive with understood units and that the application's shutdown procedure includes the monitoring work. The release supplies a stable collection interface. The consuming application still needs a tested route from those observations to the operational questions its owners intend to answer.