MCPcopy Create free account
hub / github.com/containerd/nerdctl / viewLogsJSONFileDirect

Function viewLogsJSONFileDirect

pkg/logging/json_logger.go:166–278  ·  view source on GitHub ↗

Loads JSON log entries directly from the provided JSON log file. If `LogViewOptions.Follow` is provided, it will refresh and re-read the file until it receives something through the stopChannel.

(lvopts LogViewOptions, jsonLogFilePath string, stdout, stderr io.Writer, stopChannel chan os.Signal)

Source from the content-addressed store, hash-verified

164// If `LogViewOptions.Follow` is provided, it will refresh and re-read the file until
165// it receives something through the stopChannel.
166func viewLogsJSONFileDirect(lvopts LogViewOptions, jsonLogFilePath string, stdout, stderr io.Writer, stopChannel chan os.Signal) error {
167 fin, err := os.OpenFile(jsonLogFilePath, os.O_RDONLY, 0400)
168 if err != nil {
169 return err
170 }
171 defer func() { fin.Close() }()
172
173 // Search start point based on tail line.
174 start, err := tail.FindTailLineStartIndex(fin, lvopts.Tail)
175 if err != nil {
176 return fmt.Errorf("failed to tail %d lines of JSON logfile %q: %w", lvopts.Tail, jsonLogFilePath, err)
177 }
178
179 if _, err := fin.Seek(start, io.SeekStart); err != nil {
180 return fmt.Errorf("failed to seek in log file %q from %d position: %w", jsonLogFilePath, start, err)
181 }
182
183 limitedMode := (lvopts.Tail > 0) && (!lvopts.Follow)
184 limitedNum := lvopts.Tail
185 var stop bool
186 var watcher *fsnotify.Watcher
187 baseName := filepath.Base(jsonLogFilePath)
188 dir := filepath.Dir(jsonLogFilePath)
189 retryTimes := 2
190 backBytes := 0
191
192 for {
193 select {
194 case <-stopChannel:
195 log.L.Debug("received stop signal while re-reading JSON logfile, draining remaining logs and returning")
196 // The stop signal is only sent after WaitForLogger has confirmed that the
197 // logger finished writing (see pkg/cmd/container.Logs). However, the
198 // watcher-driven read loop may not have consumed the final entries yet:
199 // they may have been flushed to the file while we were blocked in
200 // startTail, and the stop signal wins the next select iteration before
201 // they are read. Do a final read so that we don't drop log content that
202 // was written right before the container exited.
203 // https://github.com/containerd/nerdctl/issues/5006
204 if _, err := jsonfile.Decode(stdout, stderr, fin, lvopts.Timestamps, lvopts.Since, lvopts.Until); err != nil {
205 log.L.WithError(err).Debugf("error draining remaining logs from JSON logfile %q", jsonLogFilePath)
206 }
207 return nil
208 default:
209 if stop || (limitedMode && limitedNum == 0) {
210 log.L.Debugf("finished parsing log JSON filefile, path: %s", jsonLogFilePath)
211 return nil
212 }
213
214 if line, err := jsonfile.Decode(stdout, stderr, fin, lvopts.Timestamps, lvopts.Since, lvopts.Until); err != nil {
215 if len(line) > 0 {
216 time.Sleep(5 * time.Millisecond)
217 if retryTimes == 0 {
218 log.L.Infof("finished parsing log JSON filefile, path: %s, line: %s", jsonLogFilePath, string(line))
219 return fmt.Errorf("error occurred while doing read of JSON logfile %q: %w, retryTimes: %d", jsonLogFilePath, err, retryTimes)
220 }
221 retryTimes--
222 backBytes = len(line)
223 } else {

Callers 4

viewLogsJSONFileFunction · 0.85
TestReadRotatedJSONLogFunction · 0.85
TestReadJSONLogsFunction · 0.85

Calls 9

FindTailLineStartIndexFunction · 0.92
DecodeFunction · 0.92
NewLogFileWatcherFunction · 0.85
startTailFunction · 0.85
SeekMethod · 0.80
openFileShareDeleteFunction · 0.70
DirMethod · 0.65
BackgroundMethod · 0.65
CloseMethod · 0.45

Tested by 3

TestReadRotatedJSONLogFunction · 0.68
TestReadJSONLogsFunction · 0.68

Used in the wild real call sites across dependent graphs

searching dependent graphs…