<commit_before>package logrus

import (
	"io"
	"os"
	"sync"
	"sync/atomic"
)

type Logger struct {
	// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
	// file, or leave it default which is `os.Stderr`. You can also set this to
	// something more adventorous, such as logging to Kafka.
	Out io.Writer
	// Hooks for the logger instance. These allow firing events based on logging
	// levels and log entries. For example, to send errors to an error tracking
	// service, log to StatsD or dump the core on fatal errors.
	Hooks LevelHooks
	// All log entries pass through the formatter before logged to Out. The
	// included formatters are `TextFormatter` and `JSONFormatter` for which
	// TextFormatter is the default. In development (when a TTY is attached) it
	// logs with colors, but to a file it wouldn't. You can easily implement your
	// own that implements the `Formatter` interface, see the `README` or included
	// formatters for examples.
	Formatter Formatter
	// The logging level the logger should log at. This is typically (and defaults
	// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
	// logged.
	Level Level
	// Used to sync writing to the log. Locking is enabled by Default
	mu MutexWrap
	// Reusable empty entry
	entryPool sync.Pool
}

type MutexWrap struct {
	lock     sync.Mutex
	disabled bool
}

func (mw *MutexWrap) Lock() {
	if !mw.disabled {
		mw.lock.Lock()
	}
}

func (mw *MutexWrap) Unlock() {
	if !mw.disabled {
		mw.lock.Unlock()
	}
}

func (mw *MutexWrap) Disable() {
	mw.disabled = true
}

// Creates a new logger. Configuration should be set by changing `Formatter`,
// `Out` and `Hooks` directly on the default logger instance. You can also just
// instantiate your own:
//
//    var log = &Logger{
//      Out: os.Stderr,
//      Formatter: new(JSONFormatter),
//      Hooks: make(LevelHooks),
//      Level: logrus.DebugLevel,
//    }
//
// It's recommended to make this a global instance called `log`.
func New() *Logger {
	return &Logger{
		Out:       os.Stderr,
		Formatter: new(TextFormatter),
		Hooks:     make(LevelHooks),
		Level:     InfoLevel,
	}
}

func (logger *Logger) newEntry() *Entry {
	entry, ok := logger.entryPool.Get().(*Entry)
	if ok {
		return entry
	}
	return NewEntry(logger)
}

func (logger *Logger) releaseEntry(entry *Entry) {
	logger.entryPool.Put(entry)
}

// Adds a field to the log entry, note that it doesn't log until you call
// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
// If you want multiple fields, use `WithFields`.
func (logger *Logger) WithField(key string, value interface{}) *Entry {
	entry := logger.newEntry()
	defer logger.releaseEntry(entry)
	return entry.WithField(key, value)
}

// Adds a struct of fields to the log entry. All it does is call `WithField` for
// each `Field`.
func (logger *Logger) WithFields(fields Fields) *Entry {
	entry := logger.newEntry()
	defer logger.releaseEntry(entry)
	return entry.WithFields(fields)
}

// Add an error as single field to the log entry.  All it does is call
// `WithError` for the given `error`.
func (logger *Logger) WithError(err error) *Entry {
	entry := logger.newEntry()
	defer logger.releaseEntry(entry)
	return entry.WithError(err)
}

func (logger *Logger) Debugf(format string, args ...interface{}) {
	if logger.level() >= DebugLevel {
		entry := logger.newEntry()
		entry.Debugf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Infof(format string, args ...interface{}) {
	if logger.level() >= InfoLevel {
		entry := logger.newEntry()
		entry.Infof(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Printf(format string, args ...interface{}) {
	entry := logger.newEntry()
	entry.Printf(format, args...)
	logger.releaseEntry(entry)
}

func (logger *Logger) Warnf(format string, args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warnf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Warningf(format string, args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warnf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Errorf(format string, args ...interface{}) {
	if logger.level() >= ErrorLevel {
		entry := logger.newEntry()
		entry.Errorf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Fatalf(format string, args ...interface{}) {
	if logger.level() >= FatalLevel {
		entry := logger.newEntry()
		entry.Fatalf(format, args...)
		logger.releaseEntry(entry)
	}
	Exit(1)
}

func (logger *Logger) Panicf(format string, args ...interface{}) {
	if logger.level() >= PanicLevel {
		entry := logger.newEntry()
		entry.Panicf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Debug(args ...interface{}) {
	if logger.level() >= DebugLevel {
		entry := logger.newEntry()
		entry.Debug(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Info(args ...interface{}) {
	if logger.level() >= InfoLevel {
		entry := logger.newEntry()
		entry.Info(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Print(args ...interface{}) {
	entry := logger.newEntry()
	entry.Info(args...)
	logger.releaseEntry(entry)
}

func (logger *Logger) Warn(args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warn(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Warning(args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warn(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Error(args ...interface{}) {
	if logger.level() >= ErrorLevel {
		entry := logger.newEntry()
		entry.Error(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Fatal(args ...interface{}) {
	if logger.level() >= FatalLevel {
		entry := logger.newEntry()
		entry.Fatal(args...)
		logger.releaseEntry(entry)
	}
	Exit(1)
}

func (logger *Logger) Panic(args ...interface{}) {
	if logger.level() >= PanicLevel {
		entry := logger.newEntry()
		entry.Panic(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Debugln(args ...interface{}) {
	if logger.level() >= DebugLevel {
		entry := logger.newEntry()
		entry.Debugln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Infoln(args ...interface{}) {
	if logger.level() >= InfoLevel {
		entry := logger.newEntry()
		entry.Infoln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Println(args ...interface{}) {
	entry := logger.newEntry()
	entry.Println(args...)
	logger.releaseEntry(entry)
}

func (logger *Logger) Warnln(args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warnln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Warningln(args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warnln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Errorln(args ...interface{}) {
	if logger.level() >= ErrorLevel {
		entry := logger.newEntry()
		entry.Errorln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Fatalln(args ...interface{}) {
	if logger.level() >= FatalLevel {
		entry := logger.newEntry()
		entry.Fatalln(args...)
		logger.releaseEntry(entry)
	}
	Exit(1)
}

func (logger *Logger) Panicln(args ...interface{}) {
	if logger.level() >= PanicLevel {
		entry := logger.newEntry()
		entry.Panicln(args...)
		logger.releaseEntry(entry)
	}
}

//When file is opened with appending mode, it's safe to
//write concurrently to a file (within 4k message on Linux).
//In these cases user can choose to disable the lock.
func (logger *Logger) SetNoLock() {
	logger.mu.Disable()
}

func (logger *Logger) level() Level {
	return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
}

func (logger *Logger) SetLevel(level Level) {
	atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
}

func (logger *Logger) AddHook(hook Hook) {
	logger.mu.Lock()
	defer logger.mu.Unlock()
	logger.Hooks.Add(hook)
}
<commit_msg>Fix typo in docstring<commit_after>package logrus

import (
	"io"
	"os"
	"sync"
	"sync/atomic"
)

type Logger struct {
	// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
	// file, or leave it default which is `os.Stderr`. You can also set this to
	// something more adventurous, such as logging to Kafka.
	Out io.Writer
	// Hooks for the logger instance. These allow firing events based on logging
	// levels and log entries. For example, to send errors to an error tracking
	// service, log to StatsD or dump the core on fatal errors.
	Hooks LevelHooks
	// All log entries pass through the formatter before logged to Out. The
	// included formatters are `TextFormatter` and `JSONFormatter` for which
	// TextFormatter is the default. In development (when a TTY is attached) it
	// logs with colors, but to a file it wouldn't. You can easily implement your
	// own that implements the `Formatter` interface, see the `README` or included
	// formatters for examples.
	Formatter Formatter
	// The logging level the logger should log at. This is typically (and defaults
	// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
	// logged.
	Level Level
	// Used to sync writing to the log. Locking is enabled by Default
	mu MutexWrap
	// Reusable empty entry
	entryPool sync.Pool
}

type MutexWrap struct {
	lock     sync.Mutex
	disabled bool
}

func (mw *MutexWrap) Lock() {
	if !mw.disabled {
		mw.lock.Lock()
	}
}

func (mw *MutexWrap) Unlock() {
	if !mw.disabled {
		mw.lock.Unlock()
	}
}

func (mw *MutexWrap) Disable() {
	mw.disabled = true
}

// Creates a new logger. Configuration should be set by changing `Formatter`,
// `Out` and `Hooks` directly on the default logger instance. You can also just
// instantiate your own:
//
//    var log = &Logger{
//      Out: os.Stderr,
//      Formatter: new(JSONFormatter),
//      Hooks: make(LevelHooks),
//      Level: logrus.DebugLevel,
//    }
//
// It's recommended to make this a global instance called `log`.
func New() *Logger {
	return &Logger{
		Out:       os.Stderr,
		Formatter: new(TextFormatter),
		Hooks:     make(LevelHooks),
		Level:     InfoLevel,
	}
}

func (logger *Logger) newEntry() *Entry {
	entry, ok := logger.entryPool.Get().(*Entry)
	if ok {
		return entry
	}
	return NewEntry(logger)
}

func (logger *Logger) releaseEntry(entry *Entry) {
	logger.entryPool.Put(entry)
}

// Adds a field to the log entry, note that it doesn't log until you call
// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
// If you want multiple fields, use `WithFields`.
func (logger *Logger) WithField(key string, value interface{}) *Entry {
	entry := logger.newEntry()
	defer logger.releaseEntry(entry)
	return entry.WithField(key, value)
}

// Adds a struct of fields to the log entry. All it does is call `WithField` for
// each `Field`.
func (logger *Logger) WithFields(fields Fields) *Entry {
	entry := logger.newEntry()
	defer logger.releaseEntry(entry)
	return entry.WithFields(fields)
}

// Add an error as single field to the log entry.  All it does is call
// `WithError` for the given `error`.
func (logger *Logger) WithError(err error) *Entry {
	entry := logger.newEntry()
	defer logger.releaseEntry(entry)
	return entry.WithError(err)
}

func (logger *Logger) Debugf(format string, args ...interface{}) {
	if logger.level() >= DebugLevel {
		entry := logger.newEntry()
		entry.Debugf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Infof(format string, args ...interface{}) {
	if logger.level() >= InfoLevel {
		entry := logger.newEntry()
		entry.Infof(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Printf(format string, args ...interface{}) {
	entry := logger.newEntry()
	entry.Printf(format, args...)
	logger.releaseEntry(entry)
}

func (logger *Logger) Warnf(format string, args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warnf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Warningf(format string, args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warnf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Errorf(format string, args ...interface{}) {
	if logger.level() >= ErrorLevel {
		entry := logger.newEntry()
		entry.Errorf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Fatalf(format string, args ...interface{}) {
	if logger.level() >= FatalLevel {
		entry := logger.newEntry()
		entry.Fatalf(format, args...)
		logger.releaseEntry(entry)
	}
	Exit(1)
}

func (logger *Logger) Panicf(format string, args ...interface{}) {
	if logger.level() >= PanicLevel {
		entry := logger.newEntry()
		entry.Panicf(format, args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Debug(args ...interface{}) {
	if logger.level() >= DebugLevel {
		entry := logger.newEntry()
		entry.Debug(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Info(args ...interface{}) {
	if logger.level() >= InfoLevel {
		entry := logger.newEntry()
		entry.Info(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Print(args ...interface{}) {
	entry := logger.newEntry()
	entry.Info(args...)
	logger.releaseEntry(entry)
}

func (logger *Logger) Warn(args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warn(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Warning(args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warn(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Error(args ...interface{}) {
	if logger.level() >= ErrorLevel {
		entry := logger.newEntry()
		entry.Error(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Fatal(args ...interface{}) {
	if logger.level() >= FatalLevel {
		entry := logger.newEntry()
		entry.Fatal(args...)
		logger.releaseEntry(entry)
	}
	Exit(1)
}

func (logger *Logger) Panic(args ...interface{}) {
	if logger.level() >= PanicLevel {
		entry := logger.newEntry()
		entry.Panic(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Debugln(args ...interface{}) {
	if logger.level() >= DebugLevel {
		entry := logger.newEntry()
		entry.Debugln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Infoln(args ...interface{}) {
	if logger.level() >= InfoLevel {
		entry := logger.newEntry()
		entry.Infoln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Println(args ...interface{}) {
	entry := logger.newEntry()
	entry.Println(args...)
	logger.releaseEntry(entry)
}

func (logger *Logger) Warnln(args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warnln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Warningln(args ...interface{}) {
	if logger.level() >= WarnLevel {
		entry := logger.newEntry()
		entry.Warnln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Errorln(args ...interface{}) {
	if logger.level() >= ErrorLevel {
		entry := logger.newEntry()
		entry.Errorln(args...)
		logger.releaseEntry(entry)
	}
}

func (logger *Logger) Fatalln(args ...interface{}) {
	if logger.level() >= FatalLevel {
		entry := logger.newEntry()
		entry.Fatalln(args...)
		logger.releaseEntry(entry)
	}
	Exit(1)
}

func (logger *Logger) Panicln(args ...interface{}) {
	if logger.level() >= PanicLevel {
		entry := logger.newEntry()
		entry.Panicln(args...)
		logger.releaseEntry(entry)
	}
}

//When file is opened with appending mode, it's safe to
//write concurrently to a file (within 4k message on Linux).
//In these cases user can choose to disable the lock.
func (logger *Logger) SetNoLock() {
	logger.mu.Disable()
}

func (logger *Logger) level() Level {
	return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
}

func (logger *Logger) SetLevel(level Level) {
	atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
}

func (logger *Logger) AddHook(hook Hook) {
	logger.mu.Lock()
	defer logger.mu.Unlock()
	logger.Hooks.Add(hook)
}
<|endoftext|>


<commit_before>package libkb

import "os"

// TrapKeypress is designed to read stdin, looking for Ctrl-C or
// Ctrl-D.  When it receives either, it will shut down the client.
// To use it, do this:
//
// func x() {
//	done := make(chan bool)
//	defer close(done)
//	go libkb.TrapKeypress(done)
//	// do something that takes a long time and doesn't prompt
//	// the user for anything
// }
//
// When the function exits, TrapKeypress will stop.  It will
// consume one more byte from stdin, however, as there is no way
// to cancel the pending read.
//
// This is only necessary when there is a long-running command
// that doesn't use the ui to prompt the user.  For example,
// logging in on a new device while it is waiting for the `sibkey
// add` command to run on an existing device.
func TrapKeypress(done chan bool) {
	keys := make(chan byte)
	go func() {
		buf := make([]byte, 1)
		for {
			_, err := os.Stdin.Read(buf)
			if err != nil {
				G.Log.Debug("stdin read error: %s", err)
				return
			}
			select {
			case keys <- buf[0]:
			case <-done:
				G.Log.Debug("TrapKeypress read goroutine stopping due to closed done chan")
				return
			}
		}
	}()

	for {
		select {
		case k := <-keys:
			if k == 3 || k == 4 {
				// ctrl-c or ctrl-d pressed
				G.Log.Debug("TrapKeypress trapped ctrl-c or ctrl-d")
				G.Shutdown()
				G.Log.Error("interrupted")
				os.Exit(3)
			}
		case <-done:
			G.Log.Debug("TrapKeypress received on done chan, exiting")
			return
		}
	}
}
<commit_msg>Remove unused code press.go<commit_after><|endoftext|>


<commit_before>/* Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 siesta

import (
	"fmt"

	log "github.com/cihub/seelog"
)

//Logger used by this client. Defaults to build-in logger with Info log level.
var Logger KafkaLogger = NewDefaultLogger(InfoLevel)

// KafkaLogger is a logger interface. Lets you plug-in your custom logging library instead of using built-in one.
type KafkaLogger interface {
	//Formats a given message according to given params to log with level Trace.
	Trace(message string, params ...interface{})

	//Formats a given message according to given params to log with level Debug.
	Debug(message string, params ...interface{})

	//Formats a given message according to given params to log with level Info.
	Info(message string, params ...interface{})

	//Formats a given message according to given params to log with level Warn.
	Warn(message string, params ...interface{})

	//Formats a given message according to given params to log with level Error.
	Error(message string, params ...interface{})

	//Formats a given message according to given params to log with level Critical.
	Critical(message string, params ...interface{})
}

// LogLevel represents a logging level.
type LogLevel string

const (
	// TraceLevel is used for debugging to find problems in functions, variables etc.
	TraceLevel LogLevel = "trace"

	// DebugLevel is used for detailed system reports and diagnostic messages.
	DebugLevel LogLevel = "debug"

	// InfoLevel is used for general information about a running application.
	InfoLevel LogLevel = "info"

	// WarnLevel is used to indicate small errors and failures that should not happen normally but are recovered automatically.
	WarnLevel LogLevel = "warn"

	// ErrorLevel is used to indicate severe errors that affect application workflow and are not handled automatically.
	ErrorLevel LogLevel = "error"

	// CriticalLevel is used to indicate fatal errors that may cause data corruption or loss.
	CriticalLevel LogLevel = "critical"
)

// Trace writes a given message with a given tag to log with level Trace.
func Trace(tag interface{}, message interface{}) {
	Logger.Trace(fmt.Sprintf("[%s] %s", tag, message))
}

// Tracef formats a given message according to given params with a given tag to log with level Trace.
func Tracef(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Trace(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Debug writes a given message with a given tag to log with level Debug.
func Debug(tag interface{}, message interface{}) {
	Logger.Debug(fmt.Sprintf("[%s] %s", tag, message))
}

// Debugf formats a given message according to given params with a given tag to log with level Debug.
func Debugf(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Debug(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Info writes a given message with a given tag to log with level Info.
func Info(tag interface{}, message interface{}) {
	Logger.Info(fmt.Sprintf("[%s] %s", tag, message))
}

// Infof formats a given message according to given params with a given tag to log with level Info.
func Infof(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Info(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Warn writes a given message with a given tag to log with level Warn.
func Warn(tag interface{}, message interface{}) {
	Logger.Warn(fmt.Sprintf("[%s] %s", tag, message))
}

// Warnf formats a given message according to given params with a given tag to log with level Warn.
func Warnf(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Warn(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Error writes a given message with a given tag to log with level Error.
func Error(tag interface{}, message interface{}) {
	Logger.Error(fmt.Sprintf("[%s] %s", tag, message))
}

// Errorf formats a given message according to given params with a given tag to log with level Error.
func Errorf(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Error(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Critical writes a given message with a given tag to log with level Critical.
func Critical(tag interface{}, message interface{}) {
	Logger.Critical(fmt.Sprintf("[%s] %s", tag, message))
}

// Criticalf formats a given message according to given params with a given tag to log with level Critical.
func Criticalf(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Critical(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// DefaultLogger is a default implementation of KafkaLogger interface used in this client.
type DefaultLogger struct {
	logger log.LoggerInterface
}

// NewDefaultLogger creates a new DefaultLogger that is configured to write messages to console with minimum log level Level.
func NewDefaultLogger(Level LogLevel) *DefaultLogger {
	var config = fmt.Sprintf(`<seelog minlevel="%s">
    <outputs formatid="main">
        <console />
    </outputs>

    <formats>
        <format id="main" format="%%Date/%%Time [%%LEVEL] %%Msg%%n"/>
    </formats>
</seelog>`, Level)
	logger, _ := log.LoggerFromConfigAsBytes([]byte(config))
	return &DefaultLogger{logger}
}

// Trace formats a given message according to given params to log with level Trace.
func (dl *DefaultLogger) Trace(message string, params ...interface{}) {
	dl.logger.Tracef(message, params...)
}

// Debug formats a given message according to given params to log with level Debug.
func (dl *DefaultLogger) Debug(message string, params ...interface{}) {
	dl.logger.Debugf(message, params...)
}

// Info formats a given message according to given params to log with level Info.
func (dl *DefaultLogger) Info(message string, params ...interface{}) {
	dl.logger.Infof(message, params...)
}

// Warn formats a given message according to given params to log with level Warn.
func (dl *DefaultLogger) Warn(message string, params ...interface{}) {
	dl.logger.Warnf(message, params...)
}

// Error formats a given message according to given params to log with level Error.
func (dl *DefaultLogger) Error(message string, params ...interface{}) {
	dl.logger.Errorf(message, params...)
}

// Critical formats a given message according to given params to log with level Critical.
func (dl *DefaultLogger) Critical(message string, params ...interface{}) {
	dl.logger.Criticalf(message, params...)
}
<commit_msg>Replaced logger package to use gopkg.in<commit_after>/* Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 siesta

import (
	"fmt"

	log "gopkg.in/cihub/seelog.v2"
)

//Logger used by this client. Defaults to build-in logger with Info log level.
var Logger KafkaLogger = NewDefaultLogger(InfoLevel)

// KafkaLogger is a logger interface. Lets you plug-in your custom logging library instead of using built-in one.
type KafkaLogger interface {
	//Formats a given message according to given params to log with level Trace.
	Trace(message string, params ...interface{})

	//Formats a given message according to given params to log with level Debug.
	Debug(message string, params ...interface{})

	//Formats a given message according to given params to log with level Info.
	Info(message string, params ...interface{})

	//Formats a given message according to given params to log with level Warn.
	Warn(message string, params ...interface{})

	//Formats a given message according to given params to log with level Error.
	Error(message string, params ...interface{})

	//Formats a given message according to given params to log with level Critical.
	Critical(message string, params ...interface{})
}

// LogLevel represents a logging level.
type LogLevel string

const (
	// TraceLevel is used for debugging to find problems in functions, variables etc.
	TraceLevel LogLevel = "trace"

	// DebugLevel is used for detailed system reports and diagnostic messages.
	DebugLevel LogLevel = "debug"

	// InfoLevel is used for general information about a running application.
	InfoLevel LogLevel = "info"

	// WarnLevel is used to indicate small errors and failures that should not happen normally but are recovered automatically.
	WarnLevel LogLevel = "warn"

	// ErrorLevel is used to indicate severe errors that affect application workflow and are not handled automatically.
	ErrorLevel LogLevel = "error"

	// CriticalLevel is used to indicate fatal errors that may cause data corruption or loss.
	CriticalLevel LogLevel = "critical"
)

// Trace writes a given message with a given tag to log with level Trace.
func Trace(tag interface{}, message interface{}) {
	Logger.Trace(fmt.Sprintf("[%s] %s", tag, message))
}

// Tracef formats a given message according to given params with a given tag to log with level Trace.
func Tracef(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Trace(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Debug writes a given message with a given tag to log with level Debug.
func Debug(tag interface{}, message interface{}) {
	Logger.Debug(fmt.Sprintf("[%s] %s", tag, message))
}

// Debugf formats a given message according to given params with a given tag to log with level Debug.
func Debugf(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Debug(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Info writes a given message with a given tag to log with level Info.
func Info(tag interface{}, message interface{}) {
	Logger.Info(fmt.Sprintf("[%s] %s", tag, message))
}

// Infof formats a given message according to given params with a given tag to log with level Info.
func Infof(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Info(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Warn writes a given message with a given tag to log with level Warn.
func Warn(tag interface{}, message interface{}) {
	Logger.Warn(fmt.Sprintf("[%s] %s", tag, message))
}

// Warnf formats a given message according to given params with a given tag to log with level Warn.
func Warnf(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Warn(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Error writes a given message with a given tag to log with level Error.
func Error(tag interface{}, message interface{}) {
	Logger.Error(fmt.Sprintf("[%s] %s", tag, message))
}

// Errorf formats a given message according to given params with a given tag to log with level Error.
func Errorf(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Error(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// Critical writes a given message with a given tag to log with level Critical.
func Critical(tag interface{}, message interface{}) {
	Logger.Critical(fmt.Sprintf("[%s] %s", tag, message))
}

// Criticalf formats a given message according to given params with a given tag to log with level Critical.
func Criticalf(tag interface{}, message interface{}, params ...interface{}) {
	Logger.Critical(fmt.Sprintf("[%s] %s", tag, message), params...)
}

// DefaultLogger is a default implementation of KafkaLogger interface used in this client.
type DefaultLogger struct {
	logger log.LoggerInterface
}

// NewDefaultLogger creates a new DefaultLogger that is configured to write messages to console with minimum log level Level.
func NewDefaultLogger(Level LogLevel) *DefaultLogger {
	var config = fmt.Sprintf(`<seelog minlevel="%s">
    <outputs formatid="main">
        <console />
    </outputs>

    <formats>
        <format id="main" format="%%Date/%%Time [%%LEVEL] %%Msg%%n"/>
    </formats>
</seelog>`, Level)
	logger, _ := log.LoggerFromConfigAsBytes([]byte(config))
	return &DefaultLogger{logger}
}

// Trace formats a given message according to given params to log with level Trace.
func (dl *DefaultLogger) Trace(message string, params ...interface{}) {
	dl.logger.Tracef(message, params...)
}

// Debug formats a given message according to given params to log with level Debug.
func (dl *DefaultLogger) Debug(message string, params ...interface{}) {
	dl.logger.Debugf(message, params...)
}

// Info formats a given message according to given params to log with level Info.
func (dl *DefaultLogger) Info(message string, params ...interface{}) {
	dl.logger.Infof(message, params...)
}

// Warn formats a given message according to given params to log with level Warn.
func (dl *DefaultLogger) Warn(message string, params ...interface{}) {
	dl.logger.Warnf(message, params...)
}

// Error formats a given message according to given params to log with level Error.
func (dl *DefaultLogger) Error(message string, params ...interface{}) {
	dl.logger.Errorf(message, params...)
}

// Critical formats a given message according to given params to log with level Critical.
func (dl *DefaultLogger) Critical(message string, params ...interface{}) {
	dl.logger.Criticalf(message, params...)
}
<|endoftext|>


<commit_before>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements Sizes.

package types

// Sizes defines the sizing functions for package unsafe.
type Sizes interface {
	// Alignof returns the alignment of a variable of type T.
	// Alignof must implement the alignment guarantees required by the spec.
	Alignof(T Type) int64

	// Offsetsof returns the offsets of the given struct fields, in bytes.
	// Offsetsof must implement the offset guarantees required by the spec.
	Offsetsof(fields []*Var) []int64

	// Sizeof returns the size of a variable of type T.
	// Sizeof must implement the size guarantees required by the spec.
	Sizeof(T Type) int64
}

// StdSizes is a convenience type for creating commonly used Sizes.
// It makes the following simplifying assumptions:
//
//	- The size of explicitly sized basic types (int16, etc.) is the
//	  specified size.
//	- The size of strings, functions, and interfaces is 2*WordSize.
//	- The size of slices is 3*WordSize.
//	- All other types have size WordSize.
//	- Arrays and structs are aligned per spec definition; all other
//	  types are naturally aligned with a maximum alignment MaxAlign.
//
// *StdSizes implements Sizes.
//
type StdSizes struct {
	WordSize int64 // word size in bytes - must be >= 4 (32bits)
	MaxAlign int64 // maximum alignment in bytes - must be >= 1
}

func (s *StdSizes) Alignof(T Type) int64 {
	// For arrays and structs, alignment is defined in terms
	// of alignment of the elements and fields, respectively.
	switch t := T.Underlying().(type) {
	case *Array:
		// spec: "For a variable x of array type: unsafe.Alignof(x)
		// is the same as unsafe.Alignof(x[0]), but at least 1."
		return s.Alignof(t.elem)
	case *Struct:
		// spec: "For a variable x of struct type: unsafe.Alignof(x)
		// is the largest of the values unsafe.Alignof(x.f) for each
		// field f of x, but at least 1."
		max := int64(1)
		for _, f := range t.fields {
			if a := s.Alignof(f.typ); a > max {
				max = a
			}
		}
		return max
	}
	a := s.Sizeof(T) // may be 0
	// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
	if a < 1 {
		return 1
	}
	if a > s.MaxAlign {
		return s.MaxAlign
	}
	return a
}

func (s *StdSizes) Offsetsof(fields []*Var) []int64 {
	offsets := make([]int64, len(fields))
	var o int64
	for i, f := range fields {
		a := s.Alignof(f.typ)
		o = align(o, a)
		offsets[i] = o
		o += s.Sizeof(f.typ)
	}
	return offsets
}

func (s *StdSizes) Sizeof(T Type) int64 {
	switch t := T.Underlying().(type) {
	case *Basic:
		if z := t.size; z > 0 {
			return z
		}
		if t.kind == String {
			return s.WordSize * 2
		}
	case *Array:
		a := s.Alignof(t.elem)
		z := s.Sizeof(t.elem)
		return align(z, a) * t.len // may be 0
	case *Slice:
		return s.WordSize * 3
	case *Struct:
		n := t.NumFields()
		if n == 0 {
			return 0
		}
		offsets := t.offsets
		if t.offsets == nil {
			// compute offsets on demand
			offsets = s.Offsetsof(t.fields)
			t.offsets = offsets
		}
		return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
	case *Signature, *Interface:
		return s.WordSize * 2
	}
	return s.WordSize // catch-all
}

// stdSizes is used if Config.Sizes == nil.
var stdSizes = StdSizes{8, 8}

func (conf *Config) alignof(T Type) int64 {
	if s := conf.Sizes; s != nil {
		if a := s.Alignof(T); a >= 1 {
			return a
		}
		panic("Config.Sizes.Alignof returned an alignment < 1")
	}
	return stdSizes.Alignof(T)
}

func (conf *Config) offsetsof(T *Struct) []int64 {
	offsets := T.offsets
	if offsets == nil && T.NumFields() > 0 {
		// compute offsets on demand
		if s := conf.Sizes; s != nil {
			offsets = s.Offsetsof(T.fields)
			// sanity checks
			if len(offsets) != T.NumFields() {
				panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
			}
			for _, o := range offsets {
				if o < 0 {
					panic("Config.Sizes.Offsetsof returned an offset < 0")
				}
			}
		} else {
			offsets = stdSizes.Offsetsof(T.fields)
		}
		T.offsets = offsets
	}
	return offsets
}

// offsetof returns the offset of the field specified via
// the index sequence relative to typ. All embedded fields
// must be structs (rather than pointer to structs).
func (conf *Config) offsetof(typ Type, index []int) int64 {
	var o int64
	for _, i := range index {
		s := typ.Underlying().(*Struct)
		o += conf.offsetsof(s)[i]
		typ = s.fields[i].typ
	}
	return o
}

func (conf *Config) sizeof(T Type) int64 {
	if s := conf.Sizes; s != nil {
		if z := s.Sizeof(T); z >= 0 {
			return z
		}
		panic("Config.Sizes.Sizeof returned a size < 0")
	}
	return stdSizes.Sizeof(T)
}

// align returns the smallest y >= x such that y % a == 0.
func align(x, a int64) int64 {
	y := x + a - 1
	return y - y%a
}
<commit_msg>go.tools/go/types: use WordSize as function pointer size<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements Sizes.

package types

// Sizes defines the sizing functions for package unsafe.
type Sizes interface {
	// Alignof returns the alignment of a variable of type T.
	// Alignof must implement the alignment guarantees required by the spec.
	Alignof(T Type) int64

	// Offsetsof returns the offsets of the given struct fields, in bytes.
	// Offsetsof must implement the offset guarantees required by the spec.
	Offsetsof(fields []*Var) []int64

	// Sizeof returns the size of a variable of type T.
	// Sizeof must implement the size guarantees required by the spec.
	Sizeof(T Type) int64
}

// StdSizes is a convenience type for creating commonly used Sizes.
// It makes the following simplifying assumptions:
//
//	- The size of explicitly sized basic types (int16, etc.) is the
//	  specified size.
//	- The size of strings and interfaces is 2*WordSize.
//	- The size of slices is 3*WordSize.
//	- All other types have size WordSize.
//	- Arrays and structs are aligned per spec definition; all other
//	  types are naturally aligned with a maximum alignment MaxAlign.
//
// *StdSizes implements Sizes.
//
type StdSizes struct {
	WordSize int64 // word size in bytes - must be >= 4 (32bits)
	MaxAlign int64 // maximum alignment in bytes - must be >= 1
}

func (s *StdSizes) Alignof(T Type) int64 {
	// For arrays and structs, alignment is defined in terms
	// of alignment of the elements and fields, respectively.
	switch t := T.Underlying().(type) {
	case *Array:
		// spec: "For a variable x of array type: unsafe.Alignof(x)
		// is the same as unsafe.Alignof(x[0]), but at least 1."
		return s.Alignof(t.elem)
	case *Struct:
		// spec: "For a variable x of struct type: unsafe.Alignof(x)
		// is the largest of the values unsafe.Alignof(x.f) for each
		// field f of x, but at least 1."
		max := int64(1)
		for _, f := range t.fields {
			if a := s.Alignof(f.typ); a > max {
				max = a
			}
		}
		return max
	}
	a := s.Sizeof(T) // may be 0
	// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
	if a < 1 {
		return 1
	}
	if a > s.MaxAlign {
		return s.MaxAlign
	}
	return a
}

func (s *StdSizes) Offsetsof(fields []*Var) []int64 {
	offsets := make([]int64, len(fields))
	var o int64
	for i, f := range fields {
		a := s.Alignof(f.typ)
		o = align(o, a)
		offsets[i] = o
		o += s.Sizeof(f.typ)
	}
	return offsets
}

func (s *StdSizes) Sizeof(T Type) int64 {
	switch t := T.Underlying().(type) {
	case *Basic:
		if z := t.size; z > 0 {
			return z
		}
		if t.kind == String {
			return s.WordSize * 2
		}
	case *Array:
		a := s.Alignof(t.elem)
		z := s.Sizeof(t.elem)
		return align(z, a) * t.len // may be 0
	case *Slice:
		return s.WordSize * 3
	case *Struct:
		n := t.NumFields()
		if n == 0 {
			return 0
		}
		offsets := t.offsets
		if t.offsets == nil {
			// compute offsets on demand
			offsets = s.Offsetsof(t.fields)
			t.offsets = offsets
		}
		return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
	case *Interface:
		return s.WordSize * 2
	}
	return s.WordSize // catch-all
}

// stdSizes is used if Config.Sizes == nil.
var stdSizes = StdSizes{8, 8}

func (conf *Config) alignof(T Type) int64 {
	if s := conf.Sizes; s != nil {
		if a := s.Alignof(T); a >= 1 {
			return a
		}
		panic("Config.Sizes.Alignof returned an alignment < 1")
	}
	return stdSizes.Alignof(T)
}

func (conf *Config) offsetsof(T *Struct) []int64 {
	offsets := T.offsets
	if offsets == nil && T.NumFields() > 0 {
		// compute offsets on demand
		if s := conf.Sizes; s != nil {
			offsets = s.Offsetsof(T.fields)
			// sanity checks
			if len(offsets) != T.NumFields() {
				panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
			}
			for _, o := range offsets {
				if o < 0 {
					panic("Config.Sizes.Offsetsof returned an offset < 0")
				}
			}
		} else {
			offsets = stdSizes.Offsetsof(T.fields)
		}
		T.offsets = offsets
	}
	return offsets
}

// offsetof returns the offset of the field specified via
// the index sequence relative to typ. All embedded fields
// must be structs (rather than pointer to structs).
func (conf *Config) offsetof(typ Type, index []int) int64 {
	var o int64
	for _, i := range index {
		s := typ.Underlying().(*Struct)
		o += conf.offsetsof(s)[i]
		typ = s.fields[i].typ
	}
	return o
}

func (conf *Config) sizeof(T Type) int64 {
	if s := conf.Sizes; s != nil {
		if z := s.Sizeof(T); z >= 0 {
			return z
		}
		panic("Config.Sizes.Sizeof returned a size < 0")
	}
	return stdSizes.Sizeof(T)
}

// align returns the smallest y >= x such that y % a == 0.
func align(x, a int64) int64 {
	y := x + a - 1
	return y - y%a
}
<|endoftext|>


<commit_before>package logger

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strconv"
	"sync"
	"time"
)

const (
	_VER string = "1.0.0"
)

type UNIT int64

const (
	_       = iota
	KB UNIT = 1 << (iota * 10)
	MB
	GB
	TB
)

const (
	LOG int = iota
	DEBUG
	INFO
	WARN
	ERROR
	FATAL
)

const (
	OS_LINUX = iota
	OS_X
	OS_WIN
	OS_OTHERS
)

//日志结构对象
var logObj *LogFile
var logLevel = 1
var maxFileSize int64
var maxFileCount int32
var dailyFlag bool
var consoleAppender = false

const (
	//TimeDayFormat 日期格式化到日
	TimeDayFormat = "2006-01-02"
	//TimeFormat 日期格式化到秒
	TimeFormat = "2006-01-02 15:04:05"
)

var logFormat = "%s %s:%d %s %s"
var logObjFormat = "%s %s:%d %s %s %s %s"
var consoleFormat = "%s:%d %s %s"

//SetConsole 设置终端是否显示
func SetConsole(isConsole bool) {
	consoleAppender = isConsole
}

//SetLevel 设置日子级别
func SetLevel(_level int) {
	logLevel = _level
}

//RollingLogger 生成按文件大小及数量分割日子类
func RollingLogger(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
	rollingLogger(fileDir, fileName, maxNumber, maxSize, _unit)
}

//SetRollingFile 生成按文件大小及数量分割日子类
func SetRollingFile(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
	rollingLogger(fileDir, fileName, maxNumber, maxSize, _unit)
}

func rollingLogger(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
	maxFileCount = maxNumber
	maxFileSize = maxSize * int64(_unit)
	dailyFlag = false
	logObj = &LogFile{dir: fileDir, filename: fileName, mu: new(sync.Mutex)}
	logObj.mu.Lock()
	defer logObj.mu.Unlock()

	logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0777)
	fi, err := logObj.logfile.Stat()
	if err != nil {
		log.Println(err.Error())
		return
	}
	logObj.filesize = fi.Size()
}

//DailyLogger new按日期分割日子类
func DailyLogger(fileDir, filename string) {
	dailyLogger(fileDir, filename)
}

func dailyLogger(fileDir, fileName string) {
	dailyFlag = true
	t, _ := time.Parse(TimeDayFormat, time.Now().Format(TimeDayFormat))
	logObj = &LogFile{dir: fileDir, filename: fileName, _date: &t, mu: new(sync.Mutex)}
	logObj.mu.Lock()
	defer logObj.mu.Unlock()

	if !logObj.isMustRename() {
		var err error
		logObj.logfile, err = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0777)
		if err != nil {
			log.Println(err.Error())
		}
	} else {
		logObj.rename()
	}
}

func concat(delimiter string, input ...interface{}) string {
	buffer := bytes.Buffer{}
	l := len(input)
	for i := 0; i < l; i++ {
		buffer.WriteString(fmt.Sprint(input[i]))
		if i < l-1 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String()
}

func console(msg string) {
	if logObj == nil || logObj.logfile == nil || consoleAppender {
		log.Print(msg)
	}
}

func buildJSONMessage(level int, l *LogObj, msg string) string {
	file, line := getTraceFileLine()
	logInfo := map[string]interface{}{"atime": time.Now().Format(TimeFormat), "bfile": file + " " + strconv.Itoa(line), "clevel": getTraceLevelName(level)}

	if l != nil {
		logInfo["dlogid"] = l.logid
		logInfo["etag"] = l.tag
	}
	logInfo["msg"] = msg
	resb, err := json.Marshal(logInfo)
	if err != nil {
		log.Println(err.Error())
		return ""
	}
	return string(resb) + getOsEol()
}

func buildLogMessage(level int, l *LogObj, msg string) string {
	file, line := getTraceFileLine()
	logInfo := ""
	if l == nil {
		logInfo = fmt.Sprintf(logFormat+getOsEol(), time.Now().Format(TimeFormat), file, line, getTraceLevelName(level), msg)
	} else {
		logInfo = fmt.Sprintf(logObjFormat+getOsEol(), time.Now().Format(TimeFormat), file, line, l.logid, l.tag, getTraceLevelName(level), msg)
	}
	return logInfo
}

func catchError() {
	if err := recover(); err != nil {
		log.Println("err", err)
	}
}

//Trace write
func Trace(level int, l *LogObj, v ...interface{}) bool {
	defer catchError()
	if logObj != nil {
		logObj.mu.Lock()
		defer logObj.mu.Unlock()
	}
	msg := concat(" ", v...)
	logStr := ""
	if l.json {
		logStr = buildJSONMessage(level, l, msg)
	} else {
		logStr = buildLogMessage(level, l, msg)
	}
	console(logStr)
	if v[0] != nil && v[0].(string) == "remote" {
		remoteMsg := concat(" ", v[1:]...)
		go httpLog(remoteMsg)
	}
	if level >= logLevel {
		if logObj != nil {
			_, err := logObj.write([]byte(logStr))
			if err != nil {
				log.Println(err.Error())
				return false
			}
		}
	}
	return true
}

//Log LOG
func Log(v ...interface{}) bool {
	return Trace(LOG, nil, v...)
}

//Debug DEBUG
func Debug(v ...interface{}) bool {
	return Trace(DEBUG, nil, v...)
}

//Info INFO
func Info(v ...interface{}) bool {
	return Trace(INFO, nil, v...)
}

//Warn WARN
func Warn(v ...interface{}) bool {
	return Trace(WARN, nil, v...)
}

//Error ERROR
func Error(v ...interface{}) bool {
	return Trace(ERROR, nil, v...)
}

//Fatal FATAL
func Fatal(v ...interface{}) bool {
	return Trace(FATAL, nil, v...)
}
<commit_msg>modify nil pointer when write log<commit_after>package logger

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strconv"
	"sync"
	"time"
)

const (
	_VER string = "1.0.0"
)

type UNIT int64

const (
	_       = iota
	KB UNIT = 1 << (iota * 10)
	MB
	GB
	TB
)

const (
	LOG int = iota
	DEBUG
	INFO
	WARN
	ERROR
	FATAL
)

const (
	OS_LINUX = iota
	OS_X
	OS_WIN
	OS_OTHERS
)

//日志结构对象
var logObj *LogFile
var logLevel = 1
var maxFileSize int64
var maxFileCount int32
var dailyFlag bool
var consoleAppender = false

const (
	//TimeDayFormat 日期格式化到日
	TimeDayFormat = "2006-01-02"
	//TimeFormat 日期格式化到秒
	TimeFormat = "2006-01-02 15:04:05"
)

var logFormat = "%s %s:%d %s %s"
var logObjFormat = "%s %s:%d %s %s %s %s"
var consoleFormat = "%s:%d %s %s"

//SetConsole 设置终端是否显示
func SetConsole(isConsole bool) {
	consoleAppender = isConsole
}

//SetLevel 设置日子级别
func SetLevel(_level int) {
	logLevel = _level
}

//RollingLogger 生成按文件大小及数量分割日子类
func RollingLogger(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
	rollingLogger(fileDir, fileName, maxNumber, maxSize, _unit)
}

//SetRollingFile 生成按文件大小及数量分割日子类
func SetRollingFile(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
	rollingLogger(fileDir, fileName, maxNumber, maxSize, _unit)
}

func rollingLogger(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
	maxFileCount = maxNumber
	maxFileSize = maxSize * int64(_unit)
	dailyFlag = false
	logObj = &LogFile{dir: fileDir, filename: fileName, mu: new(sync.Mutex)}
	logObj.mu.Lock()
	defer logObj.mu.Unlock()

	logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0777)
	fi, err := logObj.logfile.Stat()
	if err != nil {
		log.Println(err.Error())
		return
	}
	logObj.filesize = fi.Size()
}

//DailyLogger new按日期分割日子类
func DailyLogger(fileDir, filename string) {
	dailyLogger(fileDir, filename)
}

func dailyLogger(fileDir, fileName string) {
	dailyFlag = true
	t, _ := time.Parse(TimeDayFormat, time.Now().Format(TimeDayFormat))
	logObj = &LogFile{dir: fileDir, filename: fileName, _date: &t, mu: new(sync.Mutex)}
	logObj.mu.Lock()
	defer logObj.mu.Unlock()

	if !logObj.isMustRename() {
		var err error
		logObj.logfile, err = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0777)
		if err != nil {
			log.Println(err.Error())
		}
	} else {
		logObj.rename()
	}
}

func concat(delimiter string, input ...interface{}) string {
	buffer := bytes.Buffer{}
	l := len(input)
	for i := 0; i < l; i++ {
		buffer.WriteString(fmt.Sprint(input[i]))
		if i < l-1 {
			buffer.WriteString(delimiter)
		}
	}
	return buffer.String()
}

func console(msg string) {
	if logObj == nil || logObj.logfile == nil || consoleAppender {
		log.Print(msg)
	}
}

func buildJSONMessage(level int, l *LogObj, msg string) string {
	file, line := getTraceFileLine()
	logInfo := map[string]interface{}{"atime": time.Now().Format(TimeFormat), "bfile": file + " " + strconv.Itoa(line), "clevel": getTraceLevelName(level)}

	if l != nil {
		logInfo["dlogid"] = l.logid
		logInfo["etag"] = l.tag
	}
	logInfo["msg"] = msg
	resb, err := json.Marshal(logInfo)
	if err != nil {
		log.Println(err.Error())
		return ""
	}
	return string(resb) + getOsEol()
}

func buildLogMessage(level int, l *LogObj, msg string) string {
	file, line := getTraceFileLine()
	logInfo := ""
	if l == nil {
		logInfo = fmt.Sprintf(logFormat+getOsEol(), time.Now().Format(TimeFormat), file, line, getTraceLevelName(level), msg)
	} else {
		logInfo = fmt.Sprintf(logObjFormat+getOsEol(), time.Now().Format(TimeFormat), file, line, l.logid, l.tag, getTraceLevelName(level), msg)
	}
	return logInfo
}

func catchError() {
	if err := recover(); err != nil {
		log.Println("err", err)
	}
}

//Trace write
func Trace(level int, l *LogObj, v ...interface{}) bool {
	defer catchError()
	if logObj != nil {
		logObj.mu.Lock()
		defer logObj.mu.Unlock()
	}
	msg := concat(" ", v...)
	logStr := ""
	if l != nil && l.json {
		logStr = buildJSONMessage(level, l, msg)
	} else {
		logStr = buildLogMessage(level, l, msg)
	}
	console(logStr)
	if v[0] != nil && v[0].(string) == "remote" {
		remoteMsg := concat(" ", v[1:]...)
		go httpLog(remoteMsg)
	}
	if level >= logLevel {
		if logObj != nil {
			_, err := logObj.write([]byte(logStr))
			if err != nil {
				log.Println(err.Error())
				return false
			}
		}
	}
	return true
}

//Log LOG
func Log(v ...interface{}) bool {
	return Trace(LOG, nil, v...)
}

//Debug DEBUG
func Debug(v ...interface{}) bool {
	return Trace(DEBUG, nil, v...)
}

//Info INFO
func Info(v ...interface{}) bool {
	return Trace(INFO, nil, v...)
}

//Warn WARN
func Warn(v ...interface{}) bool {
	return Trace(WARN, nil, v...)
}

//Error ERROR
func Error(v ...interface{}) bool {
	return Trace(ERROR, nil, v...)
}

//Fatal FATAL
func Fatal(v ...interface{}) bool {
	return Trace(FATAL, nil, v...)
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 backup_test

import (
	"github.com/jacobsa/comeback/backup"
	"github.com/jacobsa/comeback/backup/mock"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/blob/mock"
	"github.com/jacobsa/comeback/fs/mock"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestDirectoryRestorer(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type DirectoryRestorerTest struct {
	blobStore    mock_blob.MockStore
	fileSystem   mock_fs.MockFileSystem
	fileRestorer mock_backup.MockFileRestorer
	wrapped      mock_backup.MockDirectoryRestorer

	dirRestorer backup.DirectoryRestorer

	score    blob.Score
	basePath string
	relPath  string

	err error
}

func init() { RegisterTestSuite(&DirectoryRestorerTest{}) }

func (t *DirectoryRestorerTest) SetUp(i *TestInfo) {
	var err error

	// Create dependencies.
	t.blobStore = mock_blob.NewMockStore(i.MockController, "blobStore")
	t.fileSystem = mock_fs.NewMockFileSystem(i.MockController, "fileSystem")
	t.fileRestorer = mock_backup.NewMockFileRestorer(i.MockController, "fileRestorer")
	t.wrapped = mock_backup.NewMockDirectoryRestorer(i.MockController, "wrapped")

	// Create restorer.
	t.dirRestorer, err = backup.NewNonRecursiveDirectoryRestorer(
		t.blobStore,
		t.fileSystem,
		t.fileRestorer,
		t.wrapped,
	)

	AssertEq(nil, err)
}

func (t *DirectoryRestorerTest) call() {
	t.err = t.dirRestorer.RestoreDirectory(t.score, t.basePath, t.relPath)
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *DirectoryRestorerTest) CallsBlobStore() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) BlobStoreReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) BlobStoreReturnsJunk() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) NoEntries() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_CallsLinkForHardLink() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_LinkReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_LinkSucceeds() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_CallsRestoreFile() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_RestoreFileReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_ZeroScores() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_TwoScores() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_CallsMkdir() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_MkdirReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_CallsWrapped() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_WrappedReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) SymlinkEntry_CallsSymlink() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) SymlinkEntry_SymlinkReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) PipeEntry_CallsCreate() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) PipeEntry_CreateReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) BlockDevEntry_CallsCreate() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) BlockDevEntry_CreateReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) CharDevEntry_CallsCreate() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) CharDevEntry_CreateReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) CallsChown() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) ChownReturnsErrorForOneEntry() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) CallsSetModTime() {
	ExpectEq("TODO", "")
	// NOTE: Not for devices (see restore.go)
}

func (t *DirectoryRestorerTest) SetModTimeReturnsErrorForOneEntry() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) EverythingSucceeds() {
	ExpectEq("TODO", "")
}
<commit_msg>DirectoryRestorerTest.CallsBlobStore<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 backup_test

import (
	"errors"
	"github.com/jacobsa/comeback/backup"
	"github.com/jacobsa/comeback/backup/mock"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/blob/mock"
	"github.com/jacobsa/comeback/fs/mock"
	. "github.com/jacobsa/oglematchers"
	"github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
	"testing"
)

func TestDirectoryRestorer(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type DirectoryRestorerTest struct {
	blobStore    mock_blob.MockStore
	fileSystem   mock_fs.MockFileSystem
	fileRestorer mock_backup.MockFileRestorer
	wrapped      mock_backup.MockDirectoryRestorer

	dirRestorer backup.DirectoryRestorer

	score    blob.Score
	basePath string
	relPath  string

	err error
}

func init() { RegisterTestSuite(&DirectoryRestorerTest{}) }

func (t *DirectoryRestorerTest) SetUp(i *TestInfo) {
	var err error

	// Create dependencies.
	t.blobStore = mock_blob.NewMockStore(i.MockController, "blobStore")
	t.fileSystem = mock_fs.NewMockFileSystem(i.MockController, "fileSystem")
	t.fileRestorer = mock_backup.NewMockFileRestorer(i.MockController, "fileRestorer")
	t.wrapped = mock_backup.NewMockDirectoryRestorer(i.MockController, "wrapped")

	// Create restorer.
	t.dirRestorer, err = backup.NewNonRecursiveDirectoryRestorer(
		t.blobStore,
		t.fileSystem,
		t.fileRestorer,
		t.wrapped,
	)

	AssertEq(nil, err)
}

func (t *DirectoryRestorerTest) call() {
	t.err = t.dirRestorer.RestoreDirectory(t.score, t.basePath, t.relPath)
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *DirectoryRestorerTest) CallsBlobStore() {
	t.score = []byte("taco")

	// Blob store
	ExpectCall(t.blobStore, "Load")(DeepEquals(t.score)).
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Call
	t.call()
}

func (t *DirectoryRestorerTest) BlobStoreReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) BlobStoreReturnsJunk() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) NoEntries() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_CallsLinkForHardLink() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_LinkReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_LinkSucceeds() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_CallsRestoreFile() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) FileEntry_RestoreFileReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_ZeroScores() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_TwoScores() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_CallsMkdir() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_MkdirReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_CallsWrapped() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) DirEntry_WrappedReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) SymlinkEntry_CallsSymlink() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) SymlinkEntry_SymlinkReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) PipeEntry_CallsCreate() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) PipeEntry_CreateReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) BlockDevEntry_CallsCreate() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) BlockDevEntry_CreateReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) CharDevEntry_CallsCreate() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) CharDevEntry_CreateReturnsError() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) CallsChown() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) ChownReturnsErrorForOneEntry() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) CallsSetModTime() {
	ExpectEq("TODO", "")
	// NOTE: Not for devices (see restore.go)
}

func (t *DirectoryRestorerTest) SetModTimeReturnsErrorForOneEntry() {
	ExpectEq("TODO", "")
}

func (t *DirectoryRestorerTest) EverythingSucceeds() {
	ExpectEq("TODO", "")
}
<|endoftext|>


<commit_before>package ln

import (
	"fmt"
	"os"
	"time"
)

// Priority represents the importance of an Event.
type Priority int

const (
	// PriEmergency is the emergency priority, and is the highest.
	PriEmergency Priority = iota
	// PriAlert is the alert priority
	PriAlert
	// PriCritical is the critical priority
	PriCritical
	// PriError is the error priority.
	PriError
	// PriWarning is the warning priority
	PriWarning
	// PriNotice is the notice priority
	PriNotice
	// PriInfo is the info priority
	PriInfo
	// PriDebug is the debug priority.
	PriDebug
)

var priStrings = []string{
	"emerg",
	"alert",
	"crit",
	"error",
	"warn",
	"notice",
	"info",
	"debug",
}

func (p Priority) String() string {
	if int(p) < len(priStrings) {
		return priStrings[p]
	}

	return "UNKNOWN"
}

// Logger holds the current priority and list of filters
type Logger struct {
	Pri     Priority
	Filters []Filter
}

// DefaultLogger is the default implementation of Logger
var DefaultLogger *Logger

func init() {
	var defaultFilters []Filter

	// Default to STDOUT for logging, but allow LN_OUT to change it.
	out := os.Stdout
	if os.Getenv("LN_OUT") == "<stderr>" {
		out = os.Stderr
	}

	// Default to INFO for the level, but allow LN_PRI to change it.
	pri := PriInfo
	if lnPri := os.Getenv("LN_PRI"); lnPri != "" {
		for idx, p := range priStrings {
			if p == lnPri {
				pri = Priority(idx)
			}
		}
	}

	defaultFilters = append(defaultFilters, NewWriterFilter(out, nil))

	DefaultLogger = &Logger{
		Pri:     pri,
		Filters: defaultFilters,
	}

}

// F is a key-value mapping for structured data.
type F map[string]interface{}

// Event represents an event
type Event struct {
	Pri     Priority
	Time    time.Time
	Data    F
	Message string
}

// Log is the generic logging method.
func (l *Logger) Log(p Priority, xs ...interface{}) {
	if l.Pri < p {
		return // don't log
	}

	var bits []interface{}
	event := Event{Pri: p, Time: time.Now()}

	// Assemble the event
	for _, b := range xs {
		switch b.(type) {
		case F:
			bf := b.(F)
			if event.Data == nil {
				event.Data = bf
			} else {
				for k, v := range bf {
					event.Data[k] = v
				}
			}
		default:
			bits = append(bits, b)
		}
	}

	event.Message = fmt.Sprint(bits...)

	if l.Pri == PriDebug {
		frame := callersFrame()
		event.Data["_lineno"] = frame.lineno
		event.Data["_function"] = frame.function
		event.Data["_filename"] = frame.filename
	}

	l.filter(event)
}

func (l *Logger) filter(e Event) {
	for _, f := range l.Filters {
		if !f.Apply(e) {
			return
		}
	}
}

// Emergency sets the priority of this event to PriEmergency
func (l *Logger) Emergency(xs ...interface{}) {
	l.Log(PriEmergency, xs...)
}

// Alert sets the priority of this event to PriAlert
func (l *Logger) Alert(xs ...interface{}) {
	l.Log(PriAlert, xs...)
}

// Critical sets the priority of this event to PriCritical
func (l *Logger) Critical(xs ...interface{}) {
	l.Log(PriCritical, xs...)
}

// Error sets the priority of this event to PriError
func (l *Logger) Error(xs ...interface{}) {
	l.Log(PriError, xs...)
}

// Warning sets the priority of this event to PriWarning
func (l *Logger) Warning(xs ...interface{}) {
	l.Log(PriWarning, xs...)
}

// Notice sets the priority of this event to PriNotice
func (l *Logger) Notice(xs ...interface{}) {
	l.Log(PriNotice, xs...)
}

// Info sets the priority of this event to PriInfo
func (l *Logger) Info(xs ...interface{}) {
	l.Log(PriInfo, xs...)
}

// Debug sets the priority of this event to PriDebug
func (l *Logger) Debug(xs ...interface{}) {
	l.Log(PriDebug, xs...)
}

// Default Implementation

// Emergency sets the priority of this event to PriEmergency
func Emergency(xs ...interface{}) {
	DefaultLogger.Log(PriEmergency, xs...)
}

// Alert sets the priority of this event to PriAlert
func Alert(xs ...interface{}) {
	DefaultLogger.Log(PriAlert, xs...)
}

// Critical sets the priority of this event to PriCritical
func Critical(xs ...interface{}) {
	DefaultLogger.Log(PriCritical, xs...)
}

// Error sets the priority of this event to PriError
func Error(xs ...interface{}) {
	DefaultLogger.Log(PriError, xs...)
}

// Warning sets the priority of this event to PriWarning
func Warning(xs ...interface{}) {
	DefaultLogger.Log(PriWarning, xs...)
}

// Notice sets the priority of this event to PriNotice
func Notice(xs ...interface{}) {
	DefaultLogger.Log(PriNotice, xs...)
}

// Info sets the priority of this event to PriInfo
func Info(xs ...interface{}) {
	DefaultLogger.Log(PriInfo, xs...)
}

// Debug sets the priority of this event to PriDebug
func Debug(xs ...interface{}) {
	DefaultLogger.Log(PriDebug, xs...)
}
<commit_msg>panic! when event's data is nil.<commit_after>package ln

import (
	"fmt"
	"os"
	"time"
)

// Priority represents the importance of an Event.
type Priority int

const (
	// PriEmergency is the emergency priority, and is the highest.
	PriEmergency Priority = iota
	// PriAlert is the alert priority
	PriAlert
	// PriCritical is the critical priority
	PriCritical
	// PriError is the error priority.
	PriError
	// PriWarning is the warning priority
	PriWarning
	// PriNotice is the notice priority
	PriNotice
	// PriInfo is the info priority
	PriInfo
	// PriDebug is the debug priority.
	PriDebug
)

var priStrings = []string{
	"emerg",
	"alert",
	"crit",
	"error",
	"warn",
	"notice",
	"info",
	"debug",
}

func (p Priority) String() string {
	if int(p) < len(priStrings) {
		return priStrings[p]
	}

	return "UNKNOWN"
}

// Logger holds the current priority and list of filters
type Logger struct {
	Pri     Priority
	Filters []Filter
}

// DefaultLogger is the default implementation of Logger
var DefaultLogger *Logger

func init() {
	var defaultFilters []Filter

	// Default to STDOUT for logging, but allow LN_OUT to change it.
	out := os.Stdout
	if os.Getenv("LN_OUT") == "<stderr>" {
		out = os.Stderr
	}

	// Default to INFO for the level, but allow LN_PRI to change it.
	pri := PriInfo
	if lnPri := os.Getenv("LN_PRI"); lnPri != "" {
		for idx, p := range priStrings {
			if p == lnPri {
				pri = Priority(idx)
			}
		}
	}

	defaultFilters = append(defaultFilters, NewWriterFilter(out, nil))

	DefaultLogger = &Logger{
		Pri:     pri,
		Filters: defaultFilters,
	}

}

// F is a key-value mapping for structured data.
type F map[string]interface{}

// Event represents an event
type Event struct {
	Pri     Priority
	Time    time.Time
	Data    F
	Message string
}

// Log is the generic logging method.
func (l *Logger) Log(p Priority, xs ...interface{}) {
	if l.Pri < p {
		return // don't log
	}

	var bits []interface{}
	event := Event{Pri: p, Time: time.Now()}

	// Assemble the event
	for _, b := range xs {
		switch b.(type) {
		case F:
			bf := b.(F)
			if event.Data == nil {
				event.Data = bf
			} else {
				for k, v := range bf {
					event.Data[k] = v
				}
			}
		default:
			bits = append(bits, b)
		}
	}

	event.Message = fmt.Sprint(bits...)

	if l.Pri == PriDebug {
		frame := callersFrame()
		if event.Data == nil {
			event.Data = make(F)
		}
		event.Data["_lineno"] = frame.lineno
		event.Data["_function"] = frame.function
		event.Data["_filename"] = frame.filename
	}

	l.filter(event)
}

func (l *Logger) filter(e Event) {
	for _, f := range l.Filters {
		if !f.Apply(e) {
			return
		}
	}
}

// Emergency sets the priority of this event to PriEmergency
func (l *Logger) Emergency(xs ...interface{}) {
	l.Log(PriEmergency, xs...)
}

// Alert sets the priority of this event to PriAlert
func (l *Logger) Alert(xs ...interface{}) {
	l.Log(PriAlert, xs...)
}

// Critical sets the priority of this event to PriCritical
func (l *Logger) Critical(xs ...interface{}) {
	l.Log(PriCritical, xs...)
}

// Error sets the priority of this event to PriError
func (l *Logger) Error(xs ...interface{}) {
	l.Log(PriError, xs...)
}

// Warning sets the priority of this event to PriWarning
func (l *Logger) Warning(xs ...interface{}) {
	l.Log(PriWarning, xs...)
}

// Notice sets the priority of this event to PriNotice
func (l *Logger) Notice(xs ...interface{}) {
	l.Log(PriNotice, xs...)
}

// Info sets the priority of this event to PriInfo
func (l *Logger) Info(xs ...interface{}) {
	l.Log(PriInfo, xs...)
}

// Debug sets the priority of this event to PriDebug
func (l *Logger) Debug(xs ...interface{}) {
	l.Log(PriDebug, xs...)
}

// Default Implementation

// Emergency sets the priority of this event to PriEmergency
func Emergency(xs ...interface{}) {
	DefaultLogger.Log(PriEmergency, xs...)
}

// Alert sets the priority of this event to PriAlert
func Alert(xs ...interface{}) {
	DefaultLogger.Log(PriAlert, xs...)
}

// Critical sets the priority of this event to PriCritical
func Critical(xs ...interface{}) {
	DefaultLogger.Log(PriCritical, xs...)
}

// Error sets the priority of this event to PriError
func Error(xs ...interface{}) {
	DefaultLogger.Log(PriError, xs...)
}

// Warning sets the priority of this event to PriWarning
func Warning(xs ...interface{}) {
	DefaultLogger.Log(PriWarning, xs...)
}

// Notice sets the priority of this event to PriNotice
func Notice(xs ...interface{}) {
	DefaultLogger.Log(PriNotice, xs...)
}

// Info sets the priority of this event to PriInfo
func Info(xs ...interface{}) {
	DefaultLogger.Log(PriInfo, xs...)
}

// Debug sets the priority of this event to PriDebug
func Debug(xs ...interface{}) {
	DefaultLogger.Log(PriDebug, xs...)
}
<|endoftext|>


<commit_before>package jshapi

import (
	"log"
	"net/http"
	"os"

	"golang.org/x/net/context"

	"github.com/derekdowling/go-json-spec-handler"
	"github.com/derekdowling/go-stdlogger"
)

// ILogger is the default standard logger used in JSH API:
// https://godoc.org/github.com/derekdowling/goji2-logger#Logger
// This should be compatible with almost all loggers including the std log package
// and Logrus.
type ILogger std.Logger

// Logger can be overridden with your own logger to utilize any custom features
// it might have
var Logger ILogger = log.New(os.Stderr, "jshapi: ", log.LstdFlags)

// SendAndLog is a jsh wrapper function that first prepares a jsh.Sendable response,
// and then handles logging 5XX errors that it encounters in the process.
func SendAndLog(ctx context.Context, w http.ResponseWriter, r *http.Request, sendable jsh.Sendable) {

	intentionalErr, isType := sendable.(*jsh.Error)
	if isType && intentionalErr.Status() >= 500 {
		Logger.Printf("Returning ISE for: %s", intentionalErr.Internal())
	}

	response, err := sendable.Prepare(r, true)

	if err != nil && response.HTTPStatus >= 500 {
		Logger.Printf("Error preparing response: %s\n", err.Internal())
	}

	sendErr := jsh.SendResponse(w, r, response)
	if sendErr != nil {
		Logger.Println(err.Error())
	}
}
<commit_msg>Removing weird sub-type<commit_after>package jshapi

import (
	"log"
	"net/http"
	"os"

	"golang.org/x/net/context"

	"github.com/derekdowling/go-json-spec-handler"
	"github.com/derekdowling/go-stdlogger"
)

// Logger can be overridden with your own logger to utilize any custom features
// it might have. Interface defined here: https://github.com/derekdowling/go-stdlogger/blob/master/logger.go
var Logger std.Logger = log.New(os.Stderr, "jshapi: ", log.LstdFlags)

// SendAndLog is a jsh wrapper function that first prepares a jsh.Sendable response,
// and then handles logging 5XX errors that it encounters in the process.
func SendAndLog(ctx context.Context, w http.ResponseWriter, r *http.Request, sendable jsh.Sendable) {

	intentionalErr, isType := sendable.(*jsh.Error)
	if isType && intentionalErr.Status() >= 500 {
		Logger.Printf("Returning ISE for: %s", intentionalErr.Internal())
	}

	response, err := sendable.Prepare(r, true)

	if err != nil && response.HTTPStatus >= 500 {
		Logger.Printf("Error preparing response: %s\n", err.Internal())
	}

	sendErr := jsh.SendResponse(w, r, response)
	if sendErr != nil {
		Logger.Println(err.Error())
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2011 Google Inc.

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 localdisk

import (
	"fmt"
	"os"
	"sort"
	"strings"
	"time"

	"camli/blobref"
)

type readBlobRequest struct {
	ch      chan<- blobref.SizedBlobRef
	after   string
	remain  *uint // limit countdown
	dirRoot string

	// Not used on initial request, only on recursion
	blobPrefix, pathInto string
}

type enumerateError struct {
	msg string
	err os.Error
}

func (ee *enumerateError) String() string {
	return fmt.Sprintf("Enumerate error: %s: %v", ee.msg, ee.err)
}

func readBlobs(opts readBlobRequest) os.Error {
	dirFullPath := opts.dirRoot + "/" + opts.pathInto
	dir, err := os.Open(dirFullPath)
	if err != nil {
		return &enumerateError{"localdisk: opening directory " + dirFullPath, err}
	}
	defer dir.Close()
	names, err := dir.Readdirnames(32768)
	if err != nil {
		return &enumerateError{"localdisk: readdirnames of " + dirFullPath, err}
	}
	sort.SortStrings(names)
	for _, name := range names {
		if *opts.remain == 0 {
			return nil
		}
		if name == "partition" {
			continue
		}
		fullPath := dirFullPath + "/" + name
		fi, err := os.Stat(fullPath)
		if err != nil {
			return &enumerateError{"localdisk: stat of file " + fullPath, err}
		}

		if fi.IsDirectory() {
			var newBlobPrefix string
			if opts.blobPrefix == "" {
				newBlobPrefix = name + "-"
			} else {
				newBlobPrefix = opts.blobPrefix + name
			}
			if len(opts.after) > 0 {
				compareLen := len(newBlobPrefix)
				if len(opts.after) < compareLen {
					compareLen = len(opts.after)
				}
				if newBlobPrefix[0:compareLen] < opts.after[0:compareLen] {
					continue
				}
			}
			ropts := opts
			ropts.blobPrefix = newBlobPrefix
			ropts.pathInto = opts.pathInto + "/" + name
			readBlobs(ropts)
			continue
		}

		if fi.IsRegular() && strings.HasSuffix(name, ".dat") {
			blobName := name[0 : len(name)-4]
			if blobName <= opts.after {
				continue
			}
			blobRef := blobref.Parse(blobName)
			if blobRef != nil {
				opts.ch <- blobref.SizedBlobRef{BlobRef: blobRef, Size: fi.Size}
				(*opts.remain)--
			}
			continue
		}
	}

	return nil
}

func (ds *DiskStorage) EnumerateBlobs(dest chan<- blobref.SizedBlobRef, after string, limit uint, waitSeconds int) os.Error {
	dirRoot := ds.PartitionRoot(ds.partition)
	limitMutable := limit
	var err os.Error
	doScan := func() {
		err = readBlobs(readBlobRequest{
			ch:      dest,
			dirRoot: dirRoot,
			after:   after,
			remain:  &limitMutable,
		})
	}
	doScan()

	// The not waiting case:
	if err != nil || limitMutable != limit || waitSeconds == 0 {
		close(dest)
		return err
	}

	// The case where we have to wait for waitSeconds for any blob
	// to possibly appear.
	hub := ds.GetBlobHub()
	ch := make(chan *blobref.BlobRef, 1)
	hub.RegisterListener(ch)
	defer hub.UnregisterListener(ch)
	timer := time.NewTimer(int64(waitSeconds) * 1e9)
	defer timer.Stop()
	select {
	case <-timer.C:
		// Done waiting.
		return nil
	case <-ch:
		// Don't actually care what it is, but _something_
		// arrived.  We can just re-scan.
		// TODO: might be better to just stat this one item
		// so there's no race?  But this is easier:
		doScan()
	}
	close(dest)
	return err
}
<commit_msg>localdisk: use defer to reliably close the channel. missed a case on enumerate timeout before.<commit_after>/*
Copyright 2011 Google Inc.

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 localdisk

import (
	"fmt"
	"os"
	"sort"
	"strings"
	"time"

	"camli/blobref"
)

type readBlobRequest struct {
	ch      chan<- blobref.SizedBlobRef
	after   string
	remain  *uint // limit countdown
	dirRoot string

	// Not used on initial request, only on recursion
	blobPrefix, pathInto string
}

type enumerateError struct {
	msg string
	err os.Error
}

func (ee *enumerateError) String() string {
	return fmt.Sprintf("Enumerate error: %s: %v", ee.msg, ee.err)
}

func readBlobs(opts readBlobRequest) os.Error {
	dirFullPath := opts.dirRoot + "/" + opts.pathInto
	dir, err := os.Open(dirFullPath)
	if err != nil {
		return &enumerateError{"localdisk: opening directory " + dirFullPath, err}
	}
	defer dir.Close()
	names, err := dir.Readdirnames(32768)
	if err != nil {
		return &enumerateError{"localdisk: readdirnames of " + dirFullPath, err}
	}
	sort.SortStrings(names)
	for _, name := range names {
		if *opts.remain == 0 {
			return nil
		}
		if name == "partition" {
			continue
		}
		fullPath := dirFullPath + "/" + name
		fi, err := os.Stat(fullPath)
		if err != nil {
			return &enumerateError{"localdisk: stat of file " + fullPath, err}
		}

		if fi.IsDirectory() {
			var newBlobPrefix string
			if opts.blobPrefix == "" {
				newBlobPrefix = name + "-"
			} else {
				newBlobPrefix = opts.blobPrefix + name
			}
			if len(opts.after) > 0 {
				compareLen := len(newBlobPrefix)
				if len(opts.after) < compareLen {
					compareLen = len(opts.after)
				}
				if newBlobPrefix[0:compareLen] < opts.after[0:compareLen] {
					continue
				}
			}
			ropts := opts
			ropts.blobPrefix = newBlobPrefix
			ropts.pathInto = opts.pathInto + "/" + name
			readBlobs(ropts)
			continue
		}

		if fi.IsRegular() && strings.HasSuffix(name, ".dat") {
			blobName := name[0 : len(name)-4]
			if blobName <= opts.after {
				continue
			}
			blobRef := blobref.Parse(blobName)
			if blobRef != nil {
				opts.ch <- blobref.SizedBlobRef{BlobRef: blobRef, Size: fi.Size}
				(*opts.remain)--
			}
			continue
		}
	}

	return nil
}

func (ds *DiskStorage) EnumerateBlobs(dest chan<- blobref.SizedBlobRef, after string, limit uint, waitSeconds int) os.Error {
	defer close(dest)

	dirRoot := ds.PartitionRoot(ds.partition)
	limitMutable := limit
	var err os.Error
	doScan := func() {
		err = readBlobs(readBlobRequest{
			ch:      dest,
			dirRoot: dirRoot,
			after:   after,
			remain:  &limitMutable,
		})
	}
	doScan()

	// The not waiting case:
	if err != nil || limitMutable != limit || waitSeconds == 0 {
		return err
	}

	// The case where we have to wait for waitSeconds for any blob
	// to possibly appear.
	hub := ds.GetBlobHub()
	ch := make(chan *blobref.BlobRef, 1)
	hub.RegisterListener(ch)
	defer hub.UnregisterListener(ch)
	timer := time.NewTimer(int64(waitSeconds) * 1e9)
	defer timer.Stop()
	select {
	case <-timer.C:
		// Done waiting.
		return nil
	case <-ch:
		// Don't actually care what it is, but _something_
		// arrived.  We can just re-scan.
		// TODO: might be better to just stat this one item
		// so there's no race?  But this is easier:
		doScan()
	}
	return err
}
<|endoftext|>