@@ -12,13 +12,17 @@ import (
12
12
"os"
13
13
"path/filepath"
14
14
"regexp"
15
+ "runtime"
16
+ "runtime/debug"
15
17
"strconv"
16
18
"strings"
17
19
"time"
18
20
19
- "github.com/blackfireio/osinfo"
21
+ "github.com/shirou/gopsutil/v4/cpu"
22
+ "github.com/shirou/gopsutil/v4/host"
20
23
log "github.com/sirupsen/logrus"
21
24
"github.com/spf13/cobra"
25
+ "gopkg.in/yaml.v3"
22
26
23
27
"github.com/crowdsecurity/go-cs-lib/trace"
24
28
@@ -42,7 +46,7 @@ const (
42
46
SUPPORT_METRICS_DIR = "metrics/"
43
47
SUPPORT_VERSION_PATH = "version.txt"
44
48
SUPPORT_FEATURES_PATH = "features.txt"
45
- SUPPORT_OS_INFO_PATH = "osinfo.txt "
49
+ SUPPORT_SYSTEM_PATH = "system.yaml "
46
50
SUPPORT_HUB = "hub.txt"
47
51
SUPPORT_BOUNCERS_PATH = "lapi/bouncers.txt"
48
52
SUPPORT_AGENTS_PATH = "lapi/agents.txt"
@@ -153,24 +157,65 @@ func (cli *cliSupport) dumpFeatures(zw *zip.Writer) {
153
157
cli .writeToZip (zw , SUPPORT_FEATURES_PATH , time .Now (), w )
154
158
}
155
159
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) " )
158
162
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"`
162
179
}
163
180
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
+ }
172
217
173
- cli .writeToZip (zw , SUPPORT_OS_INFO_PATH , time .Now (), w )
218
+ cli .writeToZip (zw , SUPPORT_SYSTEM_PATH , time .Now (), bytes . NewReader ( buf ) )
174
219
175
220
return nil
176
221
}
@@ -419,7 +464,7 @@ func (cli *cliSupport) NewCommand() *cobra.Command {
419
464
}
420
465
421
466
// 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 ) {
423
468
header := & zip.FileHeader {
424
469
Name : filename ,
425
470
Method : zip .Deflate ,
@@ -513,8 +558,8 @@ func (cli *cliSupport) dump(ctx context.Context, outFile string) error {
513
558
log .Warn (err )
514
559
}
515
560
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 )
518
563
}
519
564
520
565
if err = cli .dumpConfigYAML (zipWriter ); err != nil {
@@ -613,7 +658,7 @@ func (cli *cliSupport) NewDumpCmd() *cobra.Command {
613
658
Short : "Dump all your configuration to a zip file for easier support" ,
614
659
Long : `Dump the following information:
615
660
- Crowdsec version
616
- - OS version
661
+ - OS version and runtime system information
617
662
- Enabled feature flags
618
663
- Latest Crowdsec logs (log processor, LAPI, remediation components)
619
664
- Installed collections, parsers, scenarios...
0 commit comments