feat: add support macos version
package collector
import (
+ "encoding/xml"
"errors"
"io"
"os"
@@ -32,6 +33,7 @@ import (
const (
etcOSRelease = "/etc/os-release"
usrLibOSRelease = "/usr/lib/os-release"
+ systemVersionPlist = "/System/Library/CoreServices/SystemVersion.plist"
)
var (
@@ -65,6 +67,15 @@ type osReleaseCollector struct {
versionDesc *prometheus.Desc
}
+type Plist struct {
+ Dict Dict `xml:"dict"`
+}
+
+type Dict struct {
+ Key []string `xml:"key"`
+ String []string `xml:"string"`
+}
+
func init() {
registerCollector("os", defaultEnabled, NewOSCollector)
}
@@ -80,7 +91,7 @@ func NewOSCollector(logger log.Logger) (Collector, error) {
[]string{"build_id", "id", "id_like", "image_id", "image_version", "name", "pretty_name",
"variant", "variant_id", "version", "version_codename", "version_id"}, nil,
),
- osReleaseFilenames: []string{etcOSRelease, usrLibOSRelease},
+ osReleaseFilenames: []string{etcOSRelease, usrLibOSRelease, systemVersionPlist},
versionDesc: prometheus.NewDesc(
prometheus.BuildFQName(namespace, "os", "version"),
"Metric containing the major.minor part of the OS version.",
@@ -136,11 +147,18 @@ func (c *osReleaseCollector) UpdateStruct(path string) error {
"file", path, "old_value", c.osMtime, "new_value", t)
c.osFilename = path
c.osMtime = t
-
+ // SystemVersion.plist is xml file with MacOs version info
+ if strings.Contains(releaseFile.Name(), "SystemVersion.plist") {
+ c.os, err = getMacosProductVersion(releaseFile.Name())
+ if err != nil {
+ return err
+ }
+ } else {
c.os, err = parseOSRelease(releaseFile)
if err != nil {
return err
}
+ }
majorMinor := versionRegex.FindString(c.os.VersionID)
if majorMinor != "" {
@@ -179,3 +197,35 @@ func (c *osReleaseCollector) Update(ch chan<- prometheus.Metric) error {
}
return nil
}
+
+func getMacosProductVersion(filename string) (*osRelease, error) {
+ f, _ := os.Open(filename)
+ bytePlist, _ := io.ReadAll(f)
+ f.Close()
+
+ var plist Plist
+ err := xml.Unmarshal(bytePlist, &plist)
+ if err != nil {
+ return &osRelease{}, err
+ }
+
+ var osVersionID, osVersionName, osBuildID string
+ if len(plist.Dict.Key) > 0 {
+ for index, value := range plist.Dict.Key {
+ switch value {
+ case "ProductVersion":
+ osVersionID = plist.Dict.String[index]
+ case "ProductName":
+ osVersionName = plist.Dict.String[index]
+ case "ProductBuildVersion":
+ osBuildID = plist.Dict.String[index]
+ }
+ }
+ }
+ return &osRelease{
+ Name: osVersionName,
+ Version: osVersionID,
+ VersionID: osVersionID,
+ BuildID: osBuildID,
+ }, nil
+}
