mattermost/server/channels/app/platform/uptime_linux.go
Ben Schumacher 58052db8e3
[MM-67976] Add server uptime to support packet (#35838)
* MM-67976: Add server uptime to support packet

Add process start time (started_at) and approximate host start time
(host_started_at, Linux only, derived from /proc/uptime) to the support
packet diagnostics. This helps diagnose restart loops and distinguish
process restarts from full machine/container reboots.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* Add HostStartedAt assertions to support packet happy-path test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Revert unrelated changes

* Add unit tests for getHostUptimeSeconds and fix cross-platform portability

- Extract parseUptimeFile helper in uptime_linux.go to enable unit testing
  with synthetic file paths without touching the real /proc/uptime
- Add uptime_linux_test.go covering all error paths (file read error,
  empty file, non-numeric value) and happy-path parsing
- Add uptime_other_test.go asserting the non-Linux stub returns
  ErrHostUptimeUnsupportedPlatform and zero seconds
- Guard HostStartedAt assertions in support_packet_test.go with
  runtime.GOOS so the test correctly asserts zero-time on non-Linux
  platforms instead of failing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: use t.TempDir() for guaranteed-missing path in uptime test

Replace the hard-coded /nonexistent/proc/uptime path with a path
constructed from t.TempDir() to guarantee the file is absent without
relying on filesystem layout assumptions. Also remove the misleading
comment about swapping implementations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Reorder Server struct fields and assignments to group process identity fields together

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add macOS support for host uptime in support packet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-21 10:52:10 +00:00

41 lines
1 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
//go:build linux
package platform
import (
"fmt"
"os"
"strconv"
"strings"
)
// getHostUptimeSeconds reads /proc/uptime and returns the number of seconds
// the host OS has been running.
func getHostUptimeSeconds() (int64, error) {
return parseUptimeFile("/proc/uptime")
}
// parseUptimeFile reads an uptime file in the /proc/uptime format and returns
// the number of seconds as an int64. It is a separate function to allow unit
// tests to supply a synthetic file path.
func parseUptimeFile(path string) (int64, error) {
data, err := os.ReadFile(path)
if err != nil {
return 0, fmt.Errorf("failed to read /proc/uptime: %w", err)
}
fields := strings.Fields(string(data))
if len(fields) == 0 {
return 0, fmt.Errorf("unexpected /proc/uptime format")
}
f, err := strconv.ParseFloat(fields[0], 64)
if err != nil {
return 0, fmt.Errorf("failed to parse /proc/uptime value: %w", err)
}
return int64(f), nil
}