Log more OS info at startup

In addition to logging `GOOS` and `GOARCH`, also log more info about the
system:

- Windows: the Windows version and edition.
- Linux: distribution, distribution version, and kernel version.
- macOS: just "macOS", until we know more about getting info there too.
This commit is contained in:
Sybren A. Stüvel 2023-10-15 14:15:46 +02:00
parent 879a280da2
commit 12bc182857
9 changed files with 151 additions and 2 deletions

@ -22,6 +22,7 @@ bugs in actually-released versions.
- Show the configured Flamenco Manager name in the webapp's browser window title.
- Workers can be marked as 'restartable' by using the `-restart-exit-code N` commandline option. More info in the [Worker Actions documentation](https://flamenco.blender.org/usage/worker-actions/).
- The `{timestamp}` placeholder in the render output path is now replaced with a local timestamp (rather than UTC).
- Log more information about the operating system at startup. On Windows this includes the version & edition (like "Core" or "Professional"), and on Linux this includes the distribution, version, and kernel version.
- Security updates of some dependencies:
- https://pkg.go.dev/vuln/GO-2023-1989
- https://pkg.go.dev/vuln/GO-2023-1990

@ -39,6 +39,7 @@ import (
"projects.blender.org/studio/flamenco/internal/own_url"
"projects.blender.org/studio/flamenco/internal/upnp_ssdp"
"projects.blender.org/studio/flamenco/pkg/shaman"
"projects.blender.org/studio/flamenco/pkg/sysinfo"
)
var cliArgs struct {
@ -58,11 +59,17 @@ const (
func main() {
output := zerolog.ConsoleWriter{Out: colorable.NewColorableStdout(), TimeFormat: time.RFC3339}
log.Logger = log.Output(output)
osDetail, err := sysinfo.Description()
if err != nil {
osDetail = err.Error()
}
log.Info().
Str("version", appinfo.ApplicationVersion).
Str("git", appinfo.ApplicationGitHash).
Str("releaseCycle", appinfo.ReleaseCycle).
Str("os", runtime.GOOS).
Str("osDetail", osDetail).
Str("arch", runtime.GOARCH).
Msgf("starting %v", appinfo.ApplicationName)

@ -23,6 +23,7 @@ import (
"projects.blender.org/studio/flamenco/internal/appinfo"
"projects.blender.org/studio/flamenco/internal/worker"
"projects.blender.org/studio/flamenco/internal/worker/cli_runner"
"projects.blender.org/studio/flamenco/pkg/sysinfo"
)
var (
@ -61,12 +62,18 @@ func main() {
output := zerolog.ConsoleWriter{Out: colorable.NewColorableStdout(), TimeFormat: time.RFC3339}
log.Logger = log.Output(output)
osDetail, err := sysinfo.Description()
if err != nil {
osDetail = err.Error()
}
log.Info().
Str("version", appinfo.ApplicationVersion).
Str("git", appinfo.ApplicationGitHash).
Str("releaseCycle", appinfo.ReleaseCycle).
Str("OS", runtime.GOOS).
Str("ARCH", runtime.GOARCH).
Str("os", runtime.GOOS).
Str("osDetail", osDetail).
Str("arch", runtime.GOARCH).
Int("pid", os.Getpid()).
Msgf("starting %v Worker", appinfo.ApplicationName)
configLogLevel()

1
go.mod

@ -54,6 +54,7 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
github.com/zcalusic/sysinfo v1.0.1 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect

2
go.sum

@ -172,6 +172,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zcalusic/sysinfo v1.0.1 h1:cVh8q3codjh43AGRTa54dJ2Zq+qPejv8n2VWpxKViwc=
github.com/zcalusic/sysinfo v1.0.1/go.mod h1:LxwKwtQdbTIQc65drhjQzYzt0o7jfB80LrrZm7SWn8o=
github.com/ziflex/lecho/v3 v3.1.0 h1:65bSzSc0yw7EEhi44lMnkOI877ZzbE7tGDWfYCQXZwI=
github.com/ziflex/lecho/v3 v3.1.0/go.mod h1:dwQ6xCAKmSBHhwZ6XmiAiDptD7iklVkW7xQYGUncX0Q=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

15
pkg/sysinfo/sysinfo.go Normal file

@ -0,0 +1,15 @@
package sysinfo
// SPDX-License-Identifier: GPL-3.0-or-later
// CanSymlink tries to determine whether the running system can use symbolic
// links.
func CanSymlink() (bool, error) {
return canSymlink()
}
// Description returns a string that describes the current platform in more
// detail than runtime.GOOS does.
func Description() (string, error) {
return description()
}

@ -0,0 +1,14 @@
package sysinfo
// SPDX-License-Identifier: GPL-3.0-or-later
// canSymlink always returns true, as symlinking on non-Windows platforms is not
// hard.
func canSymlink() (bool, error) {
return true, nil
}
func description() (string, error) {
// TODO: figure out how to get more info on macOS.
return "macOS", nil
}

@ -0,0 +1,22 @@
package sysinfo
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"fmt"
the_other_sysinfo "github.com/zcalusic/sysinfo"
)
// canSymlink always returns true, as symlinking on non-Windows platforms is not
// hard.
func canSymlink() (bool, error) {
return true, nil
}
func description() (string, error) {
var si the_other_sysinfo.SysInfo
si.GetSysInfo()
description := fmt.Sprintf("%s (%s)", si.OS.Name, si.Kernel.Release)
return description, nil
}

@ -0,0 +1,80 @@
package sysinfo
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"fmt"
"github.com/rs/zerolog/log"
"golang.org/x/sys/windows/registry"
)
// editionCanSymlink maps the EditionID key in the registry to a boolean indicating whether
// symlinks are available.
var editionCanSymlink = map[string]bool{
"Core": false, // Windows Home misses the tool to allow symlinking to a user.
"Professional": true, // Still requires explicit right to be assigned to the user.
}
// canSymlink tries to determine whether the running system can use symbolic
// links, based on information from the Windows registry.
func canSymlink() (bool, error) {
editionID, err := windowsEditionID()
if err != nil {
return false, fmt.Errorf("determining edition of Windows: %w", err)
}
canSymlink, found := editionCanSymlink[editionID]
if !found {
log.Warn().Str("editionID", editionID).Msg("unknown Windows edition, assuming it can use symlinks")
return true, nil
}
return canSymlink, nil
}
func description() (string, error) {
productName, err := registryReadString(
`SOFTWARE\Microsoft\Windows NT\CurrentVersion`,
"ProductName",
)
if err != nil {
return "", err
}
editionID, err := windowsEditionID()
if err != nil {
return "", err
}
description := fmt.Sprintf("%s (%s)", productName, editionID)
return description, nil
}
func windowsEditionID() (string, error) {
// Values seen so far:
// - "Professional"
// - "Core"
return registryReadString(
`SOFTWARE\Microsoft\Windows NT\CurrentVersion`,
"EditionID",
)
}
func registryReadString(keyPath, valueName string) (string, error) {
regkey, err := registry.OpenKey(
registry.LOCAL_MACHINE,
keyPath,
registry.QUERY_VALUE)
if err != nil {
return "", fmt.Errorf("opening registry key %q: %w", keyPath, err)
}
defer regkey.Close()
value, _, err := regkey.GetStringValue(valueName)
if err != nil {
return "", fmt.Errorf("reading registry key %q: %w", valueName, err)
}
return value, nil
}