https://github.com/osapi-io/gohai
A Go-based system fact collector inspired by Chef Ohai.
https://github.com/osapi-io/gohai
facts golang node-exporter ohai osapi system-information
Last synced: 21 days ago
JSON representation
A Go-based system fact collector inspired by Chef Ohai.
- Host: GitHub
- URL: https://github.com/osapi-io/gohai
- Owner: osapi-io
- License: mit
- Created: 2026-04-12T00:54:49.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-19T20:03:29.000Z (about 2 months ago)
- Last Synced: 2026-04-19T22:07:20.120Z (about 2 months ago)
- Topics: facts, golang, node-exporter, ohai, osapi, system-information
- Language: Go
- Size: 15 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Contributing: docs/contributing.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/osapi-io/gohai/releases/latest)
[](https://codecov.io/gh/osapi-io/gohai)
[](https://goreportcard.com/report/github.com/osapi-io/gohai)
[](LICENSE)
[](https://github.com/osapi-io/gohai/actions/workflows/go.yml)
[](https://github.com/goreleaser)
[](https://conventionalcommits.org)
[](https://just.systems)

[](https://pkg.go.dev/github.com/osapi-io/gohai/pkg/gohai)
# gohai
**gohai is an SDK-first Go library** for collecting comprehensive system
facts, inspired by [Chef Ohai][]. Import it into your Go application for
typed access to system facts β or use the standalone `gohai` CLI, a thin
wrapper over the same SDK.
> π§ **Linux-first.** macOS is supported with a narrower field surface
> (see per-collector docs for platform coverage); Windows is not supported.
Each collector wraps a well-maintained backing source ([gopsutil][],
[ghw][], [procfs][], cloud SDKs) and reshapes its output into typed Go
structs. gohai's value is the unified API, typed structs, and pluggable
collector model β not reimplementing `/proc` parsing from scratch.
### Schema: OCSF + OpenTelemetry + Ohai
Fact naming and structure follow, in order of precedence:
1. **[OCSF][]** (Open Cybersecurity Schema Framework) β the primary
schema. Backed by AWS and Splunk for asset, observability, and
security data. Aligning means gohai output feeds SIEMs, data lakes,
and inventory tools without translation. Browse
[schema.ocsf.io][ocsf-schema] to see field names and object shapes.
2. **[OpenTelemetry Resource Semantic Conventions][otel-semconv]** β
used when OCSF is silent. Widely adopted for observability
telemetry; covers areas OCSF hasn't (per-CPU vendor/family/model,
system load averages, process runtime, host uptime).
What we collect (which facts, which distro edge cases, which fallback
sources) draws on [Chef Ohai][]'s years of accumulated plugin logic.
What we call each field draws on OCSF + OpenTelemetry. We do **not**
pursue Ohai JSON shape parity β Ruby Mash β Go struct translation
isn't worth pinning byte-for-byte.
### Primary consumer
gohai is built to be embedded in [OSAPI][] and other Go services that need
typed system facts for routing, guards, discovery, inventory, and
compliance. The CLI is a convenience β the SDK is the product.
## π¦ Install
```bash
go install github.com/osapi-io/gohai/cmd/gohai@latest
```
As a library dependency:
```bash
go get github.com/osapi-io/gohai
```
## β¨ Features
| Feature | Description |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| π Pluggable Collectors | Enable/disable individual fact collectors |
| ποΈ Typed Structs | Strongly-typed Go structs for all facts |
| π JSON Output | Nested JSON output for CLI and programmatic use |
| πΊοΈ Flat Map Access | Dot-separated key-value access |
| π§ Cross-Platform | Linux primary, macOS best-effort |
| π Collector Dependencies | Automatic dependency resolution between facts |
| β‘ Concurrent Collection | Collectors run concurrently; dependency graph resolves order when any collector declares deps. |
| β±οΈ Per-Collector Timings | Opt-in `--with-timings` / `WithTimings()` embeds per-collector durations, status, and error messages under `_timings` in the JSON output |
| π OCSF + OpenTelemetry + Ohai | Field names follow [OCSF](https://schema.ocsf.io/) then [OpenTelemetry](https://opentelemetry.io/docs/specs/semconv/resource/); data sources mirror Chef Ohai's plugins |
| π SDK Integration | Import as a Go package for OSAPI and others |
## π Collectors
65 collectors across 9 categories. See the **[Collectors
reference](docs/collectors/README.md)** for the full catalog β
implementation status, default membership, schema mappings, and
per-collector docs.
Collectors are individually toggled using node_exporter-style flags β
`--collector.` to opt in, `--no-collector.` to opt out. SDK
consumers use `gohai.WithEnabled(...)` / `gohai.WithDisabled(...)` /
`gohai.WithCollectors(...)`.
**Defaults are opt-in.** `gohai.New()` returns an empty registry. Pass
`gohai.WithDefaults()` for the recommended set (cheap + near-universal β
identity, base hardware, network, load, virt detect). The CLI wires
`WithDefaults()` automatically; pass `--no-defaults` to skip it and use only
explicit `--collector.X` flags.
## π― Usage
### CLI
```bash
# Collect the recommended default collector set
gohai
# Pretty-printed JSON
gohai --pretty
# Flat key=value pairs instead of nested JSON
gohai --flat
# Enable specific collectors on top of the defaults
gohai --collector.process --collector.packages
# Disable specific collectors
gohai --no-collector.virtualization --no-collector.network
# Skip defaults entirely; run only what --collector.X turns on
gohai --no-defaults --collector.platform --collector.cpu
# Embed per-collector timings + errors under `_timings` in the JSON
gohai --with-timings --pretty
# List every registered collector and exit
gohai --list-collectors
```
### SDK
Importers should read the [full API reference on pkg.go.dev][Package
documentation] for every `Option`, `Facts` field, and `Info` struct β
that's the authoritative API surface. The examples below show the two
usage shapes.
**Collecting facts** (producer side):
```go
package main
import (
"context"
"fmt"
"log"
"github.com/osapi-io/gohai/pkg/gohai"
)
func main() {
g, err := gohai.New(
gohai.WithDefaults(), // the recommended set
gohai.WithEnabled("process", "packages"), // plus these two
)
if err != nil {
log.Fatal(err)
}
facts, err := g.Collect(context.Background())
if err != nil {
log.Fatal(err)
}
// Typed access β pkg.go.dev documents every Info struct's fields.
fmt.Printf("OS: %s %s\n", facts.Platform.Name, facts.Platform.Version)
fmt.Printf("Cores: %d\n", facts.CPU.Cores)
fmt.Printf("Memory: %d bytes\n", facts.Memory.Total)
// Serialize for transport / storage.
b, _ := facts.PrettyJSON()
fmt.Println(string(b))
}
```
**Consuming stored facts** (decoder side β e.g. a server that received
a fact blob from an agent):
```go
var facts gohai.Facts
if err := json.Unmarshal(payload, &facts); err != nil {
log.Fatal(err)
}
// Typed access on the decoded value β no map[string]any guessing.
fmt.Println(facts.Platform.Name, facts.CPU.Cores)
fmt.Println(facts.Network.DefaultInterface)
```
Per-collector timings + error messages can be embedded in Facts by adding
`gohai.WithTimings()` to `gohai.New(...)` β useful for debugging slow
collectors or seeing why a collector failed without blocking the run.
See the `Timings` field on [pkg.go.dev][Package documentation].
**Detecting which cloud you're on.** Enable the cloud collectors
(`WithCategory("cloud")`) and switch on `Facts.Cloud()` β returns a
`*Cloud` with `Name` set to a provider identifier, or nil when no
cloud was detected. Use the exported `gohai.CloudAWS` / `CloudGCE` /
`CloudAzure` / etc. constants instead of raw strings:
```go
g, _ := gohai.New(gohai.WithCategory("cloud"))
facts, _ := g.Collect(ctx)
cloud := facts.Cloud()
if cloud == nil { return } // not on a supported cloud
switch cloud.Name {
case gohai.CloudAWS:
fmt.Println(facts.Ec2.Region, facts.Ec2.IAMInfo.InstanceProfileArn)
case gohai.CloudGCE:
fmt.Println(facts.Gce.ProjectID, facts.Gce.Zone)
}
```
Rich per-provider data lives on the typed `Facts.Ec2` / `Facts.Gce` /
etc. field. See [docs/collectors/cloud.md](docs/collectors/cloud.md)
for the full pattern.
## π Documentation
- [Package documentation][] on pkg.go.dev β generated API reference. Every
`Option`, `Facts` field, and `Info` struct is documented there. This is
the authoritative SDK reference.
- [Collectors reference](docs/collectors/README.md) β one doc per collector
with fields, schema mappings (OCSF + OpenTelemetry), and Ohai source
alignment.
- [Development](docs/development.md) β prerequisites, setup, testing, commit
conventions.
- [Contributing](docs/contributing.md) β PR workflow.
## π€ Contributing
See the [Development](docs/development.md) guide for prerequisites, setup,
and conventions. See the [Contributing](docs/contributing.md) guide before
submitting a PR.
## π Related Works
gohai stands on the shoulders of the following projects β as methodology
references, as backing libraries we wrap, or as peers solving adjacent
problems:
**Fact collectors (direct peers):**
- [Chef Ohai][] β the canonical reference. Ruby-based plugin-driven fact
collector; every gohai collector cross-references the corresponding
Ohai plugin for data sources and per-distro edge cases.
- [Puppet Facter](https://github.com/puppetlabs/facter) β Puppet's
equivalent. Different JSON shape, overlapping fact surface.
- [osquery](https://github.com/osquery/osquery) β Meta's SQL-based
endpoint visibility. Different abstraction (SQL), same data space;
common reference point when evaluating an inventory tool.
- [Ansible setup](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/setup_module.html) β
Ansible's built-in fact gathering, exposed as `ansible_facts` in
playbooks.
- [Salt Grains](https://docs.saltproject.io/en/latest/topics/grains/) β
SaltStack's static facts.
**Backing libraries (we import these):**
- [gopsutil][] β primary source for dynamic runtime state (memory,
network I/O, process enumeration, virtualization detection).
- [ghw][] β canonical for physical hardware topology (CPU NUMA,
DIMMs, block devices, DMI, GPU, PCI).
- [procfs][] β Linux `/proc` and `/sys` parsing when a library doesn't
cover a field.
- [go-sysinfo](https://github.com/elastic/go-sysinfo) β Elastic's
alternative for host/platform/kernel facts.
- [avfs](https://github.com/avfs/avfs) β virtual filesystem
abstraction used in every collector that reads files, so tests can
run against in-memory fixtures.
**Other Go libraries in the space:**
- [gosigar](https://github.com/cloudfoundry/gosigar) β Cloud Foundry's
Go port of Hyperic Sigar. Historical reference for Go-based host
metrics.
- [go-ps](https://github.com/mitchellh/go-ps) β narrow process-listing
library. gopsutil supersedes it for our use.
- [goprocinfo](https://github.com/c9s/goprocinfo) β lightweight `/proc`
parser. gopsutil + procfs cover the same ground for us.
**Methodology references (we read, don't import):**
- [node_exporter](https://github.com/prometheus/node_exporter) β gold
standard for tricky Linux `/proc` and `/sys` parsing. Apache-2, but
we rewrite in our style rather than import.
- [psutil](https://github.com/giampaolo/psutil) β the Python library
gopsutil is a port of; the original design reference for the
dynamic-state facts.
## π License
The [MIT][] License.
[Chef Ohai]: https://docs.chef.io/ohai/
[OSAPI]: https://github.com/osapi-io/osapi
[gopsutil]: https://github.com/shirou/gopsutil
[ghw]: https://github.com/jaypipes/ghw
[procfs]: https://github.com/prometheus/procfs
[OCSF]: https://ocsf.io/
[ocsf-schema]: https://schema.ocsf.io/
[otel-semconv]: https://opentelemetry.io/docs/specs/semconv/resource/
[package documentation]: https://pkg.go.dev/github.com/osapi-io/gohai/pkg/gohai
[MIT]: LICENSE