blob: 798f33bdc3a0daa9b55aadca326a9e9a9e60d040 [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package log
import (
"fmt"
"io"
"os"
"sync"
)
// Handler is the type for entities that process log streams.
// It will be invoked once per log record in the stream.
type Handler func(r Record)
// Closer is returned from handler constructors that must also be closed.
type Closer func()
// GetHandler gets the active Handler for this context.
func GetHandler(ctx Context) Handler {
return ctx.Value(handlerKey).(Handler)
}
// Handler returns a new Builder with the given Handler set on it.
func (ctx logContext) Handler(h Handler) Context {
return ctx.setValue(handlerKey, h)
}
// Stdout returns a Handler that writes to os.Stdout.
// This is conceptually the same as Writer(style, os.Stdout) except the writer is not bound, so if os.Stdout changes
// the new value will be picked up.
func Stdout(style Style) Handler {
return func(r Record) {
style(os.Stdout, r)
fmt.Fprintln(os.Stdout)
}
}
// Stderr returns a Handler that writes to os.Stderr.
// This is conceptually the same as Writer(style, os.Stderr) except the writer is not bound, so if os.Stderr changes
// the new value will be picked up.
func Stderr(style Style) Handler {
return func(r Record) {
style(os.Stderr, r)
fmt.Fprintln(os.Stderr)
}
}
// Std returns a Handler that splits writes between to Stderr and Stdout.
func Std(style Style) Handler {
stderr := Stderr(style)
stdout := Stdout(style)
return func(r Record) {
switch {
case r.Severity <= ErrorLevel:
stderr(r)
default:
stdout(r)
}
}
}
// Writer is a Handler that uses the active Style to write records to an underlying io.Writer
func Writer(style Style, to io.Writer) Handler {
return func(r Record) {
style(to, r)
fmt.Fprintln(to)
}
}
// Channel is a Handler that passes log records to another Handler through a blocking chan.
// This makes this Handler safe to use from multiple threads
func Channel(to Handler) (Handler, Closer) {
c := make(chan Record)
done := make(chan struct{})
go func() {
for r := range c {
to(r)
}
close(done)
}()
handler := func(r Record) {
c <- r
}
once := sync.Once{}
closer := func() {
once.Do(func() {
close(c)
<-done
})
}
return handler, closer
}
// Fork forwards all messages to all supplied handlers.
func Fork(handlers ...Handler) Handler {
return func(r Record) {
for _, handler := range handlers {
handler(r)
}
}
}
// LimitSplit splits incoming log messages based on their priority.
// It forwards all messages of limit or higher severity to the high handler, and the rest to the low Handler.
func LimitSplit(limit Severity, high Handler, low Handler) Handler {
return func(r Record) {
handler := low
if r.Severity <= limit {
handler = high
}
if handler != nil {
handler(r)
}
}
}