@@ -22,14 +22,14 @@ func init() {
2222var numReg = regexp .MustCompile (`\d+` )
2323
2424type CheckLogFile struct {
25- snc * Agent
26- FilePath []string
27- Paths string
28- LineDelimiter string
29- TimestampPattern string
30- ColumnDelimiter string
31- LabelPattern []string
32- Offset string // Changed to string to detect if user provided it
25+ snc * Agent
26+ FilePathPatterns []string
27+ FilePathPatternsCS string
28+ LineDelimiter string
29+ TimestampPattern string
30+ ColumnDelimiter string
31+ LabelPattern []string
32+ Offset string // Changed to string to detect if user provided it
3333}
3434
3535type LogLine struct {
@@ -69,8 +69,8 @@ func (c *CheckLogFile) Build() *CheckData {
6969 emptySyntax : "%(status) - No files found" ,
7070 emptyState : CheckExitUnknown ,
7171 args : map [string ]CheckArgument {
72- "file" : {value : & c .FilePath , description : "The file that should be checked" },
73- "files" : {value : & c .Paths , description : "Comma separated list of files" },
72+ "file" : {value : & c .FilePathPatterns , description : "The file that should be checked" },
73+ "files" : {value : & c .FilePathPatternsCS , description : "Comma separated list of files" },
7474 "offset" : {value : & c .Offset , description : "Starting position (in bytes) for scanning the file (0 for beginning). This overrides any saved offset" },
7575 "line-split" : {value : & c .LineDelimiter , description : "Character string used to split a file into several lines (default \\ n)" },
7676 "column-split" : {value : & c .ColumnDelimiter , description : "Tab split default: \\ t" },
@@ -104,8 +104,8 @@ func (c *CheckLogFile) Check(_ context.Context, snc *Agent, check *CheckData, _
104104 return nil , fmt .Errorf ("module CheckLogFile is not enabled in /modules section" )
105105 }
106106
107- c .FilePath = append (c .FilePath , strings .Split (c .Paths , "," )... )
108- if len (c .FilePath ) == 0 {
107+ c .FilePathPatterns = append (c .FilePathPatterns , strings .Split (c .FilePathPatternsCS , "," )... )
108+ if len (c .FilePathPatterns ) == 0 {
109109 return nil , fmt .Errorf ("no file defined" )
110110 }
111111
@@ -122,55 +122,112 @@ func (c *CheckLogFile) Check(_ context.Context, snc *Agent, check *CheckData, _
122122 }
123123 }
124124
125+ // patterns are for the file names/paths, not file contents!
125126 allowedPattern := c .getAllowedPattern ()
126127
127- totalLineCount := 0
128- for _ , fileName := range c .FilePath {
128+ totalLineIndexedCount := 0
129+ checkedFilesWithMatchedEntries := make (map [string ]int , 0 )
130+
131+ for _ , fileName := range c .FilePathPatterns {
129132 if fileName == "" {
130133 continue
131134 }
132- count := 0
135+
136+ lineIndexedInThisFilePattern := 0
133137 files , err := filepath .Glob (fileName )
134138 if err != nil {
135139 return nil , fmt .Errorf ("could not get files for pattern %s, error was: %s" , fileName , err .Error ())
136140 }
141+
137142 for _ , fileName := range files {
138143 if ! c .matchPattern (fileName , allowedPattern ) {
144+ log .Tracef ("check_logfile rejecting file: %s as it does not any match patterns: %v " , fileName , allowedPattern )
145+
139146 return nil , fmt .Errorf ("file %s does not match any allowed pattern" , fileName )
140147 }
141- tmpCount , err := c .addFile (fileName , check , patterns )
148+
149+ log .Debugf ("check_logfile adding file: %s" , fileName )
150+ entries , lineIndex , err := c .addFile (fileName , check , patterns )
142151 if err != nil {
143152 return nil , fmt .Errorf ("error for file %s, error was: %s" , fileName , err .Error ())
144153 }
145- count += tmpCount
154+ log .Debugf ("check_logfile file: %s | returned entries: %v | lines indexed: %d" , fileName , entries , lineIndex )
155+
156+ lineIndexedInThisFilePattern += lineIndex
157+ check .listData = append (check .listData , entries ... )
158+ checkedFilesWithMatchedEntries [fileName ] = len (entries )
146159 }
147- totalLineCount += count
160+
161+ totalLineIndexedCount += lineIndexedInThisFilePattern
148162 }
163+
149164 check .details = map [string ]string {
150- "total" : fmt .Sprintf ("%d" , totalLineCount ),
165+ "total" : fmt .Sprintf ("%d" , totalLineIndexedCount ),
166+ "file_counts" : c .buildFileCountsDetailString (checkedFilesWithMatchedEntries ),
167+ }
168+
169+ if len (check .listData ) == 0 {
170+ check .emptySyntax = fmt .Sprintf ("%%(status) - No matching lines found in files (%s)" , check .details ["file_counts" ])
151171 }
152172
153173 return check .Finalize ()
154174}
155175
156- func (c * CheckLogFile ) addFile (fileName string , check * CheckData , labels map [string ]* regexp.Regexp ) (int , error ) {
176+ func (c * CheckLogFile ) buildFileCountsDetailString (checkedFilesWithMatchedEntries map [string ]int ) (fileCountDetails string ) {
177+ type kv struct {
178+ file string
179+ count int
180+ }
181+ sorted := make ([]kv , 0 , len (checkedFilesWithMatchedEntries ))
182+ for file , count := range checkedFilesWithMatchedEntries {
183+ sorted = append (sorted , kv {file , count })
184+ }
185+
186+ slices .SortFunc (sorted , func (a , b kv ) int {
187+ if a .file < b .file {
188+ return - 1
189+ }
190+ if a .file > b .file {
191+ return 1
192+ }
193+ if a .count < b .count {
194+ return - 1
195+ }
196+ if a .count > b .count {
197+ return 1
198+ }
199+
200+ return 0
201+ })
202+
203+ detailParts := make ([]string , 0 , len (sorted ))
204+ for _ , item := range sorted {
205+ detailParts = append (detailParts , fmt .Sprintf ("%s: %d" , item .file , item .count ))
206+ }
207+
208+ fileCountDetails = strings .Join (detailParts , ", " )
209+
210+ return fileCountDetails
211+ }
212+
213+ func (c * CheckLogFile ) addFile (fileName string , check * CheckData , labels map [string ]* regexp.Regexp ) (entries []map [string ]string , lineIndex int , err error ) {
157214 file , err := os .Open (fileName )
158215 if err != nil {
159- return 0 , fmt .Errorf ("could not open file: %s error was: %s" , fileName , err .Error ())
216+ return entries , 0 , fmt .Errorf ("could not open file: %s error was: %s" , fileName , err .Error ())
160217 }
161218 defer file .Close ()
162219
163220 info , err := file .Stat ()
164221 if err != nil {
165- return 0 , fmt .Errorf ("could not stat file %s: %s" , fileName , err .Error ())
222+ return entries , 0 , fmt .Errorf ("could not stat file %s: %s" , fileName , err .Error ())
166223 }
167224
168225 currentInode := getInode (fileName )
169226 currentSize := info .Size ()
170227
171228 startOffset , err := c .getStartOffset (fileName , currentSize , currentInode )
172229 if err != nil {
173- return 0 , err
230+ return entries , 0 , err
174231 }
175232
176233 saveState := true
@@ -188,25 +245,23 @@ func (c *CheckLogFile) addFile(fileName string, check *CheckData, labels map[str
188245 // seek to start offset
189246 if startOffset > 0 {
190247 if startOffset > currentSize {
191- return 0 , nil
248+ return entries , 0 , nil
192249 }
193250 _ , err = file .Seek (startOffset , 0 )
194251 if err != nil {
195252 saveState = false
196253
197- return 0 , fmt .Errorf ("failed to seek to offset %d in %s: %w" , startOffset , fileName , err )
254+ return entries , 0 , fmt .Errorf ("failed to seek to offset %d in %s: %w" , startOffset , fileName , err )
198255 }
199256 }
200257
201258 scanner := bufio .NewScanner (file )
202259 scanner .Split (c .getCustomSplitFunction ())
203- okReset := len (check .okThreshold ) > 0
260+ okThresholdNotEmpty := len (check .okThreshold ) > 0
204261 lineStorage := make ([]map [string ]string , 0 )
205262
206263 columnNumbers := c .getRequiredColumnNumbers (check )
207264
208- // filter each line
209- var lineIndex int
210265 for lineIndex = 0 ; scanner .Scan (); lineIndex ++ {
211266 line := scanner .Text ()
212267 entry := map [string ]string {
@@ -230,9 +285,16 @@ func (c *CheckLogFile) addFile(fileName string, check *CheckData, labels map[str
230285 }
231286 }
232287
288+ if ! check .MatchMapCondition (check .filter , entry , false ) {
289+ log .Tracef ("file: %s , line : %s, did not match the filter set in the check, not ading to check.listData" , fileName , line )
290+
291+ continue
292+ }
293+
233294 lineStorage = append (lineStorage , entry )
234- // Do not check for OK with empty condition list, it would match all
235- if okReset && check .MatchMapCondition (check .okThreshold , entry , true ) {
295+
296+ // Do not check for OK condition if the OK condition list is empty, it would match everything
297+ if okThresholdNotEmpty && check .MatchMapCondition (check .okThreshold , entry , true ) {
236298 // add and empty entry with the current line count to the list data to keep track of line count
237299 entry := map [string ]string {
238300 "_count" : fmt .Sprintf ("%d" , len (lineStorage )),
@@ -241,9 +303,8 @@ func (c *CheckLogFile) addFile(fileName string, check *CheckData, labels map[str
241303 lineStorage = make ([]map [string ]string , 0 )
242304 }
243305 }
244- check .listData = append (check .listData , lineStorage ... )
245306
246- return lineIndex , nil
307+ return lineStorage , lineIndex , nil
247308}
248309
249310func (c * CheckLogFile ) getStartOffset (fileName string , currentSize int64 , currentInode uint64 ) (int64 , error ) {
0 commit comments