Skip to content

Commit 24b5c73

Browse files
authored
cscli support dump: collect system information with gopsutil (#3879)
* cscli support dump: collect system information with gopsutil * format
1 parent 0615518 commit 24b5c73

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

cmd/crowdsec-cli/clisupport/support.go

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ import (
1212
"os"
1313
"path/filepath"
1414
"regexp"
15+
"runtime"
16+
"runtime/debug"
1517
"strconv"
1618
"strings"
1719
"time"
1820

19-
"github.com/blackfireio/osinfo"
21+
"github.com/shirou/gopsutil/v4/cpu"
22+
"github.com/shirou/gopsutil/v4/host"
2023
log "github.com/sirupsen/logrus"
2124
"github.com/spf13/cobra"
25+
"gopkg.in/yaml.v3"
2226

2327
"github.com/crowdsecurity/go-cs-lib/trace"
2428

@@ -42,7 +46,7 @@ const (
4246
SUPPORT_METRICS_DIR = "metrics/"
4347
SUPPORT_VERSION_PATH = "version.txt"
4448
SUPPORT_FEATURES_PATH = "features.txt"
45-
SUPPORT_OS_INFO_PATH = "osinfo.txt"
49+
SUPPORT_SYSTEM_PATH = "system.yaml"
4650
SUPPORT_HUB = "hub.txt"
4751
SUPPORT_BOUNCERS_PATH = "lapi/bouncers.txt"
4852
SUPPORT_AGENTS_PATH = "lapi/agents.txt"
@@ -153,24 +157,65 @@ func (cli *cliSupport) dumpFeatures(zw *zip.Writer) {
153157
cli.writeToZip(zw, SUPPORT_FEATURES_PATH, time.Now(), w)
154158
}
155159

156-
func (cli *cliSupport) dumpOSInfo(zw *zip.Writer) error {
157-
log.Info("Collecting OS info")
160+
func (cli *cliSupport) dumpSystemInfo(zw *zip.Writer) error {
161+
log.Info("Collecting system info (gopsutil + runtime)")
158162

159-
info, err := osinfo.GetOSInfo()
160-
if err != nil {
161-
return err
163+
type snapshot struct {
164+
Timestamp time.Time `yaml:"timestamp"`
165+
GoOS string `yaml:"go_os"`
166+
GoARCH string `yaml:"go_arch"`
167+
GoVersion string `yaml:"go_version"`
168+
NumCPU int `yaml:"num_cpu"`
169+
Goroutines int `yaml:"goroutines"`
170+
CgoCalls int64 `yaml:"cgo_calls"`
171+
172+
Host *host.InfoStat `yaml:"host,omitempty"`
173+
CPUInfo []cpu.InfoStat `yaml:"cpu_info,omitempty"`
174+
CPUCounts struct {
175+
Logical int `yaml:"logical"`
176+
Physical int `yaml:"physical"`
177+
} `yaml:"cpu_counts"`
178+
BuildInfo *debug.BuildInfo `yaml:"build_info,omitempty"`
162179
}
163180

164-
w := new(bytes.Buffer)
165-
fmt.Fprintf(w, "Architecture: %s\n", info.Architecture)
166-
fmt.Fprintf(w, "Family: %s\n", info.Family)
167-
fmt.Fprintf(w, "ID: %s\n", info.ID)
168-
fmt.Fprintf(w, "Name: %s\n", info.Name)
169-
fmt.Fprintf(w, "Codename: %s\n", info.Codename)
170-
fmt.Fprintf(w, "Version: %s\n", info.Version)
171-
fmt.Fprintf(w, "Build: %s\n", info.Build)
181+
s := snapshot{
182+
Timestamp: time.Now(),
183+
GoOS: runtime.GOOS,
184+
GoARCH: runtime.GOARCH,
185+
GoVersion: runtime.Version(),
186+
NumCPU: runtime.NumCPU(),
187+
Goroutines: runtime.NumGoroutine(),
188+
CgoCalls: runtime.NumCgoCall(),
189+
}
190+
191+
// best-effort, errors ignored
192+
193+
if h, err := host.Info(); err == nil {
194+
s.Host = h
195+
}
196+
197+
if ci, err := cpu.Info(); err == nil {
198+
s.CPUInfo = ci
199+
}
200+
201+
if n, err := cpu.Counts(true); err == nil {
202+
s.CPUCounts.Logical = n
203+
}
204+
205+
if n, err := cpu.Counts(false); err == nil {
206+
s.CPUCounts.Physical = n
207+
}
208+
209+
if bi, ok := debug.ReadBuildInfo(); ok {
210+
s.BuildInfo = bi
211+
}
212+
213+
buf, err := yaml.Marshal(&s)
214+
if err != nil {
215+
return fmt.Errorf("serialize system info to YAML: %w", err)
216+
}
172217

173-
cli.writeToZip(zw, SUPPORT_OS_INFO_PATH, time.Now(), w)
218+
cli.writeToZip(zw, SUPPORT_SYSTEM_PATH, time.Now(), bytes.NewReader(buf))
174219

175220
return nil
176221
}
@@ -419,7 +464,7 @@ func (cli *cliSupport) NewCommand() *cobra.Command {
419464
}
420465

421466
// writeToZip adds a file to the zip archive, from a reader
422-
func (cli *cliSupport) writeToZip(zipWriter *zip.Writer, filename string, mtime time.Time, reader io.Reader) {
467+
func (*cliSupport) writeToZip(zipWriter *zip.Writer, filename string, mtime time.Time, reader io.Reader) {
423468
header := &zip.FileHeader{
424469
Name: filename,
425470
Method: zip.Deflate,
@@ -513,8 +558,8 @@ func (cli *cliSupport) dump(ctx context.Context, outFile string) error {
513558
log.Warn(err)
514559
}
515560

516-
if err = cli.dumpOSInfo(zipWriter); err != nil {
517-
log.Warnf("could not collect OS information: %s", err)
561+
if err = cli.dumpSystemInfo(zipWriter); err != nil {
562+
log.Warnf("could not collect system information: %s", err)
518563
}
519564

520565
if err = cli.dumpConfigYAML(zipWriter); err != nil {
@@ -613,7 +658,7 @@ func (cli *cliSupport) NewDumpCmd() *cobra.Command {
613658
Short: "Dump all your configuration to a zip file for easier support",
614659
Long: `Dump the following information:
615660
- Crowdsec version
616-
- OS version
661+
- OS version and runtime system information
617662
- Enabled feature flags
618663
- Latest Crowdsec logs (log processor, LAPI, remediation components)
619664
- Installed collections, parsers, scenarios...

0 commit comments

Comments
 (0)