github.com/nya3jp/tast@v0.0.0-20230601000426-85c8e4d83a9b/src/go.chromium.org/tast/core/internal/logs/reader.go (about) 1 // Copyright 2020 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package logs 6 7 import ( 8 "compress/gzip" 9 "context" 10 "fmt" 11 "io" 12 "os/exec" 13 "regexp" 14 ) 15 16 // croslogCursorRegexp parses output from a `croslog --show-cursor` command. Example output: 17 // -- cursor: s=bfd03b7e4c464cc09b43e1843880f9ee;i=a5eab;b=cdd933be... 18 var croslogCursorRegexp = regexp.MustCompile(`^-- cursor:\s+(\S+)`) 19 20 // GetUnifiedLogCursor returns a log cursor to the current tip of the unified system logs. 21 // The return cursor can later be passed to WriteLogs. 22 func GetUnifiedLogCursor(ctx context.Context) (string, error) { 23 cmd := exec.CommandContext(ctx, "croslog", "--lines=0", "--show-cursor", "--quiet", "--no-pager") 24 out, err := cmd.Output() 25 if err != nil { 26 return "", err 27 } 28 m := croslogCursorRegexp.FindSubmatch(out) 29 if m == nil { 30 return "", fmt.Errorf("failed to find %q in %q", croslogCursorRegexp, out) 31 } 32 return string(m[1]), nil 33 } 34 35 // UnifiedLogFormat is a format for syslog entries. 36 type UnifiedLogFormat int 37 38 const ( 39 // CompactLogFormat corresponds to human-readable single-line log entries. 40 CompactLogFormat UnifiedLogFormat = iota 41 // GzippedExportLogFormat corresponds to croslog's "--output=export" multiline format that preserves metadata. 42 // The data is additionally gzip-compressed. 43 GzippedExportLogFormat 44 ) 45 46 // ExportUnifiedLogs writes unified system log entries generated after cursor to w using fm. 47 // cursor should have been generated by an earlier call to GetUnifiedLogCursor. 48 func ExportUnifiedLogs(ctx context.Context, w io.Writer, cursor string, fm UnifiedLogFormat) error { 49 args := []string{"--after-cursor=" + cursor} 50 if fm == GzippedExportLogFormat { 51 args = append(args, "--output=export") 52 } 53 cmd := exec.CommandContext(ctx, "croslog", args...) 54 55 var ww io.WriteCloser // wraps w; may be nil 56 if fm == GzippedExportLogFormat { 57 ww = gzip.NewWriter(w) 58 cmd.Stdout = ww 59 } else { 60 cmd.Stdout = w 61 } 62 63 err := cmd.Run() 64 65 // If the writer was wrapped, close the wrapper to flush data. 66 if ww != nil { 67 if cerr := ww.Close(); cerr != nil && err == nil { 68 err = cerr 69 } 70 } 71 72 return err 73 }