예제 #1
0
// setLogEntry populates the log entry with format, arguments,
// and any available fields set in the context.
func setLogEntry(ctx context.Context, format string, args []interface{}, entry *proto.LogEntry) {
	entry.Format, entry.Args = parseFormatWithArgs(format, args)

	if ctx != nil {
		for i := Field(0); i < maxField; i++ {
			if v := ctx.Value(i); v != nil {
				switch vTyp := v.(type) {
				case proto.NodeID:
					entry.NodeID = &vTyp
				case proto.StoreID:
					entry.StoreID = &vTyp
				case proto.RaftID:
					entry.RaftID = &vTyp
				case proto.Method:
					entry.Method = &vTyp
				case proto.Key:
					entry.Key = vTyp
				}
			}
		}
	}
}
예제 #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, alsoToStderr bool, entry *proto.LogEntry) {
	l.mu.Lock()

	// Set additional details in log entry.
	now := time.Now()
	entry.Severity = int32(s)
	entry.Time = now.UnixNano()
	entry.ThreadID = int32(pid) // TODO: should be TID
	entry.File = file
	entry.Line = int32(line)
	// On fatal log, set all stacks.
	if s == FatalLog {
		entry.Stacks = stacks(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) {
			entry.Stacks = stacks(false)
		}
	}

	if l.toStderr {
		_, _ = os.Stderr.Write(l.processForStderr(entry))
	} else {
		if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() {
			_, _ = os.Stderr.Write(l.processForStderr(entry))
		}
		if l.file[s] == nil {
			if err := l.createFiles(s); err != nil {
				_, _ = os.Stderr.Write(l.processForStderr(entry)) // Make sure the message appears somewhere.
				l.exit(err)
			}
		}

		data := encodeLogEntry(entry)

		switch s {
		case FatalLog:
			l.file[FatalLog].Write(data)
			fallthrough
		case ErrorLog:
			l.file[ErrorLog].Write(data)
			fallthrough
		case WarningLog:
			l.file[WarningLog].Write(data)
			fallthrough
		case InfoLog:
			l.file[InfoLog].Write(data)
		}

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