{"id":39499734,"url":"https://github.com/gebn/bmc_exporter","last_synced_at":"2026-01-18T05:46:04.682Z","repository":{"id":57499926,"uuid":"199079903","full_name":"gebn/bmc_exporter","owner":"gebn","description":"Exposes Baseboard Management Controller data in Prometheus format.","archived":false,"fork":false,"pushed_at":"2025-09-12T00:12:07.000Z","size":578,"stargazers_count":55,"open_issues_count":16,"forks_count":3,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-09-12T01:09:07.263Z","etag":null,"topics":["bmc","dcmi","ipmi","prometheus"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gebn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-07-26T21:05:29.000Z","updated_at":"2025-09-12T00:12:07.000Z","dependencies_parsed_at":"2024-09-09T08:22:08.738Z","dependency_job_id":"330dd0ce-d9dd-4a9b-a8d6-6bc8cf773578","html_url":"https://github.com/gebn/bmc_exporter","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/gebn/bmc_exporter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gebn%2Fbmc_exporter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gebn%2Fbmc_exporter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gebn%2Fbmc_exporter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gebn%2Fbmc_exporter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gebn","download_url":"https://codeload.github.com/gebn/bmc_exporter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gebn%2Fbmc_exporter/sbom","scorecard":{"id":421270,"data":{"date":"2025-08-11","repo":{"name":"github.com/gebn/bmc_exporter","commit":"55f28f7170ce69d95250dc10c9878115b531c356"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/20 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:75: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:78: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:7: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/gebn/bmc_exporter/ci.yaml/master?enable=pin","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU Lesser General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/ci.yaml:45"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.2.16 not signed: https://api.github.com/repos/gebn/bmc_exporter/releases/179432195","Warn: release artifact v1.2.15 not signed: https://api.github.com/repos/gebn/bmc_exporter/releases/121421571","Warn: release artifact v1.2.14 not signed: https://api.github.com/repos/gebn/bmc_exporter/releases/92901925","Warn: release artifact v1.2.13 not signed: https://api.github.com/repos/gebn/bmc_exporter/releases/76405543","Warn: release artifact v1.2.12 not signed: https://api.github.com/repos/gebn/bmc_exporter/releases/73584049","Warn: release artifact v1.2.16 does not have provenance: https://api.github.com/repos/gebn/bmc_exporter/releases/179432195","Warn: release artifact v1.2.15 does not have provenance: https://api.github.com/repos/gebn/bmc_exporter/releases/121421571","Warn: release artifact v1.2.14 does not have provenance: https://api.github.com/repos/gebn/bmc_exporter/releases/92901925","Warn: release artifact v1.2.13 does not have provenance: https://api.github.com/repos/gebn/bmc_exporter/releases/76405543","Warn: release artifact v1.2.12 does not have provenance: https://api.github.com/repos/gebn/bmc_exporter/releases/73584049"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T01:16:02.623Z","repository_id":57499926,"created_at":"2025-08-19T01:16:02.623Z","updated_at":"2025-08-19T01:16:02.623Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28531443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bmc","dcmi","ipmi","prometheus"],"created_at":"2026-01-18T05:46:03.934Z","updated_at":"2026-01-18T05:46:04.658Z","avatar_url":"https://github.com/gebn.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Prometheus BMC Exporter\n\n[![CI](https://github.com/gebn/bmc_exporter/actions/workflows/ci.yaml/badge.svg)](https://github.com/gebn/bmc_exporter/actions/workflows/ci.yaml)\n[![Docker Hub](https://img.shields.io/docker/pulls/gebn/bmc_exporter.svg)](https://hub.docker.com/r/gebn/bmc_exporter)\n[![Go Reference](https://pkg.go.dev/badge/github.com/gebn/bmc_exporter.svg)](https://pkg.go.dev/github.com/gebn/bmc_exporter)\n[![Go Report Card](https://goreportcard.com/badge/github.com/gebn/bmc_exporter)](https://goreportcard.com/report/github.com/gebn/bmc_exporter)\n\nBaseboard Management Controllers (BMCs) are embedded devices found on server motherboards.\nThey are sometimes referred to by a vendor-specific name, e.g. iDRAC (Dell), iLO (HP), IMM2 (IBM) or ILOM (Oracle).\nBMCs have access to various sensors (e.g. CPU temperature and mains power draw), properties of the system (e.g. the serial number) and fault flags (e.g. fan or PSU failure), making them a valuable source of information about a server estate.\n\nThis [exporter](https://prometheus.io/docs/instrumenting/exporters/) allows a subset of these metrics to be ingested into [Prometheus](https://prometheus.io/docs/introduction/overview/) in a normalised, safe, and efficient way, that scales to tens of thousands of machines per instance.\nIt uses a [native implementation](https://github.com/gebn/bmc) of [IPMI](https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/ipmi-intelligent-platform-mgt-interface-spec-2nd-gen-v2-0-spec-update.pdf), the protocol spoken by BMCs, written with observability in mind, combined with long-lived sessions, to efficiently send the required commands each scrape.\nGuarantees can also be provided around commands in-flight to a single BMC and connection limits, both to avoid overwhelming a machine, and to be a considerate neighbour to existing management software.\nThe tool has no dependency on any of the conventional IPMI command line tools, and never leaves Go.\n\n## Getting Started\n\nDownload the [latest release](https://github.com/gebn/bmc_exporter/releases/latest) for your platform.\nCreate a `secrets.yml` file mapping a sample BMC to its credentials in the following way:\n\n```yaml\n192.0.2.1:623:               # target configured in Prometheus\n  username: \u003cusername\u003e       # must have USER IPMI privileges\n  password: \u003cpassword\u003e\n'[2001:db8::1]:623':\n  username: \u003cusername\u003e\n  password: \u003cpassword\u003e\n```\n\nYou may use a hostname instead of an IP literal, however the exporter uses long-lived sessions, so may fall behind DNS until the next communication failure and reconnect.\nLiterals are preferred for this reason, and also to make config explicit - changes to DNS do not show up in the config's version control history\n\nStart the exporter with `./bmc_exporter [--secrets.static secrets.yml]`.\nNavigate to [http://localhost:9622](http://localhost:9622), and copy the target on the first line of your YAML file into the *Target* text field (e.g. `192.0.2.1:623`), then click *Scrape*.\nYou will be directed to `/bmc?target=\u003cyour target\u003e`, hopefully resembling the following:\n\n    # HELP bmc_info Provides the BMC's GUID, firmware, and the version of IPMI used to scrape it. Constant 1.\n    # TYPE bmc_info gauge\n    bmc_info{firmware=\"3.45.01\",guid=\"04d298z2-8178-11e5-adf4-54ab3a0a0baa\",ipmi=\"2.0\"} 1\n    # HELP bmc_scrape_duration_seconds The time taken to collect all metrics, measured by the exporter.\n    # TYPE bmc_scrape_duration_seconds gauge\n    bmc_scrape_duration_seconds 0.014362754\n    # HELP bmc_up 1 if the exporter was able to establish a session, 0 otherwise.\n    # TYPE bmc_up gauge\n    bmc_up 1\n    # HELP chassis_cooling_fault Whether a cooling or fan fault has been detected, according to Get Chassis Status.\n    # TYPE chassis_cooling_fault gauge\n    chassis_cooling_fault 0\n    # HELP chassis_drive_fault Whether a disk drive in the system is faulty, according to Get Chassis Status.\n    # TYPE chassis_drive_fault gauge\n    chassis_drive_fault 0\n    # HELP chassis_intrusion Whether the system cover is open, according to Get Chassis Status.\n    # TYPE chassis_intrusion gauge\n    chassis_intrusion 0\n    # HELP chassis_power_fault Whether a fault has been detected in the main power subsystem, according to Get Chassis Status.\n    # TYPE chassis_power_fault gauge\n    chassis_power_fault 0\n    # HELP chassis_powered_on Whether the system is currently turned on, according to Get Chassis Status. If 0, the system could be in S4/S5, or mechanical off.\n    # TYPE chassis_powered_on gauge\n    chassis_powered_on 1\n    # HELP power_draw_watts The instantaneous amount of electricity being used by the machine, broken down by PSU where possible.\n    # TYPE power_draw_watts gauge\n    power_draw_watts{psu=\"1\"} 70\n    power_draw_watts{psu=\"2\"} 105\n    # HELP processor_temperature_celsius The temperature of each CPU in degrees celsius.\n    # TYPE processor_temperature_celsius gauge\n    processor_temperature_celsius{cpu=\"1\"} 42\n    processor_temperature_celsius{cpu=\"2\"} 44\n\nIf `bmc_up` has a value of `0`, double check the BMC is reachable from your machine and the credentials are correct using `ipmitool`:\n\n    ipmitool -I lanplus -H \u003cip\u003e -U \u003cusername\u003e -P \u003cpassword\u003e -L USER sdr\n\nIf `bmc_up` is `1`, congrats, you've scraped your first BMC!\nThe Prometheus `scrape_config` for this job would look like this:\n\n```yaml\n- job_name: bmc\n  scrape_interval: 30s                  # a 30s scrape interval is recommended\n  metrics_path: /bmc                    # the exporter exposes its own metrics at /metrics\n  static_configs:\n  - targets:\n    - 192.0.2.1:623                     # strings corresponding to the keys in secrets.yml\n    - '[2001:db8::1]:623'\n  relabel_configs:\n  - source_labels: [__address__]\n    target_label: __param_target\n  - source_labels: [__param_target]\n    target_label: instance\n  - target_label: __address__\n    replacement: localhost:9622         # the location of the exporter to Prometheus\n```\n\n## Metrics\n\nThe exporter may return the following metrics in response to a request to `/bmc`.\nTo prevent Prometheus timing out and throwing everything away, the exporter may return a subset if it does not have time to gather everything.\n\n| Metric | Description |\n|-|-|\n| `bmc_up` | A boolean indicating whether the BMC is healthy. This means a session could be established, the exporter could retrieve the entire SDR repository, and subcollectors had time to do their initialisation. If this is `0`, it is likely to be on the first scrape, as subsequent scrapes reuse the session. |\n| `bmc_scrape_duration_seconds` | This effectively a stopwatch on the `Collect()` method in the exporter. It may differ widely from Prometheus, as the exporter serialises collections for each BMC (some BMCs appear to use a single buffer for all requests, so scraping them simultaneously causes corrupted responses). The time a request spends waiting for the target's event loop to pick it up is not included in this value, however it is tracked by the `bmc_target_scrape_dispatch_latency_seconds` histogram. |\n| `bmc_info` |  A constant `1`, providing the `firmware` version and `guid` of the BMC in labels, along with the `version` of IPMI being used by the exporter to interact with it (which will currently always be `2.0`). Each BMC vendor includes different supplementary version information, which is used to create the version string on a best-effort basis. The GUID label uses the original byte order; this can be in any format, and any byte order, so cannot be interpreted reliably without additional knowledge. Treating the original bytes as a GUID seems to work fairly well. On Dell this matches the smbiosGUID field in the iDRAC UI, and on Quanta it produces a valid version 1 GUID. These values are all obtained from the `Get Device ID` and `Get System GUID` commands. |\n| `chassis_powered_on` | A boolean indicating whether the system power is on. If `0`, it could be in S4/S5, or mechanical off. This value is returned in the `Get Chassis Status` command. |\n| `chassis_cooling_fault` | A boolean indicating whether a cooling or fan fault has been detected. Obtained via `Get Chassis Status`. |\n| `chassis_drive_fault` | A boolean indicating whether a disk drive in the system is faulty. Obtained via `Get Chassis Status`. |\n| `chassis_power_fault` | A boolean indicating whether a fault has been detected in the main power subsystem. Obtained via `Get Chassis Status`. |\n| `chassis_intrusion` | A boolean indicating whether the chassis is currently open. Retrieved via `Get Chassis Status`. |\n| `power_draw_watts` | One gauge for each wattage sensor instance under the *power supply* SDR entity, in which case the `psu` label is the instance ID, so may not be 0-based or continuous (treat these as opaque strings). If power usage isn't available in the SDR, this will fall back to issuing a `Get Power Reading` DCMI command, which returns a label-less aggregate draw for the entire machine. The power supplies must support PMBus for either mechanism to work. Values could theoretically have a fractional component, however all values observed have been integers. |\n| `processor_temperature_celsius` | One gauge for each temperature sensor under the *processor* SDR entity. This usually corresponds to one sensor per die rather than per core. We prefer sensors with the IPMI entity ID (`0x3`), falling back to the deprecated DCMI variant (`0x41`). We never combine sensors from both in order to avoid duplication. Only sensors with a unit of celsius are currently considered. Values could theoretically have a fractional component, however all values observed have been integers. |\n\n### Interesting Queries\n\nNumber of machines by BMC firmware:\n\n    sum by (firmware) (bmc_info)\n\nNumber of machines with a cooling fault:\n\n    sum(chassis_cooling_fault == bool 1)\n\nRatio of machines currently powered on:\n\n    sum(chassis_powered_on == bool 1) / count(chassis_powered_on)\n\nIt is strongly recommended to set appropriate target labels for the manufacturer, model and location of each machine.\nThis allows more interesting aggregations, e.g. viewing the different firmware versions installed for a single model, or power usage by data centre field.\nBy `count()`ing the `*_fault` metrics, you could also see which model is proving most troublesome overall, and eventually trends of all of the above over time.\n\n## Next Steps\n\nThe exporter listens on `:9622` by default, which can be overridden with `--web.listen-address`.\nA homepage is exposed at `/` with the exporter's version, and a simple form to scrape a given address.\nThis also doubles as a liveness and/or readiness probe endpoint.\nThe exporter's own metrics, including total IPMI commands sent and various latency and traffic statistics, are exposed at `/metrics`.\nThis can be scraped more frequently than a given BMC if required.\nTo scrape a BMC, request `/bmc?target=\u003cIP[:port]\u003e`.\nNote that the target parameter is passed verbatim to the session provider.\nAlthough the port defaults to 623, for consistency and to avoid confusion, it is recommended to be explicit and include the port after the IP address wherever it appears.\n\n### Ulimit\n\nThe exporter requires one file descriptor per BMC for the UDP socket, so you may need to increase the limit.\nTo see the current number of file descriptors a process may open, run `ulimit -n`.\nYou can maximise the number of fds the exporter may use by running `ulimit -Sn $(ulimit -Hn)`.\n\n### Scrape Interval\n\nA scrape interval of 30s is recommended.\nThe IPMI specification recommends a 60s (+/-3s) timeout for sessions on the BMC, so provided your scrape interval is below this, this should be the only session for the lifetime of the exporter process.\nIf deployed in a pair as recommended in the [Deployment](#Deployment) section, this will result in each exporter scraping every 60s, assuming perfect round-robin.\n\n### Scrape Timeout\n\nScraping a healthy, available BMC from within the data centre takes a fraction of a second, however this will never be the case for all targets with any sizeable fleet.\nThe exporter will retry commands outside a session in an exponential back-off, but retrying inside a session has been known to cause corrupted responses (#29), so we re-establish the session after 5 seconds.\nEach scrape also has a timeout within the exporter, defaulting to 8s (to allow wiggle room before the default Prometheus scrape timeout of 10s) and overridable via `--scrape.timeout`.\nThe idea behind this is that *some* data is better than no data.\nIf a BMC is excruciatingly slow, it is better to return a subset of metrics than nothing whatsoever.\nThis can only be done if the exporter knows to give up on the BMC before Prometheus gives up on the exporter.\nLike the [`blackbox_exporter`](https://github.com/prometheus/blackbox_exporter), all targets in Prometheus that hit the exporter should show as `UP`, regardless of the underlying machine.\nIf this is not the case, it suggests something wrong with the exporter or Prometheus configuration rather the BMC.\n\n## Deployment\n\nFiring up a single instance of the exporter will work just fine for evaluation.\nAs the IPMI protocol operates in lock-step, similar to TFTP, a small increase in latency is multiplied by the number of packets required to perform the scrape.\nIt is strongly recommended to locate the exporter in the same region as the BMCs it scrapes.\nAttempting to scrape across the Atlantic or further will slow down scrapes significantly, and the effects of any packet loss will be magnified.\n\nThe exporter has been designed around only having one open socket and session to a given BMC, and sending only one command at once to it.\nThis is important, as the specification only requires support for two concurrent sessions between the LAN and console channels, and a network buffer with capacity for two packets.\nIt is recommended to have a pair of exporters in each region, behind the same DNS record or K8s service, and point Prometheus at that alias.\nThis will result in two sessions being established with the BMC, which allows room for use by other system management software, while having N+1 resiliency.\nA single exporter will serialise multiple scrape requests for a given BMC arriving at the same time, so it is fine to point multiple Prometheis at it.\nHowever, in this case, it is recommended to increase the scrape timeout, as if all N scrapes arrive simultaneously for an unresponsive BMC, the last one will take `N * --scrape.timeout` seconds.\nIf in doubt, set the scrape timeout to equal the scrape interval.\n\nIf you have too many BMCs to scrape with one exporter, or would like to spread the load more thinly, it is recommended to shard targets across multiple pairs of exporters, e.g. half go to one pair, half to another.\nThis maintains the property of having at most two sessions per BMC, and means a single exporter dying results in loss of resiliency for a smaller subset of BMCs.\n\nOn `SIGINT` or `SIGTERM`, the exporter will shut down its web server, then wait for all in-progress scrapes to finish before closing all BMC connections and sockets as cleanly as possible.\nThis can take some time with thousands of BMCs, especially if some are unresponsive.\nThere is no timeout built into the exporter; it relies on the environment to kill it when it is fed up waiting.\n\n### Alerts\n\nIn addition to alerting on BMC metrics, you may want to be notified of an unhealthy exporter. Both the exporter and its underlying `bmc` library were written with Prometheus in mind, so you have lots of metrics, from collection latency to to number of each IPMI command attempted. This section is intended to provide a guide for what to look at. Exact alert thresholds will depend on the number of targets in the estate and how the exporter is deployed.\n\n#### BMC\n\nAlerts for metrics exposed at `/bmc`. The key one here is `bmc_up`, however you may want to alert on others (e.g. `chassis_cooling_fault`) depending on your environment. Be wary of using IPMI to alert on `chassis_power_fault`, as any significant problem will cause the BMC to also lose power! It is better to use `bmc_up` as an indication of an unhealthy machine.\n\n| Metric | Description |\n|-|-|\n| `bmc_up` | Every BMC where this is `0` is a monitoring gap, as no other metrics (besides `bmc_scrape_duration_seconds`) are exposed. It can be caused by incorrect credentials (check `bmc_session_open_failures_total`), or running out of time while initialising after the session is established, typically because of high latency (see `bmc_collector_initialise_timeouts_total` below). |\n\n#### Exporter\n\nThese metrics are exposed at `/metrics`, so are an overall view of all scrapes going through the exporter and do not concern any single BMC. They can indicate a configuration error in Prometheus or the exporter, and general network issues. Note that [pprof](https://golang.org/pkg/runtime/pprof/) is enabled on the exporter at the default paths, so profiles can be retrieved at any time.\n\n| Metric | Description |\n|-|-|\n| `bmc_collector_initialise_timeouts_total` | If this increases too rapidly, it suggests BMCs have too high latency to complete initialisation before Prometheus times out the scrape. This causes a kind of crash looping behaviour where the BMC never manages to be ready for scraping. The solution is to increase the scrape timeout, or move the exporter closer to the BMC. |\n| `bmc_collector_partial_collections_total` | This counts the number of times the exporter returned a subset of metrics to avoid Prometheus timing out the scrape request. If this happens too often the scrape timeout may be too low, or BMCs may be being reticent. |\n| `bmc_collector_session_expiries_total` | The specification recommends a timeout of 60s +/- 3s, so if you have deployed the exporter in a pair and scrape every 30s, a high rate of increase indicates a load balancing issue. When the session expires, the exporter will attempt to establish a new one, so this is not a problem in itself; it just results in a few more requests and higher load on BMCs. If your scrape interval is 2m, you would expect every scrape to require a new session. |\n| `bmc_provider_credential_failures_total` | Any increase here indicates the credential provider is struggling to fulfil requests, and BMCs cannot be logged into. The only bundled implementation is the file provider, so these errors will not be temporary, and indicates the exporter is being asked to scrape a set of BMCs that has drifted from its secrets config file. |\n| `bmc_target_abandoned_requests_total` | A high rate of abandoned requests indicates contention for access to BMCs. This is most likely to be caused by multiple Prometheis scraping a single exporter with a short scrape timeout. These requests did not have time to begin a collection, let alone initialise a session. |\n| `process_open_fds` | The exporter requires one file descriptor per BMC, plus 15-20% depending on the scrape interval. You'll want to alert if `process_open_fds / process_max_fds` approaches `1`. |\n\n## Limitations\n\n - Only power draw and processor temperature sensor data is currently available. Other sensors are far less standardised, so normalising them in the exporter's output - a key feature - is much harder. Next up is `chassis_(intake|exhaust)_temperature_celsius`.\n - IPMI v1.5, the first to feature IPMI-over-LAN support, is currently unimplemented in the underlying library. Given IPMI v2.0 was first published in 2004, this is hopefully not relevant to most, however for the sake of legacy devices and completeness, it will be added after non-power sensor data is retrievable. The exporter itself is already version-agnostic.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgebn%2Fbmc_exporter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgebn%2Fbmc_exporter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgebn%2Fbmc_exporter/lists"}