Пример #1
0
// rotateFile closes the syncBuffer's file and starts a new one.
func (sb *syncBuffer) rotateFile(now time.Time) error {
	if sb.file != nil {
		if err := sb.Flush(); err != nil {
			return err
		}
		if err := sb.file.Close(); err != nil {
			return err
		}
	}
	var err error
	sb.file, _, err = create(sb.sev, now)
	sb.nbytes = 0
	if err != nil {
		return err
	}

	sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)

	f, l, _ := caller.Lookup(1)
	for _, msg := range []string{
		fmt.Sprintf("[config] file created at: %s\n", now.Format("2006/01/02 15:04:05")),
		fmt.Sprintf("[config] running on machine: %s\n", host),
		fmt.Sprintf("[config] binary: %s\n", build.GetInfo().Short()),
		fmt.Sprintf("[config] arguments: %s\n", os.Args),
		fmt.Sprintf("line format: [IWEF]yymmdd hh:mm:ss.uuuuuu goid file:line msg\n"),
	} {
		buf := formatLogEntry(Entry{
			Severity:  sb.sev,
			Time:      now.UnixNano(),
			Goroutine: goid.Get(),
			File:      f,
			Line:      int64(l),
			Message:   msg,
		}, nil, nil)
		var n int
		n, err = sb.file.Write(buf.Bytes())
		sb.nbytes += uint64(n)
		if err != nil {
			return err
		}
		logging.putBuffer(buf)
	}
	return nil
}
Пример #2
0
// outputLogEntry marshals a log entry proto into bytes, and writes
// the data to the log files. If a trace location is set, stack traces
// are added to the entry before marshaling.
func (l *loggingT) outputLogEntry(s Severity, file string, line int, msg string) {
	// TODO(tschottdorf): this is a pretty horrible critical section.
	l.mu.Lock()

	// Set additional details in log entry.
	now := time.Now()
	entry := Entry{
		Severity:  s,
		Time:      now.UnixNano(),
		Goroutine: goid.Get(),
		File:      file,
		Line:      int64(line),
		Message:   msg,
	}
	// On fatal log, set all stacks.
	var stacks []byte
	if s == Severity_FATAL {
		switch traceback {
		case tracebackSingle:
			stacks = getStacks(false)
		case tracebackAll:
			stacks = getStacks(true)
		}
		logExitFunc = func(error) {} // If we get a write error, we'll still exit.
	} else if l.traceLocation.isSet() {
		if l.traceLocation.match(file, line) {
			stacks = getStacks(false)
		}
	}

	if l.toStderr || !logDir.isSet() {
		l.outputToStderr(entry, stacks)
	} else {
		if s >= l.stderrThreshold.get() {
			l.outputToStderr(entry, stacks)
		}
		if l.file[s] == nil {
			if err := l.createFiles(s); err != nil {
				// Make sure the message appears somewhere.
				l.outputToStderr(entry, stacks)
				l.mu.Unlock()
				l.exit(err)
				return
			}
		}

		buf := l.processForFile(entry, stacks)
		data := buf.Bytes()

		switch s {
		case Severity_FATAL:
			if _, err := l.file[Severity_FATAL].Write(data); err != nil {
				panic(err)
			}
			fallthrough
		case Severity_ERROR:
			if _, err := l.file[Severity_ERROR].Write(data); err != nil {
				panic(err)
			}
			fallthrough
		case Severity_WARNING:
			if _, err := l.file[Severity_WARNING].Write(data); err != nil {
				panic(err)
			}
			fallthrough
		case Severity_INFO:
			if _, err := l.file[Severity_INFO].Write(data); err != nil {
				panic(err)
			}
		}

		l.putBuffer(buf)

		if stats := severityStats[s]; stats != nil {
			atomic.AddInt64(&stats.lines, 1)
			atomic.AddInt64(&stats.bytes, int64(len(data)))
		}
	}
	exitFunc := l.exitFunc
	l.mu.Unlock()
	// Flush and exit on fatal logging.
	if s == Severity_FATAL {
		// If we got here via Exit rather than Fatal, print no stacks.
		timeoutFlush(10 * time.Second)
		if atomic.LoadUint32(&fatalNoStacks) > 0 {
			exitFunc(1)
		} else {
			exitFunc(255) // C++ uses -1, which is silly because it's anded with 255 anyway.
		}
	}
}