1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 package klog
92
93 import (
94 "bufio"
95 "bytes"
96 "errors"
97 "flag"
98 "fmt"
99 "io"
100 stdLog "log"
101 "math"
102 "os"
103 "path/filepath"
104 "runtime"
105 "strconv"
106 "strings"
107 "sync"
108 "sync/atomic"
109 "time"
110
111 "k8s.io/klog/v2/internal/buffer"
112 "k8s.io/klog/v2/internal/clock"
113 "k8s.io/klog/v2/internal/dbg"
114 "k8s.io/klog/v2/internal/serialize"
115 "k8s.io/klog/v2/internal/severity"
116 )
117
118
119
120
121
122 type severityValue struct {
123 severity.Severity
124 }
125
126
127 func (s *severityValue) get() severity.Severity {
128 return severity.Severity(atomic.LoadInt32((*int32)(&s.Severity)))
129 }
130
131
132 func (s *severityValue) set(val severity.Severity) {
133 atomic.StoreInt32((*int32)(&s.Severity), int32(val))
134 }
135
136
137 func (s *severityValue) String() string {
138 return strconv.FormatInt(int64(s.Severity), 10)
139 }
140
141
142 func (s *severityValue) Get() interface{} {
143 return s.Severity
144 }
145
146
147 func (s *severityValue) Set(value string) error {
148 var threshold severity.Severity
149
150 if v, ok := severity.ByName(value); ok {
151 threshold = v
152 } else {
153 v, err := strconv.ParseInt(value, 10, 32)
154 if err != nil {
155 return err
156 }
157 threshold = severity.Severity(v)
158 }
159 logging.stderrThreshold.set(threshold)
160 return nil
161 }
162
163
164 type OutputStats struct {
165 lines int64
166 bytes int64
167 }
168
169
170 func (s *OutputStats) Lines() int64 {
171 return atomic.LoadInt64(&s.lines)
172 }
173
174
175 func (s *OutputStats) Bytes() int64 {
176 return atomic.LoadInt64(&s.bytes)
177 }
178
179
180
181 var Stats struct {
182 Info, Warning, Error OutputStats
183 }
184
185 var severityStats = [severity.NumSeverity]*OutputStats{
186 severity.InfoLog: &Stats.Info,
187 severity.WarningLog: &Stats.Warning,
188 severity.ErrorLog: &Stats.Error,
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203 type Level int32
204
205
206 func (l *Level) get() Level {
207 return Level(atomic.LoadInt32((*int32)(l)))
208 }
209
210
211 func (l *Level) set(val Level) {
212 atomic.StoreInt32((*int32)(l), int32(val))
213 }
214
215
216 func (l *Level) String() string {
217 return strconv.FormatInt(int64(*l), 10)
218 }
219
220
221 func (l *Level) Get() interface{} {
222 return *l
223 }
224
225
226 func (l *Level) Set(value string) error {
227 v, err := strconv.ParseInt(value, 10, 32)
228 if err != nil {
229 return err
230 }
231 logging.mu.Lock()
232 defer logging.mu.Unlock()
233 logging.setVState(Level(v), logging.vmodule.filter, false)
234 return nil
235 }
236
237
238 type moduleSpec struct {
239 filter []modulePat
240 }
241
242
243
244 type modulePat struct {
245 pattern string
246 literal bool
247 level Level
248 }
249
250
251
252 func (m *modulePat) match(file string) bool {
253 if m.literal {
254 return file == m.pattern
255 }
256 match, _ := filepath.Match(m.pattern, file)
257 return match
258 }
259
260 func (m *moduleSpec) String() string {
261
262 logging.mu.Lock()
263 defer logging.mu.Unlock()
264 return m.serialize()
265 }
266
267 func (m *moduleSpec) serialize() string {
268 var b bytes.Buffer
269 for i, f := range m.filter {
270 if i > 0 {
271 b.WriteRune(',')
272 }
273 fmt.Fprintf(&b, "%s=%d", f.pattern, f.level)
274 }
275 return b.String()
276 }
277
278
279
280 func (m *moduleSpec) Get() interface{} {
281 return nil
282 }
283
284 var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N")
285
286
287
288 func (m *moduleSpec) Set(value string) error {
289 filter, err := parseModuleSpec(value)
290 if err != nil {
291 return err
292 }
293 logging.mu.Lock()
294 defer logging.mu.Unlock()
295 logging.setVState(logging.verbosity, filter, true)
296 return nil
297 }
298
299 func parseModuleSpec(value string) ([]modulePat, error) {
300 var filter []modulePat
301 for _, pat := range strings.Split(value, ",") {
302 if len(pat) == 0 {
303
304 continue
305 }
306 patLev := strings.Split(pat, "=")
307 if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
308 return nil, errVmoduleSyntax
309 }
310 pattern := patLev[0]
311 v, err := strconv.ParseInt(patLev[1], 10, 32)
312 if err != nil {
313 return nil, errors.New("syntax error: expect comma-separated list of filename=N")
314 }
315 if v < 0 {
316 return nil, errors.New("negative value for vmodule level")
317 }
318 if v == 0 {
319 continue
320 }
321
322 filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)})
323 }
324 return filter, nil
325 }
326
327
328
329 func isLiteral(pattern string) bool {
330 return !strings.ContainsAny(pattern, `\*?[]`)
331 }
332
333
334 type traceLocation struct {
335 file string
336 line int
337 }
338
339
340
341 func (t *traceLocation) isSet() bool {
342 return t.line > 0
343 }
344
345
346
347
348 func (t *traceLocation) match(file string, line int) bool {
349 if t.line != line {
350 return false
351 }
352 if i := strings.LastIndex(file, "/"); i >= 0 {
353 file = file[i+1:]
354 }
355 return t.file == file
356 }
357
358 func (t *traceLocation) String() string {
359
360 logging.mu.Lock()
361 defer logging.mu.Unlock()
362 return fmt.Sprintf("%s:%d", t.file, t.line)
363 }
364
365
366
367 func (t *traceLocation) Get() interface{} {
368 return nil
369 }
370
371 var errTraceSyntax = errors.New("syntax error: expect file.go:234")
372
373
374
375
376 func (t *traceLocation) Set(value string) error {
377 if value == "" {
378
379 logging.mu.Lock()
380 defer logging.mu.Unlock()
381 t.line = 0
382 t.file = ""
383 return nil
384 }
385 fields := strings.Split(value, ":")
386 if len(fields) != 2 {
387 return errTraceSyntax
388 }
389 file, line := fields[0], fields[1]
390 if !strings.Contains(file, ".") {
391 return errTraceSyntax
392 }
393 v, err := strconv.Atoi(line)
394 if err != nil {
395 return errTraceSyntax
396 }
397 if v <= 0 {
398 return errors.New("negative or zero value for level")
399 }
400 logging.mu.Lock()
401 defer logging.mu.Unlock()
402 t.line = v
403 t.file = file
404 return nil
405 }
406
407 var logging loggingT
408 var commandLine flag.FlagSet
409
410
411 func init() {
412 commandLine.StringVar(&logging.logDir, "log_dir", "", "If non-empty, write log files in this directory (no effect when -logtostderr=true)")
413 commandLine.StringVar(&logging.logFile, "log_file", "", "If non-empty, use this log file (no effect when -logtostderr=true)")
414 commandLine.Uint64Var(&logging.logFileMaxSizeMB, "log_file_max_size", 1800,
415 "Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. "+
416 "If the value is 0, the maximum file size is unlimited.")
417 commandLine.BoolVar(&logging.toStderr, "logtostderr", true, "log to standard error instead of files")
418 commandLine.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files (no effect when -logtostderr=true)")
419 logging.setVState(0, nil, false)
420 commandLine.Var(&logging.verbosity, "v", "number for the log level verbosity")
421 commandLine.BoolVar(&logging.addDirHeader, "add_dir_header", false, "If true, adds the file directory to the header of the log messages")
422 commandLine.BoolVar(&logging.skipHeaders, "skip_headers", false, "If true, avoid header prefixes in the log messages")
423 commandLine.BoolVar(&logging.oneOutput, "one_output", false, "If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)")
424 commandLine.BoolVar(&logging.skipLogHeaders, "skip_log_headers", false, "If true, avoid headers when opening log files (no effect when -logtostderr=true)")
425 logging.stderrThreshold = severityValue{
426 Severity: severity.ErrorLog,
427 }
428 commandLine.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=true)")
429 commandLine.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
430 commandLine.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
431
432 logging.settings.contextualLoggingEnabled = true
433 logging.flushD = newFlushDaemon(logging.lockAndFlushAll, nil)
434 }
435
436
437
438
439
440
441 func InitFlags(flagset *flag.FlagSet) {
442 if flagset == nil {
443 flagset = flag.CommandLine
444 }
445
446 commandLine.VisitAll(func(f *flag.Flag) {
447 flagset.Var(f.Value, f.Name, f.Usage)
448 })
449 }
450
451
452 func Flush() {
453 logging.lockAndFlushAll()
454 }
455
456
457 type settings struct {
458
459
460 contextualLoggingEnabled bool
461
462
463
464 logger *logWriter
465
466
467
468 loggerOptions loggerOptions
469
470
471
472
473 toStderr bool
474 alsoToStderr bool
475
476
477 stderrThreshold severityValue
478
479
480
481
482 file [severity.NumSeverity]io.Writer
483
484
485 flushInterval time.Duration
486
487
488
489
490 filterLength int32
491
492 traceLocation traceLocation
493
494
495 vmodule moduleSpec
496 verbosity Level
497
498
499
500 logDir string
501
502
503
504 logFile string
505
506
507
508 logFileMaxSizeMB uint64
509
510
511 skipHeaders bool
512
513
514 skipLogHeaders bool
515
516
517 addDirHeader bool
518
519
520 oneOutput bool
521
522
523 filter LogFilter
524 }
525
526
527
528 func (s settings) deepCopy() settings {
529
530 filter := make([]modulePat, len(s.vmodule.filter))
531 copy(filter, s.vmodule.filter)
532 s.vmodule.filter = filter
533
534 if s.logger != nil {
535 logger := *s.logger
536 s.logger = &logger
537 }
538
539 return s
540 }
541
542
543 type loggingT struct {
544 settings
545
546
547
548 flushD *flushDaemon
549
550
551
552 mu sync.Mutex
553
554
555 pcs [1]uintptr
556
557
558 vmap map[uintptr]Level
559 }
560
561
562
563 func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) {
564
565 l.verbosity.set(0)
566
567 atomic.StoreInt32(&l.filterLength, 0)
568
569
570 if setFilter {
571 l.vmodule.filter = filter
572 l.vmap = make(map[uintptr]Level)
573 }
574
575
576
577 atomic.StoreInt32(&l.filterLength, int32(len(filter)))
578 l.verbosity.set(verbosity)
579 }
580
581 var timeNow = time.Now
582
583
584
585 func CaptureState() State {
586 logging.mu.Lock()
587 defer logging.mu.Unlock()
588 return &state{
589 settings: logging.settings.deepCopy(),
590 flushDRunning: logging.flushD.isRunning(),
591 maxSize: MaxSize,
592 }
593 }
594
595
596
597
598 type State interface {
599
600 Restore()
601 }
602
603 type state struct {
604 settings
605
606 flushDRunning bool
607 maxSize uint64
608 }
609
610 func (s *state) Restore() {
611
612 if s.flushDRunning && !logging.flushD.isRunning() {
613
614
615 interval := s.flushInterval
616 if interval == 0 {
617 interval = flushInterval
618 }
619 logging.flushD.run(interval)
620 } else if !s.flushDRunning && logging.flushD.isRunning() {
621 logging.flushD.stop()
622 }
623
624 logging.mu.Lock()
625 defer logging.mu.Unlock()
626
627 logging.settings = s.settings
628 logging.setVState(s.verbosity, s.vmodule.filter, true)
629 MaxSize = s.maxSize
630 }
631
632
652 func (l *loggingT) header(s severity.Severity, depth int) (*buffer.Buffer, string, int) {
653 _, file, line, ok := runtime.Caller(3 + depth)
654 if !ok {
655 file = "???"
656 line = 1
657 } else {
658 if slash := strings.LastIndex(file, "/"); slash >= 0 {
659 path := file
660 file = path[slash+1:]
661 if l.addDirHeader {
662 if dirsep := strings.LastIndex(path[:slash], "/"); dirsep >= 0 {
663 file = path[dirsep+1:]
664 }
665 }
666 }
667 }
668 return l.formatHeader(s, file, line, timeNow()), file, line
669 }
670
671
672 func (l *loggingT) formatHeader(s severity.Severity, file string, line int, now time.Time) *buffer.Buffer {
673 buf := buffer.GetBuffer()
674 if l.skipHeaders {
675 return buf
676 }
677 buf.FormatHeader(s, file, line, now)
678 return buf
679 }
680
681 func (l *loggingT) println(s severity.Severity, logger *logWriter, filter LogFilter, args ...interface{}) {
682 l.printlnDepth(s, logger, filter, 1, args...)
683 }
684
685 func (l *loggingT) printlnDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
686 if false {
687 _ = fmt.Sprintln(args...)
688 }
689
690 buf, file, line := l.header(s, depth)
691
692
693
694 if logger != nil && logger.writeKlogBuffer == nil {
695 buffer.PutBuffer(buf)
696 buf = buffer.GetBuffer()
697 }
698 if filter != nil {
699 args = filter.Filter(args)
700 }
701 fmt.Fprintln(buf, args...)
702 l.output(s, logger, buf, depth, file, line, false)
703 }
704
705 func (l *loggingT) print(s severity.Severity, logger *logWriter, filter LogFilter, args ...interface{}) {
706 l.printDepth(s, logger, filter, 1, args...)
707 }
708
709 func (l *loggingT) printDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
710 if false {
711 _ = fmt.Sprint(args...)
712 }
713
714 buf, file, line := l.header(s, depth)
715 l.printWithInfos(buf, file, line, s, logger, filter, depth+1, args...)
716 }
717
718 func (l *loggingT) printWithInfos(buf *buffer.Buffer, file string, line int, s severity.Severity, logger *logWriter, filter LogFilter, depth int, args ...interface{}) {
719
720
721
722 if logger != nil && logger.writeKlogBuffer == nil {
723 buffer.PutBuffer(buf)
724 buf = buffer.GetBuffer()
725 }
726 if filter != nil {
727 args = filter.Filter(args)
728 }
729 fmt.Fprint(buf, args...)
730 if buf.Len() == 0 || buf.Bytes()[buf.Len()-1] != '\n' {
731 buf.WriteByte('\n')
732 }
733 l.output(s, logger, buf, depth, file, line, false)
734 }
735
736 func (l *loggingT) printf(s severity.Severity, logger *logWriter, filter LogFilter, format string, args ...interface{}) {
737 l.printfDepth(s, logger, filter, 1, format, args...)
738 }
739
740 func (l *loggingT) printfDepth(s severity.Severity, logger *logWriter, filter LogFilter, depth int, format string, args ...interface{}) {
741 if false {
742 _ = fmt.Sprintf(format, args...)
743 }
744
745 buf, file, line := l.header(s, depth)
746
747
748
749 if logger != nil && logger.writeKlogBuffer == nil {
750 buffer.PutBuffer(buf)
751 buf = buffer.GetBuffer()
752 }
753 if filter != nil {
754 format, args = filter.FilterF(format, args)
755 }
756 fmt.Fprintf(buf, format, args...)
757 if buf.Bytes()[buf.Len()-1] != '\n' {
758 buf.WriteByte('\n')
759 }
760 l.output(s, logger, buf, depth, file, line, false)
761 }
762
763
764
765
766 func (l *loggingT) printWithFileLine(s severity.Severity, logger *logWriter, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) {
767 buf := l.formatHeader(s, file, line, timeNow())
768
769
770
771 if logger != nil && logger.writeKlogBuffer == nil {
772 buffer.PutBuffer(buf)
773 buf = buffer.GetBuffer()
774 }
775 if filter != nil {
776 args = filter.Filter(args)
777 }
778 fmt.Fprint(buf, args...)
779 if buf.Bytes()[buf.Len()-1] != '\n' {
780 buf.WriteByte('\n')
781 }
782 l.output(s, logger, buf, 2 , file, line, alsoToStderr)
783 }
784
785
786 func (l *loggingT) errorS(err error, logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
787 if filter != nil {
788 msg, keysAndValues = filter.FilterS(msg, keysAndValues)
789 }
790 if logger != nil {
791 logger.WithCallDepth(depth+2).Error(err, msg, keysAndValues...)
792 return
793 }
794 l.printS(err, severity.ErrorLog, depth+1, msg, keysAndValues...)
795 }
796
797
798 func (l *loggingT) infoS(logger *logWriter, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
799 if filter != nil {
800 msg, keysAndValues = filter.FilterS(msg, keysAndValues)
801 }
802 if logger != nil {
803 logger.WithCallDepth(depth+2).Info(msg, keysAndValues...)
804 return
805 }
806 l.printS(nil, severity.InfoLog, depth+1, msg, keysAndValues...)
807 }
808
809
810
811 func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string, keysAndValues ...interface{}) {
812
813 b := buffer.GetBuffer()
814
815
816
817 b.WriteString(strconv.Quote(msg))
818 if err != nil {
819 serialize.KVListFormat(&b.Buffer, "err", err)
820 }
821 serialize.KVListFormat(&b.Buffer, keysAndValues...)
822 l.printDepth(s, nil, nil, depth+1, &b.Buffer)
823
824 buffer.PutBuffer(b)
825 }
826
827
828 func SetOutput(w io.Writer) {
829 logging.mu.Lock()
830 defer logging.mu.Unlock()
831 for s := severity.FatalLog; s >= severity.InfoLog; s-- {
832 logging.file[s] = w
833 }
834 }
835
836
837 func SetOutputBySeverity(name string, w io.Writer) {
838 logging.mu.Lock()
839 defer logging.mu.Unlock()
840 sev, ok := severity.ByName(name)
841 if !ok {
842 panic(fmt.Sprintf("SetOutputBySeverity(%q): unrecognized severity name", name))
843 }
844 logging.file[sev] = w
845 }
846
847
848 func LogToStderr(stderr bool) {
849 logging.mu.Lock()
850 defer logging.mu.Unlock()
851
852 logging.toStderr = stderr
853 }
854
855
856 func (l *loggingT) output(s severity.Severity, logger *logWriter, buf *buffer.Buffer, depth int, file string, line int, alsoToStderr bool) {
857 var isLocked = true
858 l.mu.Lock()
859 defer func() {
860 if isLocked {
861
862 l.mu.Unlock()
863 }
864 }()
865
866 if l.traceLocation.isSet() {
867 if l.traceLocation.match(file, line) {
868 buf.Write(dbg.Stacks(false))
869 }
870 }
871 data := buf.Bytes()
872 if logger != nil {
873 if logger.writeKlogBuffer != nil {
874 logger.writeKlogBuffer(data)
875 } else {
876 if len(data) > 0 && data[len(data)-1] == '\n' {
877 data = data[:len(data)-1]
878 }
879
880
881 if s == severity.ErrorLog {
882 logger.WithCallDepth(depth+3).Error(nil, string(data))
883 } else {
884 logger.WithCallDepth(depth + 3).Info(string(data))
885 }
886 }
887 } else if l.toStderr {
888 os.Stderr.Write(data)
889 } else {
890 if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() {
891 os.Stderr.Write(data)
892 }
893
894 if logging.logFile != "" {
895
896
897 if l.file[severity.InfoLog] == nil {
898 if err := l.createFiles(severity.InfoLog); err != nil {
899 os.Stderr.Write(data)
900 l.exit(err)
901 }
902 }
903 _, _ = l.file[severity.InfoLog].Write(data)
904 } else {
905 if l.file[s] == nil {
906 if err := l.createFiles(s); err != nil {
907 os.Stderr.Write(data)
908 l.exit(err)
909 }
910 }
911
912 if l.oneOutput {
913 _, _ = l.file[s].Write(data)
914 } else {
915 switch s {
916 case severity.FatalLog:
917 _, _ = l.file[severity.FatalLog].Write(data)
918 fallthrough
919 case severity.ErrorLog:
920 _, _ = l.file[severity.ErrorLog].Write(data)
921 fallthrough
922 case severity.WarningLog:
923 _, _ = l.file[severity.WarningLog].Write(data)
924 fallthrough
925 case severity.InfoLog:
926 _, _ = l.file[severity.InfoLog].Write(data)
927 }
928 }
929 }
930 }
931 if s == severity.FatalLog {
932
933 if atomic.LoadUint32(&fatalNoStacks) > 0 {
934 l.mu.Unlock()
935 isLocked = false
936 timeoutFlush(ExitFlushTimeout)
937 OsExit(1)
938 }
939
940
941
942
943 if !l.toStderr {
944 os.Stderr.Write(dbg.Stacks(false))
945 }
946
947
948 trace := dbg.Stacks(true)
949 logExitFunc = func(error) {}
950 for log := severity.FatalLog; log >= severity.InfoLog; log-- {
951 if f := l.file[log]; f != nil {
952 _, _ = f.Write(trace)
953 }
954 }
955 l.mu.Unlock()
956 isLocked = false
957 timeoutFlush(ExitFlushTimeout)
958 OsExit(255)
959 }
960 buffer.PutBuffer(buf)
961
962 if stats := severityStats[s]; stats != nil {
963 atomic.AddInt64(&stats.lines, 1)
964 atomic.AddInt64(&stats.bytes, int64(len(data)))
965 }
966 }
967
968
969
970
971
972 var logExitFunc func(error)
973
974
975
976
977 func (l *loggingT) exit(err error) {
978 fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err)
979
980 if logExitFunc != nil {
981 logExitFunc(err)
982 return
983 }
984 needToSync := l.flushAll()
985 l.syncAll(needToSync)
986 OsExit(2)
987 }
988
989
990
991
992
993 type syncBuffer struct {
994 logger *loggingT
995 *bufio.Writer
996 file *os.File
997 sev severity.Severity
998 nbytes uint64
999 maxbytes uint64
1000 }
1001
1002
1003 func CalculateMaxSize() uint64 {
1004 if logging.logFile != "" {
1005 if logging.logFileMaxSizeMB == 0 {
1006
1007 return math.MaxUint64
1008 }
1009
1010 return logging.logFileMaxSizeMB * 1024 * 1024
1011 }
1012
1013 return MaxSize
1014 }
1015
1016 func (sb *syncBuffer) Write(p []byte) (n int, err error) {
1017 if sb.nbytes+uint64(len(p)) >= sb.maxbytes {
1018 if err := sb.rotateFile(time.Now(), false); err != nil {
1019 sb.logger.exit(err)
1020 }
1021 }
1022 n, err = sb.Writer.Write(p)
1023 sb.nbytes += uint64(n)
1024 if err != nil {
1025 sb.logger.exit(err)
1026 }
1027 return
1028 }
1029
1030
1031
1032
1033 func (sb *syncBuffer) rotateFile(now time.Time, startup bool) error {
1034 if sb.file != nil {
1035 sb.Flush()
1036 sb.file.Close()
1037 }
1038 var err error
1039 sb.file, _, err = create(severity.Name[sb.sev], now, startup)
1040 if err != nil {
1041 return err
1042 }
1043 if startup {
1044 fileInfo, err := sb.file.Stat()
1045 if err != nil {
1046 return fmt.Errorf("file stat could not get fileinfo: %v", err)
1047 }
1048
1049 sb.nbytes = uint64(fileInfo.Size())
1050 } else {
1051 sb.nbytes = 0
1052 }
1053 sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)
1054
1055 if sb.logger.skipLogHeaders {
1056 return nil
1057 }
1058
1059
1060 var buf bytes.Buffer
1061 fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05"))
1062 fmt.Fprintf(&buf, "Running on machine: %s\n", host)
1063 fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
1064 fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n")
1065 n, err := sb.file.Write(buf.Bytes())
1066 sb.nbytes += uint64(n)
1067 return err
1068 }
1069
1070
1071
1072
1073 const bufferSize = 256 * 1024
1074
1075
1076
1077 func (l *loggingT) createFiles(sev severity.Severity) error {
1078 interval := l.flushInterval
1079 if interval == 0 {
1080 interval = flushInterval
1081 }
1082 l.flushD.run(interval)
1083 now := time.Now()
1084
1085
1086 for s := sev; s >= severity.InfoLog && l.file[s] == nil; s-- {
1087 sb := &syncBuffer{
1088 logger: l,
1089 sev: s,
1090 maxbytes: CalculateMaxSize(),
1091 }
1092 if err := sb.rotateFile(now, true); err != nil {
1093 return err
1094 }
1095 l.file[s] = sb
1096 }
1097 return nil
1098 }
1099
1100 const flushInterval = 5 * time.Second
1101
1102
1103 type flushDaemon struct {
1104 mu sync.Mutex
1105 clock clock.Clock
1106 flush func()
1107 stopC chan struct{}
1108 stopDone chan struct{}
1109 }
1110
1111
1112
1113 func newFlushDaemon(flush func(), tickClock clock.Clock) *flushDaemon {
1114 if tickClock == nil {
1115 tickClock = clock.RealClock{}
1116 }
1117 return &flushDaemon{
1118 flush: flush,
1119 clock: tickClock,
1120 }
1121 }
1122
1123
1124
1125 func (f *flushDaemon) run(interval time.Duration) {
1126 f.mu.Lock()
1127 defer f.mu.Unlock()
1128
1129 if f.stopC != nil {
1130 return
1131 }
1132
1133 f.stopC = make(chan struct{}, 1)
1134 f.stopDone = make(chan struct{}, 1)
1135
1136 ticker := f.clock.NewTicker(interval)
1137 go func() {
1138 defer ticker.Stop()
1139 defer func() { f.stopDone <- struct{}{} }()
1140 for {
1141 select {
1142 case <-ticker.C():
1143 f.flush()
1144 case <-f.stopC:
1145 f.flush()
1146 return
1147 }
1148 }
1149 }()
1150 }
1151
1152
1153
1154 func (f *flushDaemon) stop() {
1155 f.mu.Lock()
1156 defer f.mu.Unlock()
1157
1158 if f.stopC == nil {
1159 return
1160 }
1161
1162 f.stopC <- struct{}{}
1163 <-f.stopDone
1164
1165 f.stopC = nil
1166 f.stopDone = nil
1167 }
1168
1169
1170 func (f *flushDaemon) isRunning() bool {
1171 f.mu.Lock()
1172 defer f.mu.Unlock()
1173 return f.stopC != nil
1174 }
1175
1176
1177
1178
1179 func StopFlushDaemon() {
1180 logging.flushD.stop()
1181 }
1182
1183
1184
1185 func StartFlushDaemon(interval time.Duration) {
1186 StopFlushDaemon()
1187 logging.flushD.run(interval)
1188 }
1189
1190
1191 func (l *loggingT) lockAndFlushAll() {
1192 l.mu.Lock()
1193 needToSync := l.flushAll()
1194 l.mu.Unlock()
1195
1196 l.syncAll(needToSync)
1197 }
1198
1199
1200
1201
1202
1203 func (l *loggingT) flushAll() fileArray {
1204 var needToSync fileArray
1205
1206
1207 for s := severity.FatalLog; s >= severity.InfoLog; s-- {
1208 file := l.file[s]
1209 if sb, ok := file.(*syncBuffer); ok && sb.file != nil {
1210 _ = sb.Flush()
1211 needToSync.files[needToSync.num] = sb.file
1212 needToSync.num++
1213 }
1214 }
1215 if logging.loggerOptions.flush != nil {
1216 logging.loggerOptions.flush()
1217 }
1218 return needToSync
1219 }
1220
1221 type fileArray struct {
1222 num int
1223 files [severity.NumSeverity]*os.File
1224 }
1225
1226
1227 func (l *loggingT) syncAll(needToSync fileArray) {
1228
1229 for i := 0; i < needToSync.num; i++ {
1230 _ = needToSync.files[i].Sync()
1231 }
1232 }
1233
1234
1235
1236
1237
1238
1239
1240
1241 func CopyStandardLogTo(name string) {
1242 sev, ok := severity.ByName(name)
1243 if !ok {
1244 panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name))
1245 }
1246
1247
1248 stdLog.SetFlags(stdLog.Lshortfile)
1249 stdLog.SetOutput(logBridge(sev))
1250 }
1251
1252
1253
1254
1255
1256
1257 func NewStandardLogger(name string) *stdLog.Logger {
1258 sev, ok := severity.ByName(name)
1259 if !ok {
1260 panic(fmt.Sprintf("klog.NewStandardLogger(%q): unknown severity", name))
1261 }
1262 return stdLog.New(logBridge(sev), "", stdLog.Lshortfile)
1263 }
1264
1265
1266
1267 type logBridge severity.Severity
1268
1269
1270
1271 func (lb logBridge) Write(b []byte) (n int, err error) {
1272 var (
1273 file = "???"
1274 line = 1
1275 text string
1276 )
1277
1278 if parts := bytes.SplitN(b, []byte{':'}, 3); len(parts) != 3 || len(parts[0]) < 1 || len(parts[2]) < 1 {
1279 text = fmt.Sprintf("bad log format: %s", b)
1280 } else {
1281 file = string(parts[0])
1282 text = string(parts[2][1:])
1283 line, err = strconv.Atoi(string(parts[1]))
1284 if err != nil {
1285 text = fmt.Sprintf("bad line number: %s", b)
1286 line = 1
1287 }
1288 }
1289
1290
1291 logging.printWithFileLine(severity.Severity(lb), logging.logger, logging.filter, file, line, true, text)
1292 return len(b), nil
1293 }
1294
1295
1296
1297
1298
1299
1300
1301 func (l *loggingT) setV(pc uintptr) Level {
1302 fn := runtime.FuncForPC(pc)
1303 file, _ := fn.FileLine(pc)
1304
1305 file = strings.TrimSuffix(file, ".go")
1306 if slash := strings.LastIndex(file, "/"); slash >= 0 {
1307 file = file[slash+1:]
1308 }
1309 for _, filter := range l.vmodule.filter {
1310 if filter.match(file) {
1311 l.vmap[pc] = filter.level
1312 return filter.level
1313 }
1314 }
1315 l.vmap[pc] = 0
1316 return 0
1317 }
1318
1319
1320
1321 type Verbose struct {
1322 enabled bool
1323 logger *logWriter
1324 }
1325
1326 func newVerbose(level Level, b bool) Verbose {
1327 if logging.logger == nil {
1328 return Verbose{b, nil}
1329 }
1330 v := logging.logger.V(int(level))
1331 return Verbose{b, &logWriter{Logger: v, writeKlogBuffer: logging.loggerOptions.writeKlogBuffer}}
1332 }
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353 func V(level Level) Verbose {
1354 return VDepth(1, level)
1355 }
1356
1357
1358
1359
1360 func VDepth(depth int, level Level) Verbose {
1361
1362
1363
1364
1365 if logging.verbosity.get() >= level {
1366 return newVerbose(level, true)
1367 }
1368
1369
1370
1371 if atomic.LoadInt32(&logging.filterLength) > 0 {
1372
1373
1374
1375 logging.mu.Lock()
1376 defer logging.mu.Unlock()
1377 if runtime.Callers(2+depth, logging.pcs[:]) == 0 {
1378 return newVerbose(level, false)
1379 }
1380
1381
1382
1383
1384 pc := logging.pcs[0] - 1
1385 v, ok := logging.vmap[pc]
1386 if !ok {
1387 v = logging.setV(pc)
1388 }
1389 return newVerbose(level, v >= level)
1390 }
1391 return newVerbose(level, false)
1392 }
1393
1394
1395
1396
1397 func (v Verbose) Enabled() bool {
1398 return v.enabled
1399 }
1400
1401
1402
1403 func (v Verbose) Info(args ...interface{}) {
1404 if v.enabled {
1405 logging.print(severity.InfoLog, v.logger, logging.filter, args...)
1406 }
1407 }
1408
1409
1410
1411 func (v Verbose) InfoDepth(depth int, args ...interface{}) {
1412 if v.enabled {
1413 logging.printDepth(severity.InfoLog, v.logger, logging.filter, depth, args...)
1414 }
1415 }
1416
1417
1418
1419 func (v Verbose) Infoln(args ...interface{}) {
1420 if v.enabled {
1421 logging.println(severity.InfoLog, v.logger, logging.filter, args...)
1422 }
1423 }
1424
1425
1426
1427 func (v Verbose) InfolnDepth(depth int, args ...interface{}) {
1428 if v.enabled {
1429 logging.printlnDepth(severity.InfoLog, v.logger, logging.filter, depth, args...)
1430 }
1431 }
1432
1433
1434
1435 func (v Verbose) Infof(format string, args ...interface{}) {
1436 if v.enabled {
1437 logging.printf(severity.InfoLog, v.logger, logging.filter, format, args...)
1438 }
1439 }
1440
1441
1442
1443 func (v Verbose) InfofDepth(depth int, format string, args ...interface{}) {
1444 if v.enabled {
1445 logging.printfDepth(severity.InfoLog, v.logger, logging.filter, depth, format, args...)
1446 }
1447 }
1448
1449
1450
1451 func (v Verbose) InfoS(msg string, keysAndValues ...interface{}) {
1452 if v.enabled {
1453 logging.infoS(v.logger, logging.filter, 0, msg, keysAndValues...)
1454 }
1455 }
1456
1457
1458
1459 func InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
1460 logging.infoS(logging.logger, logging.filter, depth, msg, keysAndValues...)
1461 }
1462
1463
1464
1465 func (v Verbose) InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
1466 if v.enabled {
1467 logging.infoS(v.logger, logging.filter, depth, msg, keysAndValues...)
1468 }
1469 }
1470
1471
1472 func (v Verbose) Error(err error, msg string, args ...interface{}) {
1473 if v.enabled {
1474 logging.errorS(err, v.logger, logging.filter, 0, msg, args...)
1475 }
1476 }
1477
1478
1479
1480 func (v Verbose) ErrorS(err error, msg string, keysAndValues ...interface{}) {
1481 if v.enabled {
1482 logging.errorS(err, v.logger, logging.filter, 0, msg, keysAndValues...)
1483 }
1484 }
1485
1486
1487
1488 func Info(args ...interface{}) {
1489 logging.print(severity.InfoLog, logging.logger, logging.filter, args...)
1490 }
1491
1492
1493
1494 func InfoDepth(depth int, args ...interface{}) {
1495 logging.printDepth(severity.InfoLog, logging.logger, logging.filter, depth, args...)
1496 }
1497
1498
1499
1500 func Infoln(args ...interface{}) {
1501 logging.println(severity.InfoLog, logging.logger, logging.filter, args...)
1502 }
1503
1504
1505
1506 func InfolnDepth(depth int, args ...interface{}) {
1507 logging.printlnDepth(severity.InfoLog, logging.logger, logging.filter, depth, args...)
1508 }
1509
1510
1511
1512 func Infof(format string, args ...interface{}) {
1513 logging.printf(severity.InfoLog, logging.logger, logging.filter, format, args...)
1514 }
1515
1516
1517
1518 func InfofDepth(depth int, format string, args ...interface{}) {
1519 logging.printfDepth(severity.InfoLog, logging.logger, logging.filter, depth, format, args...)
1520 }
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530 func InfoS(msg string, keysAndValues ...interface{}) {
1531 logging.infoS(logging.logger, logging.filter, 0, msg, keysAndValues...)
1532 }
1533
1534
1535
1536 func Warning(args ...interface{}) {
1537 logging.print(severity.WarningLog, logging.logger, logging.filter, args...)
1538 }
1539
1540
1541
1542 func WarningDepth(depth int, args ...interface{}) {
1543 logging.printDepth(severity.WarningLog, logging.logger, logging.filter, depth, args...)
1544 }
1545
1546
1547
1548 func Warningln(args ...interface{}) {
1549 logging.println(severity.WarningLog, logging.logger, logging.filter, args...)
1550 }
1551
1552
1553
1554 func WarninglnDepth(depth int, args ...interface{}) {
1555 logging.printlnDepth(severity.WarningLog, logging.logger, logging.filter, depth, args...)
1556 }
1557
1558
1559
1560 func Warningf(format string, args ...interface{}) {
1561 logging.printf(severity.WarningLog, logging.logger, logging.filter, format, args...)
1562 }
1563
1564
1565
1566 func WarningfDepth(depth int, format string, args ...interface{}) {
1567 logging.printfDepth(severity.WarningLog, logging.logger, logging.filter, depth, format, args...)
1568 }
1569
1570
1571
1572 func Error(args ...interface{}) {
1573 logging.print(severity.ErrorLog, logging.logger, logging.filter, args...)
1574 }
1575
1576
1577
1578 func ErrorDepth(depth int, args ...interface{}) {
1579 logging.printDepth(severity.ErrorLog, logging.logger, logging.filter, depth, args...)
1580 }
1581
1582
1583
1584 func Errorln(args ...interface{}) {
1585 logging.println(severity.ErrorLog, logging.logger, logging.filter, args...)
1586 }
1587
1588
1589
1590 func ErrorlnDepth(depth int, args ...interface{}) {
1591 logging.printlnDepth(severity.ErrorLog, logging.logger, logging.filter, depth, args...)
1592 }
1593
1594
1595
1596 func Errorf(format string, args ...interface{}) {
1597 logging.printf(severity.ErrorLog, logging.logger, logging.filter, format, args...)
1598 }
1599
1600
1601
1602 func ErrorfDepth(depth int, format string, args ...interface{}) {
1603 logging.printfDepth(severity.ErrorLog, logging.logger, logging.filter, depth, format, args...)
1604 }
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615 func ErrorS(err error, msg string, keysAndValues ...interface{}) {
1616 logging.errorS(err, logging.logger, logging.filter, 0, msg, keysAndValues...)
1617 }
1618
1619
1620
1621 func ErrorSDepth(depth int, err error, msg string, keysAndValues ...interface{}) {
1622 logging.errorS(err, logging.logger, logging.filter, depth, msg, keysAndValues...)
1623 }
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639 func Fatal(args ...interface{}) {
1640 logging.print(severity.FatalLog, logging.logger, logging.filter, args...)
1641 }
1642
1643
1644
1645 func FatalDepth(depth int, args ...interface{}) {
1646 logging.printDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
1647 }
1648
1649
1650
1651
1652 func Fatalln(args ...interface{}) {
1653 logging.println(severity.FatalLog, logging.logger, logging.filter, args...)
1654 }
1655
1656
1657
1658 func FatallnDepth(depth int, args ...interface{}) {
1659 logging.printlnDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
1660 }
1661
1662
1663
1664
1665 func Fatalf(format string, args ...interface{}) {
1666 logging.printf(severity.FatalLog, logging.logger, logging.filter, format, args...)
1667 }
1668
1669
1670
1671 func FatalfDepth(depth int, format string, args ...interface{}) {
1672 logging.printfDepth(severity.FatalLog, logging.logger, logging.filter, depth, format, args...)
1673 }
1674
1675
1676
1677 var fatalNoStacks uint32
1678
1679
1680
1681 func Exit(args ...interface{}) {
1682 atomic.StoreUint32(&fatalNoStacks, 1)
1683 logging.print(severity.FatalLog, logging.logger, logging.filter, args...)
1684 }
1685
1686
1687
1688 func ExitDepth(depth int, args ...interface{}) {
1689 atomic.StoreUint32(&fatalNoStacks, 1)
1690 logging.printDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
1691 }
1692
1693
1694 func Exitln(args ...interface{}) {
1695 atomic.StoreUint32(&fatalNoStacks, 1)
1696 logging.println(severity.FatalLog, logging.logger, logging.filter, args...)
1697 }
1698
1699
1700
1701 func ExitlnDepth(depth int, args ...interface{}) {
1702 atomic.StoreUint32(&fatalNoStacks, 1)
1703 logging.printlnDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
1704 }
1705
1706
1707
1708 func Exitf(format string, args ...interface{}) {
1709 atomic.StoreUint32(&fatalNoStacks, 1)
1710 logging.printf(severity.FatalLog, logging.logger, logging.filter, format, args...)
1711 }
1712
1713
1714
1715 func ExitfDepth(depth int, format string, args ...interface{}) {
1716 atomic.StoreUint32(&fatalNoStacks, 1)
1717 logging.printfDepth(severity.FatalLog, logging.logger, logging.filter, depth, format, args...)
1718 }
1719
1720
1721
1722 type LogFilter interface {
1723 Filter(args []interface{}) []interface{}
1724 FilterF(format string, args []interface{}) (string, []interface{})
1725 FilterS(msg string, keysAndValues []interface{}) (string, []interface{})
1726 }
1727
1728
1729
1730
1731
1732 func SetLogFilter(filter LogFilter) {
1733 logging.filter = filter
1734 }
1735
View as plain text