Skip to content

Instantly share code, notes, and snippets.

@lawrencejones
Created December 12, 2023 19:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lawrencejones/c576e6f4521458be7f5442f762e82e12 to your computer and use it in GitHub Desktop.
Save lawrencejones/c576e6f4521458be7f5442f762e82e12 to your computer and use it in GitHub Desktop.
Produce build telemetry from a MacBook

MacBook system information

You can run this script in order to extract various runtime and system measurements from a MacBook that might be relevant to performance.

This is a sample output:

{
  "id": "3d0f3c61-480e-4ace-9a65-c6e09ffd2dbd",
  "timestamp": "2023-12-12T19:38:27.013103Z",
  "platform": "Apple M1 Pro",
  "processor_count": 10,
  "memory_total": "16.00 gigabytes",
  "user": "lawrence",
  "power_source": "AC Power",
  "battery_level": "100",
  "memory_free": "62",
  "docker_status": "disabled"
}
package main
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
"sync"
"time"
"github.com/google/uuid"
)
func main() {
data, err := json.MarshalIndent(NewEvent(), "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(data))
}
func NewEvent() *Event {
return &Event{
ID: uuid.New().String(),
Timestamp: time.Now(),
EventHost: getEventHost(),
EventRuntime: getEventRuntime(),
}
}
type Event struct {
ID string `json:"id"`
Timestamp time.Time `json:"timestamp"`
EventHost
EventRuntime
}
type EventHost struct {
Platform string `json:"platform"`
ProcessorCount int `json:"processor_count,omitempty"`
MemoryTotal string `json:"memory_total,omitempty"`
User string `json:"user"`
}
var (
hostEvent EventHost
hostEventOnce sync.Once
processorsRegex = regexp.MustCompile(`^(\d+) processors are physically available.`)
memoryFreeRegex = regexp.MustCompile(`^System-wide memory free percentage:\s+(\d+)%`)
batteryLevelRegex = regexp.MustCompile(`^ -InternalBattery-0.+?(\d+)%`)
powerSourceRegex = regexp.MustCompile(`Now drawing from '(.+)'`)
)
func getEventHost() EventHost {
hostEventOnce.Do(func() {
platformBytes, err := exec.Command("sysctl", "-n", "machdep.cpu.brand_string").Output()
if err != nil {
platformBytes = []byte("unknown")
}
ev := EventHost{
Platform: strings.TrimSpace(string(platformBytes)),
User: os.Getenv("USER"),
}
hostinfo, _ := exec.Command("hostinfo").Output()
for _, line := range strings.Split(string(hostinfo), "\n") {
if processorsRegex.MatchString(line) {
countString := processorsRegex.FindStringSubmatch(line)[1]
count, _ := strconv.ParseInt(countString, 10, 64)
ev.ProcessorCount = int(count)
} else if strings.HasPrefix(line, "Primary memory available: ") {
ev.MemoryTotal = strings.SplitN(line, ": ", 2)[1]
}
}
hostEvent = ev
})
return hostEvent
}
type EventRuntime struct {
PowerSource string `json:"power_source,omitempty"`
BatteryLevel string `json:"battery_level,omitempty"`
MemoryFree string `json:"memory_free,omitempty"`
DockerStatus string `json:"docker_status,omitempty"`
DockerCPU int `json:"docker_cpu,omitempty"`
DockerMemoryTotal int `json:"docker_memory_total,omitempty"`
DockerVersion string `json:"docker_version,omitempty"`
}
func getEventRuntime() (ev EventRuntime) {
memoryPressure, _ := exec.Command("memory_pressure").Output()
for _, line := range strings.Split(string(memoryPressure), "\n") {
if memoryFreeRegex.MatchString(line) {
ev.MemoryFree = memoryFreeRegex.FindStringSubmatch(line)[1]
}
}
// Default assume that docker is disabled.
ev.DockerStatus = "disabled"
var dockerInfo struct {
NCPU int `json:"NCPU"`
MemTotal int `json:"MemTotal"`
ServerVersion string `json:"ServerVersion"`
}
dockerInfoOutput, _ := exec.Command("docker", "info", "--format=json").Output()
_ = json.Unmarshal(dockerInfoOutput, &dockerInfo)
if dockerInfo.ServerVersion != "" {
ev.DockerStatus = "running"
ev.DockerCPU = dockerInfo.NCPU
ev.DockerMemoryTotal = dockerInfo.MemTotal
ev.DockerVersion = dockerInfo.ServerVersion
}
pmset, _ := exec.Command("pmset", "-g", "batt").Output()
ev.PowerSource = "UNKNOWN"
for _, line := range strings.Split(string(pmset), "\n") {
if powerSourceRegex.MatchString(line) {
ev.PowerSource = powerSourceRegex.FindStringSubmatch(line)[1]
} else if batteryLevelRegex.MatchString(line) {
ev.BatteryLevel = batteryLevelRegex.FindStringSubmatch(line)[1]
}
}
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment