glog.go
func (l *Log) output(s Severity, buf *buffer, file string, line int) {
	l.mu.Lock()
	if l.traceLocation.isSet() {
		if l.traceLocation.match(file, line) {
			buf.Write(stacks(false, l.maxStackBufSize))
		}
	}
	data := buf.Bytes()
	if l.toStderr {
		os.Stderr.Write(data)
	} else {
		if l.alsoToStderr || s >= l.stderrThreshold.get() {
			os.Stderr.Write(data)
		}
		if l.file[s] == nil {
			if err := l.createFiles(s); err != nil {
				os.Stderr.Write(data) // Make sure the message appears somewhere.
				l.exit(err)
			}
		}
		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 s == FatalLog {
		// Make sure we see the trace for the current goroutine on standard error.
		if !l.toStderr {
			os.Stderr.Write(stacks(false, l.maxStackBufSize))
		}
		// Write the stack trace for all goroutines to the files.
		trace := stacks(true, l.maxStackBufSize)
		logExitFunc = func(error) {} // If we get a write error, we'll still exit below.
		for log := FatalLog; log >= InfoLog; log-- {
			if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set.
				f.Write(trace)
			}
		}
		l.mu.Unlock()
		timeoutFlush(l, 10*time.Second)
		os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway.
	}
	l.putBuffer(buf)
	l.mu.Unlock()
	if stats := l.severityStats[s]; stats != nil {
		atomic.AddInt64(&stats.lines, 1)
		atomic.AddInt64(&stats.bytes, int64(len(data)))
	}
}
func (l *Log) output(s Severity, buf *buffer, file string, line int) {
	l.mu.Lock()
	if l.traceLocation.isSet() {
		if l.traceLocation.match(file, line) {
			buf.Write(stacks(false, l.maxStackBufSize))
		}
	}
	data := buf.Bytes()
	if l.toStderr {
		os.Stderr.Write(data)
	} else {
		if l.alsoToStderr || s >= l.stderrThreshold.get() {
			os.Stderr.Write(data)
		}
		if l.file[s] == nil {
			if err := l.createFiles(s); err != nil {
				os.Stderr.Write(data) // Make sure the message appears somewhere.
				l.exit(err)
			}
		}
		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 s == FatalLog {
		// Make sure we see the trace for the current goroutine on standard error.
		if !l.toStderr {
			os.Stderr.Write(stacks(false, l.maxStackBufSize))
		}
		// Write the stack trace for all goroutines to the files.
		trace := stacks(true, l.maxStackBufSize)
		logExitFunc = func(error) {} // If we get a write error, we'll still exit below.
		for log := FatalLog; log >= InfoLog; log-- {
			if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set.
				f.Write(trace)
			}
		}
		l.mu.Unlock()
		timeoutFlush(l, 10*time.Second)
		os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway.
	}
	l.putBuffer(buf)
	l.mu.Unlock()
	if stats := l.severityStats[s]; stats != nil {
		atomic.AddInt64(&stats.lines, 1)
		atomic.AddInt64(&stats.bytes, int64(len(data)))
	}
}
func ( l * Log ) output ( s Severity , buf * buffer , file string , line int ) { l . mu . Lock ( ) if l . traceLocation . isSet ( ) { if l . traceLocation . match ( file , line ) { buf . Write ( stacks ( false , l . maxStackBufSize ) ) } } data := buf . Bytes ( ) if l . toStderr { os . Stderr . Write ( data ) } else { if l . alsoToStderr || s >= l . stderrThreshold . get ( ) { os . Stderr . Write ( data ) } if l . file [ s ] == nil { if err := l . createFiles ( s ) ; err != nil { os . Stderr . Write ( data ) // Make sure the message appears somewhere. l . exit ( err ) } } 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 s == FatalLog { // Make sure we see the trace for the current goroutine on standard error. if ! l . toStderr { os . Stderr . Write ( stacks ( false , l . maxStackBufSize ) ) } // Write the stack trace for all goroutines to the files. trace := stacks ( true , l . maxStackBufSize ) logExitFunc = func ( error ) { } // If we get a write error, we'll still exit below. for log := FatalLog ; log >= InfoLog ; log -- { if f := l . file [ log ] ; f != nil { // Can be nil if -logtostderr is set. f . Write ( trace ) } } l . mu . Unlock ( ) timeoutFlush ( l , 10 * time . Second ) os . Exit ( 255 ) // C++ uses -1, which is silly because it's anded with 255 anyway. } l . putBuffer ( buf ) l . mu . Unlock ( ) if stats := l . severityStats [ s ] ; stats != nil { atomic . AddInt64 ( & stats . lines , 1 ) atomic . AddInt64 ( & stats . bytes , int64 ( len ( data ) ) ) } }
// output writes the data to the log files and releases the buffer.
output writes the data to the log files and releases the buffer .