11package capture
22
33import (
4+ "errors"
45 "fmt"
56 "io"
67 "os"
78 "path/filepath"
89 "strings"
910
1011 "yc-agent/internal/config"
12+ "yc-agent/internal/logger"
1113
1214 "github.com/mattn/go-zglob"
1315)
@@ -28,30 +30,29 @@ type AppLog struct {
2830
2931// Run executes the log capture process for all configured paths.
3032// It processes each path as a glob pattern, capturing logs from all matching files.
33+ // Supports files, directories, and glob patterns.
3134// Returns a summary Result of all operations and any errors encountered.
3235func (al * AppLog ) Run () (Result , error ) {
36+ pathStrings := make ([]string , len (al .Paths ))
37+ for i , path := range al .Paths {
38+ pathStrings [i ] = string (path )
39+ }
40+
41+ // Expand all paths (files, directories, globs) to individual files
42+ expandedPaths , expansionErr := expandPaths (pathStrings )
43+
3344 var results []Result
3445 var errs []error
3546
36- // Process each path as a glob pattern to handle wildcard matching
37- for _ , path := range al .Paths {
38- matches , err := zglob .Glob (string (path ))
39- if err != nil {
40- // Don't fail completely if one pattern is invalid - record error and continue
41- results = append (results , Result {
42- Msg : fmt .Sprintf ("invalid glob pattern: %s" , path ),
43- Ok : false ,
44- })
45- errs = append (errs , err )
46- continue
47- }
47+ if expansionErr != nil {
48+ logger .Warn ().Err (expansionErr ).Msg ("AppLog: path expansion error" )
49+ }
4850
49- // Process each file that matches the glob pattern
50- for _ , match := range matches {
51- r , err := al .CaptureSingleAppLog (match )
52- results = append (results , r )
53- errs = append (errs , err )
54- }
51+ // Process each expanded file path
52+ for _ , filePath := range expandedPaths {
53+ r , err := al .CaptureSingleAppLog (filePath )
54+ results = append (results , r )
55+ errs = append (errs , err )
5556 }
5657
5758 return summarizeResults (results , errs )
@@ -198,3 +199,81 @@ func summarizeResults(results []Result, errs []error) (Result, error) {
198199 Ok : hasSuccess ,
199200 }, nil
200201}
202+
203+ // expandPaths takes a slice of paths and expands directories to individual files
204+ // while preserving existing file and glob pattern functionality
205+ func expandPaths (paths []string ) ([]string , error ) {
206+ var expandedPaths []string
207+ var errors []error
208+
209+ for _ , path := range paths {
210+ matches , err := zglob .Glob (path )
211+ if err != nil {
212+ errors = append (errors , fmt .Errorf ("invalid glob pattern %s: %w" , path , err ))
213+ continue
214+ }
215+
216+ // For each glob match, check if it's a directory
217+ for _ , match := range matches {
218+ fileInfo , err := os .Stat (match )
219+ if err != nil {
220+ errors = append (errors , fmt .Errorf ("cannot access %s: %w" , match , err ))
221+ continue
222+ }
223+
224+ if fileInfo .IsDir () {
225+ dirFiles , err := expandDirectory (match )
226+ if err != nil {
227+ errors = append (errors , err )
228+ continue
229+ }
230+ expandedPaths = append (expandedPaths , dirFiles ... )
231+ } else {
232+ expandedPaths = append (expandedPaths , match )
233+ }
234+ }
235+ }
236+
237+ return expandedPaths , combineErrors (errors )
238+ }
239+
240+ // expandDirectory reads a directory and returns all regular files within it
241+ func expandDirectory (dirPath string ) ([]string , error ) {
242+ var files []string
243+
244+ entries , err := os .ReadDir (dirPath )
245+ if err != nil {
246+ return nil , fmt .Errorf ("cannot read directory %s: %w" , dirPath , err )
247+ }
248+
249+ for _ , entry := range entries {
250+ if entry .IsDir () {
251+ continue
252+ }
253+
254+ fullPath := filepath .Join (dirPath , entry .Name ())
255+ files = append (files , fullPath )
256+ }
257+
258+ return files , nil
259+ }
260+
261+ // combineErrors combines multiple errors into a single error
262+ func combineErrors (errs []error ) error {
263+ if len (errs ) == 0 {
264+ return nil
265+ }
266+
267+ var errorMessages []string
268+ for _ , err := range errs {
269+ if err != nil {
270+ errorMessages = append (errorMessages , err .Error ())
271+ }
272+ }
273+
274+ if len (errorMessages ) == 0 {
275+ return nil
276+ }
277+
278+ return errors .New (strings .Join (errorMessages , "; " ))
279+ }
0 commit comments