Library / SDK
prometheus/procfs avatar
prometheus/procfs

procfs: reading Linux process and kernel metrics from Go, without shelling out

procfs provides functions to retrieve system, kernel and process metrics from the pseudo-filesystem proc.

885 stars401 forksGoApache-2.0

At a glance

What is it?
procfs is the Prometheus project Go library that turns the pseudo-filesystems /proc and /sys into typed accessors, one FS type per package, so a monitoring agent can read CPU statistics, disk stats and per-process data without parsing text by hand. The trade is stated in the first paragraph of the documentation: the API may break in backwards-incompatible ways without warnings, and you use it at your own risk.
Who is it for?
Adopt procfs if you are writing a Go agent that needs Linux process, CPU, memory or disk metrics and would rather not parse the pseudo-filesystems yourself, and if you are prepared to track its minor versions. Do not adopt it expecting a stable API, because the documentation warns that it is a work in progress whose API may break in backwards-incompatible ways without warnings.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: /proc is a contract with the kernel, not an API

Almost every Linux system metric lives in a text file under /proc or /sys, and the format of those files is a contract between the kernel and the tools that read it. The contract is not versioned, not documented as a stable interface, and changes with the kernel. Reading them correctly means parsing whitespace separated columns, mapping field positions to names, and knowing which file answers which question.

procfs is the Prometheus project's answer to that for Go. The project description says it provides functions to retrieve system, kernel, and process metrics from the pseudo-filesystem proc, and the documentation is precise that it covers /proc and /sys.

The audience is Go authors writing agents and exporters, which is the same crowd that writes the node_exporter and the process collectors. If your agent is already in Go, using this library is a straightforward way to avoid writing and then maintaining a parser for every file the kernel happens to expose.

Two things about the scope are worth stating. First, this is a library and not a tool: the documentation says the procfs library is intended to be built as part of another application, so there are no distributable binaries. There is nothing to install and run; you add a dependency. Second, it is a low level library. It gives you typed access to the values in the files and leaves the interpretation, the sampling and the exposition to you.

The licence is Apache-2.0, the language is Go with the module path github.com/prometheus/procfs, and the last push was on 2026-10-19, with releases v0.22.0 from 2026-08-28, v0.21.1 from 2026-06-30 and v0.21.0 from 2026-06-27.

The FS type, and why the mount point is a parameter

The design decision that makes the library testable is that the mount point is an argument rather than a constant.

The library is organized by packages based on whether the gathered data is coming from /proc, /sys, or both. Each package contains an FS type which represents the path to either /proc, /sys, or both. The basic case is the root procfs package, where the CPU statistics are gathered from /proc/stat and are available through it:

go
fs, err := procfs.NewFS("/proc")
stats, err := fs.Stat()

The pattern repeats for every package. Some sub-packages such as blockdevice require access to both the proc and sys filesystems, and they take two paths:

go
    fs, err := blockdevice.NewFS("/proc", "/sys")
    stats, err := fs.ProcDiskstats()

That is a small API, and it is the right shape for two reasons. The first is testability: because the mount point is a parameter, a test can point the library at a directory of captured files instead of at the live kernel, which is what the fixture mechanism in this repository exists to support. The second is that it makes the library usable in a container where the host's /proc and /sys are mounted somewhere other than the usual place, which is a common reason for a monitoring library to need a configurable root in the first place.

The naming makes the second point visible. fs.ProcDiskstats in the blockdevice package is named for where the data comes from, while fs.Stat in the root package is named for the file it reads. Once you know the convention, the method names are searchable in a way that a flat list of functions would not be.

Package organisation: by filesystem first, then by information

The organisation rule is stated in the documentation, and it is a two part rule: the packages are organised according to whether the data comes from the /proc or /sys filesystem and the type of information being retrieved.

The examples make it concrete. Most process information can be gathered from the functions in the root procfs package, while information about block devices such as disk drives is available in the blockdevices sub-package.

The repository layout shows how far the split goes. The root of the repository holds the files for data that lives in one place: arp.go, buddyinfo.go, cmdline.go, crypto.go, fs.go, fscache.go, ipvs.go, kernel_hung.go, kernel_random.go, kernel_tainted.go, loadavg.go, mdstat.go and meminfo.go, each with its test file. The CPU information is split by architecture, with cpuinfo.go alongside cpuinfo_armx.go, cpuinfo_loong64.go, cpuinfo_mipsx.go, cpuinfo_others.go, cpuinfo_ppcx.go, cpuinfo_riscvx.go, cpuinfo_s390x.go and cpuinfo_x86.go, because the fields in /proc/cpuinfo differ per architecture and the columns have to be located by name rather than by position.

The filesystem specific subsystems are directories: bcache/, bcachefs/, blockdevice/, btrfs/, ext4/, iscsi/ and internal/. That is a set of filesystems with their own statistics in /proc and /sys, and each gets its own package because each has its own file format.

Two more entries in the root are worth knowing about. doc.go is the package documentation, and fscache.go is a cache layer, which suggests the library keeps parsed values around for a short period so that a caller asking for several related statistics does not re-read and re-parse the same file.

The warning in the first paragraph, and who should heed it

The documentation puts a warning right after the introduction, and it is the most important sentence in the project: this package is a work in progress, its API may still break in backwards-incompatible ways without warnings, and you should use it at your own risk.

That is a stronger statement than the usual pre-one version disclaimer, and it deserves to be read as a design constraint rather than as politeness. The library sits directly on top of a kernel interface that changes without notice, so the shape of the data it returns is partly dictated by the kernel rather than by the maintainers' own compatibility policy. When a new kernel adds a field or renames one, the accessor either gains a method, changes its return type, or stops compiling, and there is no way to keep that from being a breaking change in a Go module with semantic import versioning.

Who should heed it depends on what you are building. If you are writing an exporter whose output is consumed by a long lived monitoring stack, you should pin the version of this library as carefully as you pin the exporter itself, and expect to read the changelog on every upgrade. If you are writing a one-off tool, the risk is much lower, because the blast radius of a compile error is one repository rather than a fleet of collectors.

The dependency list is short enough that the risk is not about supply chain. The module requires google/go-cmp for the tests, golang.org/x/sync and golang.org/x/sys for the system calls, and nothing else, with the go.mod declaring go 1.26.0. A library that reads /proc with no other dependencies is not going to rot in your build, but its API can still move under you.

The upstream project is Prometheus itself, which is the reason to treat the warning seriously rather than as boilerplate. The consumers of this library are the exporters that the whole monitoring ecosystem depends on, and a library that breaks them breaks the ecosystem.

Building and testing: no binaries, and fixtures captured as a ttar

There is nothing to build for distribution, and the documentation is clear about it: the procfs library is intended to be built as part of another application, so there are no distributable binaries. However, most of the API includes unit tests which can be run with make test.

The testing story is the interesting part, because it is where the mount-point-as-parameter decision pays off. The library includes a set of test fixtures which include many example files from the /proc and /sys filesystems, and these fixtures are included as a ttar file, using the ttar format, which is extracted automatically during testing.

So a unit test can read a captured /proc/stat from a machine with a particular kernel, a particular CPU count and a particular state, and assert on the parsed result. Without that, testing a parser for a text file whose layout varies by kernel and architecture would mean running the tests on a variety of machines, which is not a thing a CI system can do reliably.

The Makefile shows the mechanics. The rule is a pattern rule, %/.unpacked: %.ttar, which extracts the archive with the ttar tool and touches a marker file so the extraction happens once. The fixtures target depends on that marker, and the test target depends on the marker and on the shared test target from Makefile.common. The build target is deliberately empty, which matches the statement that there is nothing to build.

For a contributor the practical instruction is in the documentation: to add or update the test fixtures, first ensure the testdata/fixtures directory is up to date by removing the existing directory and then extracting the ttar file using make testdata/fixtures/.unpacked or just make test.

Updating the fixtures, and why it is a maintainer job

The fixture update loop is documented step by step, and it is worth reading because it shows what a change to this library actually costs.

The first step is to regenerate the fixtures directory:

bash
rm -rf testdata/fixtures
make test

Next, make the required changes to the extracted files in the testdata/fixtures directory. When the changes are complete, run make update_fixtures to create a new fixtures.ttar file based on the updated fixtures directory. And finally, verify the changes using git diff testdata/fixtures.ttar.

The Makefile shows what the target does. It removes the unpacked marker and re-creates the archive with the ttar tool, packing the fixtures/ directory into testdata/fixtures.ttar. The instruction to check the diff is the important one, because the archive is a binary blob in the repository and a reviewer cannot see what changed inside it without extracting it.

This is the mechanism by which a new kernel version gets support. A maintainer captures the /proc and /sys files from a machine running the new kernel, drops them into the fixtures directory, runs the update target, and commits the new archive. Any change to the way a file is parsed then has a fixture to test against, and any field the kernel has added shows up as a diff rather than as a runtime surprise on someone else's machine.

The loop is also why the library's coverage is as good as it is for a parser of kernel interfaces, and it is a good illustration of the general principle that the cost of a library like this is not in reading the files, it is in being able to prove you read them the same way the kernel meant you to.

Editorial conclusion

Adopt procfs if you are writing a Go agent that needs Linux process, CPU, memory or disk metrics and would rather not parse the pseudo-filesystems yourself, and if you are prepared to track its minor versions. Do not adopt it expecting a stable API, because the documentation warns that it is a work in progress whose API may break in backwards-incompatible ways without warnings. Before you pin a version, read the changelog between the releases you are leaving and the one you are taking, and run make test once so the bundled fixtures prove your build behaves the way the maintainers expect.

Frequently asked questions

What is the prometheus procfs Go library?

It provides functions to retrieve system, kernel and process metrics from the pseudo-filesystems /proc and /sys. The library is organized by packages based on whether the data comes from /proc, /sys or both, and each package contains an FS type representing the path to those filesystems.

How do I read CPU statistics with procfs?

Initialize the filesystem and then read the stat information, for example fs, err := procfs.NewFS("/proc") followed by stats, err := fs.Stat(). The CPU statistics are gathered from /proc/stat and are available through the root procfs package.

Is the procfs API stable?

The documentation carries a warning that the package is a work in progress and that its API may still break in backwards-incompatible ways without warnings, and that you should use it at your own risk. Pin the version and read the changelog when you upgrade.

How do I run the procfs tests?

Most of the API includes unit tests which can be run with make test. The test target depends on the fixtures being unpacked, and the fixtures are many example files from /proc and /sys bundled as a ttar archive that is extracted automatically during testing.

How do I add or update the procfs test fixtures?

Remove the existing directory with rm -rf testdata/fixtures and run make test to extract the ttar file, make your changes in the extracted files, run make update_fixtures to create a new fixtures.ttar, and verify the change with git diff testdata/fixtures.ttar.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. prometheus/procfs on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/prometheus-procfs.svg)](https://hysenlabs.com/projects/prometheus-procfs)

Was this useful?