<commit_before>// Package ircudf implements parts of the Internet Realy Chat (IRC) protocol
// as defined in rfc1459 (http://tools.ietf.org/html/rfc1459.html)
// and provides basic IRC functions
package ircudf

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"strconv"
	"strings"
	"time"
)

type Server struct { // IRC Server
	Server    string        // Server address
	sendqueue chan string   // Message queue
	conn      net.Conn      // Server connection
	throttle  time.Duration // Throttle for message queue

	Nickname string // User Nickname
	username string // User username
	realname string // User realname

	kill chan bool // kills all routines when closed
}

var Debug = false // Debug enables logging to stdout

var ( // Events can be changed to custom functions
	eventOnJoin    = func(*Server, string, string) {}         // server, channel, user
	eventOnPart    = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnQuit    = func(*Server, string, string) {}         // server, user, message
	eventOnPrivmsg = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnNotice  = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnReply   = func(*Server, string, string, string) {} // server, number, name, reply
)

// Create sets the Server address and user information.
//	// Example: (Nickname!Username@Hostname): Real Name
// 	freenode := ircudf.Create("irc.freenode.org:6667", "Nickname", "Username, "Real Name")
func Create(addr, Nickname, username, realname string) *Server {
	ref := &Server{Server: addr, sendqueue: make(chan string),
		Nickname: Nickname, username: username, realname: realname,
		throttle: 0, kill: make(chan bool)}

	debug("Created: ", addr, "\n")
	return ref
}

// close closes the server related routines.
func (sock *Server) close() {
	close(sock.kill)
}

// Connect establishes a connection to the Server.
// If no parameter is given the default timeout (5 sec) will be used.
func (sock *Server) Connect(timeout ...int) error {
	wait := 5 * time.Second
	if len(timeout) >= 1 {
		wait = time.Duration(timeout[0]) * time.Second
	}

	conn, err := net.DialTimeout("tcp", sock.Server, wait)
	if err != nil {
		sock.close()
		return err
	}
	defer conn.Close()
	sock.conn = conn

	debug("Connected: ", sock.Server, "\n")
	err = sock.receive()
	if err != nil {
		sock.close()
	}
	return err
}

// Receive receives new messages from the Server and forwards them to parse().
func (sock *Server) receive() error {
	go func() {
		time.Sleep(time.Second)
		sock.Nick(sock.Nickname)
		sock.user(sock.username, "0", "0", sock.realname)
	}()

	debug("Receiving: ", sock.Server, "\n")
	reader := bufio.NewReader(sock.conn)
	sock.sendroutine() //Non-Blocking

	for {
		select {
		case <-sock.kill:
			return nil
		default:
			line, err := reader.ReadString('\n')
			if err != nil {
				return err
			}
			debug("-> ", line)
			sock.parse(strings.Trim(line, "\r\n")) //Remove \r\n for easier parsing
		}
	}
}

// parse parses incoming messages from the Server and triggers predefined events.
func (sock *Server) parse(line string) {
	split := strings.SplitN(line, " ", 4)
	split = append(split, make([]string, 4-len(split), 4-len(split))...)

	switch true {
	case split[0] == "PING":
		sock.pong(split[1]) //Ping e.g.: PING :B97B6379
	case split[1] == "JOIN":
		eventOnJoin(sock, split[2][1:], getNick(split[0]))
	case split[1] == "PART":
		eventOnPart(sock, split[2], getNick(split[0]), split[3][1:])
	case split[1] == "QUIT":
		if split[3] != "" {
			split[2] += " " + split[3]
		}
		eventOnQuit(sock, getNick(split[0]), split[2][1:])
	case split[1] == "PRIVMSG":
		nick := getNick(split[0])
		channel := split[2]
		if channel == sock.Nickname {
			channel = nick
		}
		eventOnPrivmsg(sock, channel, nick, split[3][1:])
	case split[1] == "NOTICE":
		nick := getNick(split[0])
		channel := split[2]
		if channel == sock.Nickname {
			channel = nick
		}
		eventOnNotice(sock, channel, nick, split[3][1:])
	case isNum(split[1]):
		eventOnReply(sock, split[1], split[2], split[3])
	}
}

// Throttle sets the delay between sending messages in milliseconds.
func (sock *Server) Throttle(delay int) {
	sock.throttle = time.Duration(delay) * time.Millisecond
}

// Nick sets or changes the Nickname. The IRC Server might reply an errorcode,
// if the requsted Nickname is not valid or in use.
func (sock *Server) Nick(Nickname string) {
	sock.Nickname = Nickname
	sock.Send("NICK " + Nickname)
}

// user specifies the userdata at the beginning of a new connection.
// Servername and hostname are likely to be ignored by the IRC Server.
// Scheme: (Nickname!Username@Hostname): Real Name
func (sock *Server) user(username, hostname, Servername, realname string) {
	sock.Send("USER " + username + " " + hostname + " " + Servername + " :" + realname)
}

// Join joins the specified channel(s). Multiple channels need to be
// seperated by a colon.
func (sock *Server) Join(channel string) {
	sock.Send("JOIN " + channel)
}

// Part leaves the specified channel(s). Multiple channels need to be
// seperated by a colon.
func (sock *Server) Part(channel string) {
	sock.Send("PART " + channel)
}

// Quit closes the connection to the server with a quit message.
func (sock *Server) Quit(message string) {
	sock.SendWait("QUIT " + message)
	sock.close()
}

// pong answers a ping request with a previously received reply string.
func (sock *Server) pong(reply string) {
	sock.Send("PONG " + reply)
}

// Privmsg sends a private message to a user or a channel.
// The parameter user can also contain multiple receivers seperated by a colon.
func (sock *Server) Privmsg(user string, message string) {
	sock.Send("PRIVMSG " + user + " :" + message)
}

// Notice sends a notice to a user or a channel.
// The parameter user can also contain multiple receivers seperated by a colon.
func (sock *Server) Notice(user string, message string) {
	sock.Send("NOTICE " + user + " :" + message)
}

// Send adds the message to the RAW Message queue
func (sock *Server) Send(message string) {
	go func() {
		select {
		case <-sock.kill:
		case sock.sendqueue <- message + "\n":
		}
	}()
}

// SendWait adds the message to the RAW Message queue and waits until
// the message got sent.
func (sock *Server) SendWait(message string) {
	sock.sendqueue <- message + "\n"
	sock.sendqueue <- "" //ensures that the previous message got sent
}

// sendroutine sends the messages of the queue to the Server.
func (sock *Server) sendroutine() {
	go func() {
		for {
			select {
			case <-sock.kill:
				return
			case smsg := <-sock.sendqueue:
				if smsg != "" {
					io.WriteString(sock.conn, smsg)
					debug("<- ", smsg)
					time.Sleep(sock.throttle)
				}
			}
		}
	}()
}

// getNick extracts the nickame out of an hostmask. This function is
// being used for parsing incoming messages.
func getNick(hostmask string) string {
	return strings.Split(hostmask, "!")[0][1:]
}

// isNum checks wether a string could be represented as integer.
// This function is being used for parsing incoming messages.
func isNum(str string) bool {
	_, err := strconv.Atoi(str)
	return err == nil
}

//HANDLE FUNCTIONS

// HandleJoin registers the handle function for join.
// Handle function parameters: server, channel, user
func HandleJoin(h func(*Server, string, string)) {
	eventOnJoin = h
}

// HandlePart registers the handle function for part.
// Handle function parameters: server, channel, user, message
func HandlePart(h func(*Server, string, string, string)) {
	eventOnPart = h
}

// HandleQuit registers the handle function for quit.
// Handle function parameters: server, user, message
func HandleQuit(h func(*Server, string, string)) {
	eventOnQuit = h
}

// HandlePrivmsg registers the handle function for privmsg.
// Handle function parameters: server, channel, user, message
func HandlePrivmsg(h func(*Server, string, string, string)) {
	eventOnPrivmsg = h
}

// HandleNotice registers the handle function for notice.
// Handle function parameters: server, channel, user, message
func HandleNotice(h func(*Server, string, string, string)) {
	eventOnNotice = h
}

// HandleReply registers the handle function for reply.
// Handle function parameters: server, number, name, reply
func HandleReply(h func(*Server, string, string, string)) {
	eventOnReply = h
}

// DEBUG FUNCTIONS

func debug(s ...interface{}) {
	if Debug {
		fmt.Print(s...)
	}
}
<commit_msg>fixing panic after connection error<commit_after>// Package ircudf implements parts of the Internet Realy Chat (IRC) protocol
// as defined in rfc1459 (http://tools.ietf.org/html/rfc1459.html)
// and provides basic IRC functions
package ircudf

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"strconv"
	"strings"
	"time"
)

type Server struct { // IRC Server
	Server    string        // Server address
	sendqueue chan string   // Message queue
	conn      net.Conn      // Server connection
	throttle  time.Duration // Throttle for message queue

	Nickname string // User Nickname
	username string // User username
	realname string // User realname

	kill chan bool // kills all routines when closed
}

var Debug = false // Debug enables logging to stdout

var ( // Events can be changed to custom functions
	eventOnJoin    = func(*Server, string, string) {}         // server, channel, user
	eventOnPart    = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnQuit    = func(*Server, string, string) {}         // server, user, message
	eventOnPrivmsg = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnNotice  = func(*Server, string, string, string) {} // server, channel, user, message
	eventOnReply   = func(*Server, string, string, string) {} // server, number, name, reply
)

// Create sets the Server address and user information.
//	// Example: (Nickname!Username@Hostname): Real Name
// 	freenode := ircudf.Create("irc.freenode.org:6667", "Nickname", "Username, "Real Name")
func Create(addr, Nickname, username, realname string) *Server {
	ref := &Server{Server: addr, sendqueue: make(chan string),
		Nickname: Nickname, username: username, realname: realname,
		throttle: 0, kill: make(chan bool)}

	debug("Created: ", addr, "\n")
	return ref
}

// close closes the server related routines.
func (sock *Server) close() {
	close(sock.kill)
}

// Connect establishes a connection to the Server.
// If no parameter is given the default timeout (5 sec) will be used.
func (sock *Server) Connect(timeout ...int) error {
	wait := 5 * time.Second
	if len(timeout) >= 1 {
		wait = time.Duration(timeout[0]) * time.Second
	}

	conn, err := net.DialTimeout("tcp", sock.Server, wait)
	if err != nil {
		return err
	}
	defer conn.Close()
	sock.conn = conn

	debug("Connected: ", sock.Server, "\n")
	err = sock.receive()
	if err != nil {
		sock.close()
	}
	return err
}

// Receive receives new messages from the Server and forwards them to parse().
func (sock *Server) receive() error {
	go func() {
		time.Sleep(time.Second)
		sock.Nick(sock.Nickname)
		sock.user(sock.username, "0", "0", sock.realname)
	}()

	debug("Receiving: ", sock.Server, "\n")
	reader := bufio.NewReader(sock.conn)
	sock.sendroutine() //Non-Blocking

	for {
		select {
		case <-sock.kill:
			return nil
		default:
			line, err := reader.ReadString('\n')
			if err != nil {
				return err
			}
			debug("-> ", line)
			sock.parse(strings.Trim(line, "\r\n")) //Remove \r\n for easier parsing
		}
	}
}

// parse parses incoming messages from the Server and triggers predefined events.
func (sock *Server) parse(line string) {
	split := strings.SplitN(line, " ", 4)
	split = append(split, make([]string, 4-len(split), 4-len(split))...)

	switch true {
	case split[0] == "PING":
		sock.pong(split[1]) //Ping e.g.: PING :B97B6379
	case split[1] == "JOIN":
		eventOnJoin(sock, split[2][1:], getNick(split[0]))
	case split[1] == "PART":
		eventOnPart(sock, split[2], getNick(split[0]), split[3][1:])
	case split[1] == "QUIT":
		if split[3] != "" {
			split[2] += " " + split[3]
		}
		eventOnQuit(sock, getNick(split[0]), split[2][1:])
	case split[1] == "PRIVMSG":
		nick := getNick(split[0])
		channel := split[2]
		if channel == sock.Nickname {
			channel = nick
		}
		eventOnPrivmsg(sock, channel, nick, split[3][1:])
	case split[1] == "NOTICE":
		nick := getNick(split[0])
		channel := split[2]
		if channel == sock.Nickname {
			channel = nick
		}
		eventOnNotice(sock, channel, nick, split[3][1:])
	case isNum(split[1]):
		eventOnReply(sock, split[1], split[2], split[3])
	}
}

// Throttle sets the delay between sending messages in milliseconds.
func (sock *Server) Throttle(delay int) {
	sock.throttle = time.Duration(delay) * time.Millisecond
}

// Nick sets or changes the Nickname. The IRC Server might reply an errorcode,
// if the requsted Nickname is not valid or in use.
func (sock *Server) Nick(Nickname string) {
	sock.Nickname = Nickname
	sock.Send("NICK " + Nickname)
}

// user specifies the userdata at the beginning of a new connection.
// Servername and hostname are likely to be ignored by the IRC Server.
// Scheme: (Nickname!Username@Hostname): Real Name
func (sock *Server) user(username, hostname, Servername, realname string) {
	sock.Send("USER " + username + " " + hostname + " " + Servername + " :" + realname)
}

// Join joins the specified channel(s). Multiple channels need to be
// seperated by a colon.
func (sock *Server) Join(channel string) {
	sock.Send("JOIN " + channel)
}

// Part leaves the specified channel(s). Multiple channels need to be
// seperated by a colon.
func (sock *Server) Part(channel string) {
	sock.Send("PART " + channel)
}

// Quit closes the connection to the server with a quit message.
func (sock *Server) Quit(message string) {
	sock.SendWait("QUIT " + message)
	sock.close()
}

// pong answers a ping request with a previously received reply string.
func (sock *Server) pong(reply string) {
	sock.Send("PONG " + reply)
}

// Privmsg sends a private message to a user or a channel.
// The parameter user can also contain multiple receivers seperated by a colon.
func (sock *Server) Privmsg(user string, message string) {
	sock.Send("PRIVMSG " + user + " :" + message)
}

// Notice sends a notice to a user or a channel.
// The parameter user can also contain multiple receivers seperated by a colon.
func (sock *Server) Notice(user string, message string) {
	sock.Send("NOTICE " + user + " :" + message)
}

// Send adds the message to the RAW Message queue
func (sock *Server) Send(message string) {
	go func() {
		select {
		case <-sock.kill:
		case sock.sendqueue <- message + "\n":
		}
	}()
}

// SendWait adds the message to the RAW Message queue and waits until
// the message got sent.
func (sock *Server) SendWait(message string) {
	sock.sendqueue <- message + "\n"
	sock.sendqueue <- "" //ensures that the previous message got sent
}

// sendroutine sends the messages of the queue to the Server.
func (sock *Server) sendroutine() {
	go func() {
		for {
			select {
			case <-sock.kill:
				return
			case smsg := <-sock.sendqueue:
				if smsg != "" {
					io.WriteString(sock.conn, smsg)
					debug("<- ", smsg)
					time.Sleep(sock.throttle)
				}
			}
		}
	}()
}

// getNick extracts the nickame out of an hostmask. This function is
// being used for parsing incoming messages.
func getNick(hostmask string) string {
	return strings.Split(hostmask, "!")[0][1:]
}

// isNum checks wether a string could be represented as integer.
// This function is being used for parsing incoming messages.
func isNum(str string) bool {
	_, err := strconv.Atoi(str)
	return err == nil
}

//HANDLE FUNCTIONS

// HandleJoin registers the handle function for join.
// Handle function parameters: server, channel, user
func HandleJoin(h func(*Server, string, string)) {
	eventOnJoin = h
}

// HandlePart registers the handle function for part.
// Handle function parameters: server, channel, user, message
func HandlePart(h func(*Server, string, string, string)) {
	eventOnPart = h
}

// HandleQuit registers the handle function for quit.
// Handle function parameters: server, user, message
func HandleQuit(h func(*Server, string, string)) {
	eventOnQuit = h
}

// HandlePrivmsg registers the handle function for privmsg.
// Handle function parameters: server, channel, user, message
func HandlePrivmsg(h func(*Server, string, string, string)) {
	eventOnPrivmsg = h
}

// HandleNotice registers the handle function for notice.
// Handle function parameters: server, channel, user, message
func HandleNotice(h func(*Server, string, string, string)) {
	eventOnNotice = h
}

// HandleReply registers the handle function for reply.
// Handle function parameters: server, number, name, reply
func HandleReply(h func(*Server, string, string, string)) {
	eventOnReply = h
}

// DEBUG FUNCTIONS

func debug(s ...interface{}) {
	if Debug {
		fmt.Print(s...)
	}
}
<|endoftext|>


<commit_before>package resources

//Interface of a general resource (ComputeInstance,...)
type Resouce interface {
	ExtractResource(jsonObject interface{})
	CompletePricingInfo()
	PrintPricingInfo()
}

<commit_msg>Update resource.go<commit_after>package resources

//Resource is the interface of a general resource (ComputeInstance,...).
type Resouce interface {
	ExtractResource(jsonResourceInfo interface{})
	CompletePricingInfo()
	PrintPricingInfo()
}

<|endoftext|>


<commit_before>// Package logger provides a logging framework similar to those of python
// and haskell.
package logger

import (
	"errors"
	"io"
	"strings"
	"text/template"
	"time"
)

const (
	name = "logger"
)

// Format represents the format which will be used to print the message
// for an logger.
type Format string

// Logger represent different lognames and priorities. They can have
// parents and child loggers which will inherit the priority of the
// parent if it has none. The hirachy of loggers is represented through
// sepperation with dots ('.'). The root logger has the name '.'.
type Logger string

// Priority defines how important a log message is. Loggers will output
// messages which are above their priority level.
type Priority int

// Different priority levels ordered by their severity.
const (
	Trace Priority = iota
	Debug
	Info
	Notice
	Warning
	Error
	Critical
	Alert
	Emergency
	Disable
)

// DefaultPriority of the root logger.
const (
	DefaultPriority   Priority = Notice
	DefaultSepperator          = "."
)

var (
	format     = "[{{.Time}} {{.Priority}} {{.Logger}}] - {{.Message}}.\n"
	timeformat = time.RFC3339

	priorities     map[Priority]string
	list           loggers
	formattemplate template.Template

	SaveLoggerLevels bool = true
)

func init() {
	list = newLoggers()

	priorities = make(map[Priority]string)
	priorities[Trace] = "Trace"
	priorities[Debug] = "Debug"
	priorities[Info] = "Info"
	priorities[Notice] = "Notice"
	priorities[Warning] = "Warning"
	priorities[Error] = "Error"
	priorities[Critical] = "Critical"
	priorities[Alert] = "Alert"
	priorities[Emergency] = "Emergency"
	priorities[Disable] = "Disabled"
}

// ImportLoggers sets the LogLevel for the given Loggers.
func ImportLoggers(lo map[Logger]string) (err error) {
	if lo == nil {
		err = errors.New("the loglevel map is nil")
		return
	}

	for k, v := range lo {
		p, e := ParsePriority(v)
		if e != nil {
			err = errors.New("can not parse priority: " + e.Error())
			return
		}

		SetLevel(k, p)
	}

	return
}

// New will return a logger with the given name.
func New(na ...string) (log Logger) {
	s := strings.Join(na, DefaultSepperator)
	return Logger(s)
}

// GetLevel returns the priority level of the given logger.
func GetLevel(lo Logger) (pri Priority) {
	return list.GetLevel(lo)
}

// SetLevel sets the priority level for the given logger.
func SetLevel(lo Logger, pr Priority) (err error) {
	err = list.SetLevel(lo, pr)
	if err != nil {
		return
	}

	return
}

// SetFormat changes the message format for the given logger. Avaivable
// fields are:
//
// Time: The time when the message is printed.
//
// Logger: The name of the logger.
//
// Priority: The priority of the logger.
//
// Message: The output message.
//
// The default Format is:
//
// "[{{.Time}} {{.Logger}} {{.Priority}}] - {{.Message}}.\n"
func SetFormat(lo Logger, fo Format) error {
	return list.SetFormat(lo, fo)
}

// SetTimeFormat sets the TimeFormat which will be used in the message
// format for the specified logger
//
// The default format is: RFC3339
func SetTimeFormat(lo Logger, fo string) error {
	return list.SetTimeFormat(lo, fo)
}

// SetNoColor sets the nocolor flag for the given logger. If true no
// colors will be printed for the logger.
func SetNoColor(lo Logger, nc bool) {
	list.SetNoColor(lo, nc)
}

// SetOutput sets the output parameter of the logger to the given
// io.Writer. The default is os.Stderr.
func SetOutput(lo Logger, ou io.Writer) error {
	return list.SetOutput(lo, ou)
}

// ParsePriority tries to parse the priority by the given string.
func ParsePriority(pr string) (Priority, error) {
	for k, v := range priorities {
		if v == pr {
			return k, nil
		}
	}

	e := errors.New("can not parse priority: do not recognize " + pr)
	return DefaultPriority, e
}

// NamePriority returns the string value of the given priority.
func NamePriority(pr Priority) (pri string, err error) {
	err = checkPriority(pr)
	if err != nil {
		return
	}

	pri = priorities[pr]

	return
}

func logMessage(lo Logger, pr Priority, me ...interface{}) {
	l := list.GetLogger(lo)

	if l.Priority > pr {
		return
	}

	printMessage(l, pr, me...)
}

// Log logs a message with the given priority.
func (lo Logger) Log(pr Priority, me ...interface{}) {
	logMessage(lo, pr, me)
}

// Trace logs a message with the Trace priority.
func (lo Logger) Trace(me ...interface{}) {
	logMessage(lo, Trace, me...)
}

// Debug logs a message with the Debug priority.
func (lo Logger) Debug(me ...interface{}) {
	logMessage(lo, Debug, me...)
}

// Info logs a message with the Debug priority.
func (lo Logger) Info(me ...interface{}) {
	logMessage(lo, Info, me...)
}

// Notice logs a message with the Debug priority.
func (lo Logger) Notice(me ...interface{}) {
	logMessage(lo, Notice, me...)
}

// Warning logs a message with the Debug priority.
func (lo Logger) Warning(me ...interface{}) {
	logMessage(lo, Warning, me...)
}

// Error logs a message with the Debug priority.
func (lo Logger) Error(me ...interface{}) {
	logMessage(lo, Error, me...)
}

// Critical logs a message with the Debug priority.
func (lo Logger) Critical(me ...interface{}) {
	logMessage(lo, Critical, me...)
}

// Alert logs a message with the Debug priority.
func (lo Logger) Alert(me ...interface{}) {
	logMessage(lo, Alert, me...)
}

// Emergency logs a message with the Debug priority.
func (lo Logger) Emergency(me ...interface{}) {
	logMessage(lo, Emergency, me...)
}

// GetLevel returns the priority level of the logger.
func (lo Logger) GetLevel() Priority {
	return GetLevel(lo)
}

// SetLevel sets the priority level for the Logger.
func (lo Logger) SetLevel(pr Priority) (err error) {
	err = SetLevel(lo, pr)
	if err != nil {
		return
	}

	return
}

// SetFormat changes the message format for the Logger. Avaivable fields
// are:
//
// Time: The time when the message is printed.
//
// Logger: The name of the logger.
//
// Priority: The priority of the logger.
//
// Message: The output message.
//
// The default Format is:
//
// "[{{.Time}} {{.Logger}} {{.Priority}}] - {{.Message}}.\n"
func (lo Logger) SetFormat(fo Format) {
	SetFormat(lo, fo)
}

// SetTimeFormat sets the TimeFormat which will be used in the message
// format for the Logger
//
// The default format is: RFC3339
func (lo Logger) SetTimeFormat(fo string) error {
	return SetTimeFormat(lo, fo)
}

// SetNoColor sets the nocolor flag for the given logger. If true no
// colors will be printed for the logger.
func (lo Logger) SetNoColor(nc bool) {
	SetNoColor(lo, nc)
}

// SetOutput sets the output parameter of the logger to the given
// io.Writer. The default is os.Stderr.
func (lo Logger) SetOutput(ou io.Writer) {
	SetOutput(lo, ou)
}
<commit_msg>Added comment to SaveLoggerLevels.<commit_after>// Package logger provides a logging framework similar to those of python
// and haskell.
package logger

import (
	"errors"
	"io"
	"strings"
	"text/template"
	"time"
)

const (
	name = "logger"
)

// Format represents the format which will be used to print the message
// for an logger.
type Format string

// Logger represent different lognames and priorities. They can have
// parents and child loggers which will inherit the priority of the
// parent if it has none. The hirachy of loggers is represented through
// sepperation with dots ('.'). The root logger has the name '.'.
type Logger string

// Priority defines how important a log message is. Loggers will output
// messages which are above their priority level.
type Priority int

// Different priority levels ordered by their severity.
const (
	Trace Priority = iota
	Debug
	Info
	Notice
	Warning
	Error
	Critical
	Alert
	Emergency
	Disable
)

// DefaultPriority of the root logger.
const (
	DefaultPriority   Priority = Notice
	DefaultSepperator          = "."
)

var (
	format     = "[{{.Time}} {{.Priority}} {{.Logger}}] - {{.Message}}.\n"
	timeformat = time.RFC3339

	priorities     map[Priority]string
	list           loggers
	formattemplate template.Template

	// SaveLoggerLevels will make the package save loggers which are only defined
	// by their parents if it is set to true.
	SaveLoggerLevels = true
)

func init() {
	list = newLoggers()

	priorities = make(map[Priority]string)
	priorities[Trace] = "Trace"
	priorities[Debug] = "Debug"
	priorities[Info] = "Info"
	priorities[Notice] = "Notice"
	priorities[Warning] = "Warning"
	priorities[Error] = "Error"
	priorities[Critical] = "Critical"
	priorities[Alert] = "Alert"
	priorities[Emergency] = "Emergency"
	priorities[Disable] = "Disabled"
}

// ImportLoggers sets the LogLevel for the given Loggers.
func ImportLoggers(lo map[Logger]string) (err error) {
	if lo == nil {
		err = errors.New("the loglevel map is nil")
		return
	}

	for k, v := range lo {
		p, e := ParsePriority(v)
		if e != nil {
			err = errors.New("can not parse priority: " + e.Error())
			return
		}

		SetLevel(k, p)
	}

	return
}

// New will return a logger with the given name.
func New(na ...string) (log Logger) {
	s := strings.Join(na, DefaultSepperator)
	return Logger(s)
}

// GetLevel returns the priority level of the given logger.
func GetLevel(lo Logger) (pri Priority) {
	return list.GetLevel(lo)
}

// SetLevel sets the priority level for the given logger.
func SetLevel(lo Logger, pr Priority) (err error) {
	err = list.SetLevel(lo, pr)
	if err != nil {
		return
	}

	return
}

// SetFormat changes the message format for the given logger. Avaivable
// fields are:
//
// Time: The time when the message is printed.
//
// Logger: The name of the logger.
//
// Priority: The priority of the logger.
//
// Message: The output message.
//
// The default Format is:
//
// "[{{.Time}} {{.Logger}} {{.Priority}}] - {{.Message}}.\n"
func SetFormat(lo Logger, fo Format) error {
	return list.SetFormat(lo, fo)
}

// SetTimeFormat sets the TimeFormat which will be used in the message
// format for the specified logger
//
// The default format is: RFC3339
func SetTimeFormat(lo Logger, fo string) error {
	return list.SetTimeFormat(lo, fo)
}

// SetNoColor sets the nocolor flag for the given logger. If true no
// colors will be printed for the logger.
func SetNoColor(lo Logger, nc bool) {
	list.SetNoColor(lo, nc)
}

// SetOutput sets the output parameter of the logger to the given
// io.Writer. The default is os.Stderr.
func SetOutput(lo Logger, ou io.Writer) error {
	return list.SetOutput(lo, ou)
}

// ParsePriority tries to parse the priority by the given string.
func ParsePriority(pr string) (Priority, error) {
	for k, v := range priorities {
		if v == pr {
			return k, nil
		}
	}

	e := errors.New("can not parse priority: do not recognize " + pr)
	return DefaultPriority, e
}

// NamePriority returns the string value of the given priority.
func NamePriority(pr Priority) (pri string, err error) {
	err = checkPriority(pr)
	if err != nil {
		return
	}

	pri = priorities[pr]

	return
}

func logMessage(lo Logger, pr Priority, me ...interface{}) {
	l := list.GetLogger(lo)

	if l.Priority > pr {
		return
	}

	printMessage(l, pr, me...)
}

// Log logs a message with the given priority.
func (lo Logger) Log(pr Priority, me ...interface{}) {
	logMessage(lo, pr, me)
}

// Trace logs a message with the Trace priority.
func (lo Logger) Trace(me ...interface{}) {
	logMessage(lo, Trace, me...)
}

// Debug logs a message with the Debug priority.
func (lo Logger) Debug(me ...interface{}) {
	logMessage(lo, Debug, me...)
}

// Info logs a message with the Debug priority.
func (lo Logger) Info(me ...interface{}) {
	logMessage(lo, Info, me...)
}

// Notice logs a message with the Debug priority.
func (lo Logger) Notice(me ...interface{}) {
	logMessage(lo, Notice, me...)
}

// Warning logs a message with the Debug priority.
func (lo Logger) Warning(me ...interface{}) {
	logMessage(lo, Warning, me...)
}

// Error logs a message with the Debug priority.
func (lo Logger) Error(me ...interface{}) {
	logMessage(lo, Error, me...)
}

// Critical logs a message with the Debug priority.
func (lo Logger) Critical(me ...interface{}) {
	logMessage(lo, Critical, me...)
}

// Alert logs a message with the Debug priority.
func (lo Logger) Alert(me ...interface{}) {
	logMessage(lo, Alert, me...)
}

// Emergency logs a message with the Debug priority.
func (lo Logger) Emergency(me ...interface{}) {
	logMessage(lo, Emergency, me...)
}

// GetLevel returns the priority level of the logger.
func (lo Logger) GetLevel() Priority {
	return GetLevel(lo)
}

// SetLevel sets the priority level for the Logger.
func (lo Logger) SetLevel(pr Priority) (err error) {
	err = SetLevel(lo, pr)
	if err != nil {
		return
	}

	return
}

// SetFormat changes the message format for the Logger. Avaivable fields
// are:
//
// Time: The time when the message is printed.
//
// Logger: The name of the logger.
//
// Priority: The priority of the logger.
//
// Message: The output message.
//
// The default Format is:
//
// "[{{.Time}} {{.Logger}} {{.Priority}}] - {{.Message}}.\n"
func (lo Logger) SetFormat(fo Format) {
	SetFormat(lo, fo)
}

// SetTimeFormat sets the TimeFormat which will be used in the message
// format for the Logger
//
// The default format is: RFC3339
func (lo Logger) SetTimeFormat(fo string) error {
	return SetTimeFormat(lo, fo)
}

// SetNoColor sets the nocolor flag for the given logger. If true no
// colors will be printed for the logger.
func (lo Logger) SetNoColor(nc bool) {
	SetNoColor(lo, nc)
}

// SetOutput sets the output parameter of the logger to the given
// io.Writer. The default is os.Stderr.
func (lo Logger) SetOutput(ou io.Writer) {
	SetOutput(lo, ou)
}
<|endoftext|>


<commit_before>package logo

type Logger func(level LogLevel, format string, args ...interface{})

func (l Logger) Log(level LogLevel, format string, args ...interface{}) {
	l(level, format, args...)
}

func Log(level LogLevel, format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(level, format, args...)
}

func Debug(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelDebug, format, args...)
}

func Info(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelInfo, format, args...)
}

func Warning(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelWarning, format, args...)
}

func Error(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelError, format, args...)
}

func Critical(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelCritical, format, args...)
}
<commit_msg>Added comments<commit_after>package logo

// Logger function to log message with level.
type Logger func(level LogLevel, format string, args ...interface{})

// Log mehtods calls Logger function.
func (l Logger) Log(level LogLevel, format string, args ...interface{}) {
	l(level, format, args...)
}

// Log calls DefaultLogo's Log method.
func Log(level LogLevel, format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(level, format, args...)
}

// Debug logs Debug level message.
func Debug(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelDebug, format, args...)
}

// Info logs Info level message
func Info(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelInfo, format, args...)
}

// Warning logs Warning level message.
func Warning(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelWarning, format, args...)
}

// Error logs Error level message.
func Error(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelError, format, args...)
}

// Critical logs Critical level message
func Critical(format string, args ...interface{}) {
	DefaultLogo.Skip(2).Log(LevelCritical, format, args...)
}
<|endoftext|>


<commit_before>package utils

import (
	"log"
	"os"
)

type LogLevel int

const (
	LEVEL_TRACE LogLevel = iota
	LEVEL_DEBUG
	LEVEL_INFO
	LEVEL_WARN
	LEVEL_ERROR
	LEVEL_OFF
)

type Logger struct {
	*log.Logger

	Level  LogLevel
	Output *os.File
}

func NewLogger(f string, l LogLevel) (*Logger, error) {
	file, err := os.OpenFile(f, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		return nil, err
	}

	logger := &Logger{Output: file, Level: l}
	logger.Logger = log.New(file, "", log.Ldate|log.Ltime)

	return logger, nil
}

func NewLoggerFromConfig(f string) (*Logger, error) {
	props := make(map[string]string)
	err := LoadConfig(f, props)
	if err != nil {
		return nil, err
	}

	var level LogLevel
	switch props["level"] {
	case "TRACE", "trace":
		level = LEVEL_TRACE
	case "DEBUG", "debug":
		level = LEVEL_DEBUG
	case "INFO", "info":
		level = LEVEL_INFO
	case "WARN", "warn":
		level = LEVEL_WARN
	case "ERROR", "error":
		level = LEVEL_ERROR
	case "OFF", "off":
		level = LEVEL_ERROR
	default:
		log.Fatalf("Error loading config: %s is not a valid level", props["level"])
	}

	return NewLogger(props["file"], level)
}

func (logger *Logger) Close() {
	err := logger.Output.Close()
	if err != nil {
		log.Fatalf("Error opening file: %v", err)
	}
}

func (logger *Logger) Trace(v ...interface{}) {
	if logger.Level <= LEVEL_TRACE {
		logger.Logger.Println(append([]interface{}{"TRACE:"}, v...)...)
	}
}

func (logger *Logger) Tracef(format string, v ...interface{}) {
	if logger.Level <= LEVEL_TRACE {
		logger.Logger.Printf("TRACE: "+format+"\n", v...)
	}
}

func (logger *Logger) TraceBegin(f string) {
	if logger.Level <= LEVEL_TRACE {
		logger.Logger.Println("TRACE: Begin -", f)
	}
}

func (logger *Logger) TraceEnd(f string) {
	if logger.Level <= LEVEL_TRACE {
		logger.Logger.Println("TRACE: End -", f)
	}
}

func (logger *Logger) Debug(v ...interface{}) {
	if logger.Level <= LEVEL_DEBUG {
		logger.Logger.Println(append([]interface{}{"DEBUG:"}, v...)...)
	}
}

func (logger *Logger) Debugf(format string, v ...interface{}) {
	if logger.Level <= LEVEL_DEBUG {
		logger.Logger.Printf("DEBUG: "+format+"\n", v...)
	}
}

func (logger *Logger) Info(v ...interface{}) {
	if logger.Level <= LEVEL_INFO {
		logger.Logger.Println(append([]interface{}{"INFO:"}, v...)...)
	}
}

func (logger *Logger) Infof(format string, v ...interface{}) {
	if logger.Level <= LEVEL_INFO {
		logger.Logger.Printf("INFO: "+format+"\n", v...)
	}
}

func (logger *Logger) Warn(v ...interface{}) {
	if logger.Level <= LEVEL_WARN {
		logger.Logger.Println(append([]interface{}{"WARN:"}, v...)...)
	}
}

func (logger *Logger) Warnf(format string, v ...interface{}) {
	if logger.Level <= LEVEL_WARN {
		logger.Logger.Printf("WARN: "+format+"\n", v...)
	}
}

func (logger *Logger) Error(v ...interface{}) {
	if logger.Level <= LEVEL_ERROR {
		logger.Logger.Println(append([]interface{}{"ERROR:"}, v...)...)
	}
}

func (logger *Logger) Errorf(format string, v ...interface{}) {
	if logger.Level <= LEVEL_ERROR {
		logger.Logger.Printf("ERROR: "+format+"\n", v...)
	}
}

func (logger *Logger) Fatal(v ...interface{}) {
	logger.Logger.Fatalln(append([]interface{}{"FATAL:"}, v...)...)
}

func (logger *Logger) Fatalf(format string, v ...interface{}) {
	logger.Logger.Fatalf("FATAL: "+format+"\n", v...)
}
<commit_msg>Little improvements for Logger<commit_after>package utils

import (
	"errors"
	"fmt"
	"log"
	"os"
)

type LogLevel int

const (
	LEVEL_TRACE LogLevel = iota
	LEVEL_DEBUG
	LEVEL_INFO
	LEVEL_WARN
	LEVEL_ERROR
	LEVEL_OFF
)

type Logger struct {
	*log.Logger

	Level  LogLevel
	Output *os.File
}

func NewLogger(f string, l LogLevel) (*Logger, error) {
	file, err := os.OpenFile(f, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		return nil, err
	}

	logger := &Logger{Output: file, Level: l}
	logger.Logger = log.New(file, "", log.Ldate|log.Ltime)

	return logger, nil
}

func NewLoggerFromConfig(file string) (*Logger, error) {
	props := make(map[string]string)
	err := LoadConfig(file, props)
	if err != nil {
		return nil, err
	}

	var level LogLevel
	switch props["level"] {
	case "TRACE", "trace":
		level = LEVEL_TRACE
	case "DEBUG", "debug":
		level = LEVEL_DEBUG
	case "INFO", "info":
		level = LEVEL_INFO
	case "WARN", "warn":
		level = LEVEL_WARN
	case "ERROR", "error":
		level = LEVEL_ERROR
	case "OFF", "off":
		level = LEVEL_ERROR
	default:
		return nil, errors.New(fmt.Sprintf("Error loading config: %s is not a valid level", props["level"]))
	}

	return NewLogger(props["file"], level)
}

func (logger *Logger) Close() {
	err := logger.Output.Close()
	if err != nil {
		log.Fatalf("Error opening file: %v", err)
	}
}

func (logger *Logger) Trace(v ...interface{}) {
	if logger.Level <= LEVEL_TRACE {
		logger.Logger.Println(append([]interface{}{"TRACE:"}, v...)...)
	}
}

func (logger *Logger) Tracef(format string, v ...interface{}) {
	if logger.Level <= LEVEL_TRACE {
		logger.Logger.Printf("TRACE: "+format+"\n", v...)
	}
}

func (logger *Logger) TraceBegin(f string) {
	if logger.Level <= LEVEL_TRACE {
		logger.Logger.Println("TRACE: Begin -", f)
	}
}

func (logger *Logger) TraceEnd(f string) {
	if logger.Level <= LEVEL_TRACE {
		logger.Logger.Println("TRACE: End -", f)
	}
}

func (logger *Logger) Debug(v ...interface{}) {
	if logger.Level <= LEVEL_DEBUG {
		logger.Logger.Println(append([]interface{}{"DEBUG:"}, v...)...)
	}
}

func (logger *Logger) Debugf(format string, v ...interface{}) {
	if logger.Level <= LEVEL_DEBUG {
		logger.Logger.Printf("DEBUG: "+format+"\n", v...)
	}
}

func (logger *Logger) Info(v ...interface{}) {
	if logger.Level <= LEVEL_INFO {
		logger.Logger.Println(append([]interface{}{"INFO:"}, v...)...)
	}
}

func (logger *Logger) Infof(format string, v ...interface{}) {
	if logger.Level <= LEVEL_INFO {
		logger.Logger.Printf("INFO: "+format+"\n", v...)
	}
}

func (logger *Logger) Warn(v ...interface{}) {
	if logger.Level <= LEVEL_WARN {
		logger.Logger.Println(append([]interface{}{"WARN:"}, v...)...)
	}
}

func (logger *Logger) Warnf(format string, v ...interface{}) {
	if logger.Level <= LEVEL_WARN {
		logger.Logger.Printf("WARN: "+format+"\n", v...)
	}
}

func (logger *Logger) Error(v ...interface{}) {
	if logger.Level <= LEVEL_ERROR {
		logger.Logger.Println(append([]interface{}{"ERROR:"}, v...)...)
	}
}

func (logger *Logger) Errorf(format string, v ...interface{}) {
	if logger.Level <= LEVEL_ERROR {
		logger.Logger.Printf("ERROR: "+format+"\n", v...)
	}
}

func (logger *Logger) Fatal(v ...interface{}) {
	logger.Logger.Fatalln(append([]interface{}{"FATAL:"}, v...)...)
}

func (logger *Logger) Fatalf(format string, v ...interface{}) {
	logger.Logger.Fatalf("FATAL: "+format+"\n", v...)
}
<|endoftext|>


<commit_before>package xlog

import (
	"log"
	"os"
	"fmt"
	"io"
)

// Level describes a logging level.
type Level int

const (
	Debug Level = 1 << iota
	Info        = 1 << iota
	Notice      = 1 << iota
	Warning     = 1 << iota
	Error       = 1 << iota
	Critical    = 1 << iota
	Alert       = 1 << iota
	Emergency   = 1 << iota
)

// Levels maps Level to a string representation.
var Levels = map[Level]string{
	Debug: "DEBUG",
	Info: "INFO",
	Notice: "NOTICE",
	Warning: "WARNING",
	Error: "ERROR",
	Critical: "CRITICAL",
	Alert: "ALERT",
	Emergency: "EMERGENCY",
}

// Aliases maps file aliases to real file pointers.
var Aliases = map[string]*os.File{
	"stdout": os.Stdout,
	"stdin": os.Stdin,
	"stderr": os.Stderr,
}

var (
	// DefaultDateFormat is the date format to use when none has been specified.
	DefaultDateFormat = "2006-01-02 15:04:05.000"

	// DefaultMessageFormat is the message format to use when none has been specified.
	DefaultMessageFormat = "{date|2006-01-02 15:04:05.000} {name}.{level} {message}"

	// FileFlags defines the file open options.
	FileOpenFlags int = os.O_RDWR|os.O_CREATE|os.O_APPEND

	// FileMode defines the mode files are opened in.
	FileOpenMode os.FileMode = 0666

	// PanicOnFileErrors defines whether the logger should panic when opening a file
	// fails. When set to false, any file open errors are ignored, and the file won't be
	// appended.
	PanicOnFileErrors = true

	// InitialLoggerCapacity defines the initial capacity for each type of logger.
	InitialLoggerCapacity = 4

	// FatalOn represents levels that causes the application to exit.
	FatalOn Level = 0

	// PanicOn represents levels that causes the application to panic.
	PanicOn Level = 0
)

// Loggable is an interface that provides methods for logging messages to
// various levels.
type Loggable interface {
	Log(level Level, v ...interface{})
	Logf(level Level, format string, v ...interface{})
	Debug(v ...interface{})
	Debugf(format string, v ...interface{})
	Info(v ...interface{})
	Infof(format string, v ...interface{})
	Warning(v ...interface{})
	Warningf(format string, v ...interface{})
	Error(v ...interface{})
	Errorf(format string, v ...interface{})
	Critical(v ...interface{})
	Criticalf(format string, v ...interface{})
	Alert(v ...interface{})
	Alertf(format string, v ...interface{})
	Emergency(v ...interface{})
	Emergencyf(format string, v ...interface{})
}

// Logger is a light weight logger designed to write to multiple files at different
// log levels.
type Logger struct {
	// Enabled defines whether logging is enabled.
	Enabled  bool

	// Formatter is used to format the log messages.
	Formatter Formatter

	// Loggers holds the appended file loggers.
	Loggers LoggerMap

	// pointers contains any files that have been opened for logging.
	pointers []*os.File

	// closed defines whether the logger has been closed.
	closed bool
}

// NewLogger returns a *Logger instance that's been initialized with default values.
func NewLogger(name string) *Logger {
	return &Logger{
		Enabled: true,
		Formatter: NewDefaultFormatter(DefaultMessageFormat, name),
		Loggers: NewDefaultLoggerMap(),
		pointers: make([]*os.File, 0),
		closed: false,
	}
}

// NewMultiLogger returns a *Logger instance that's been initialized with one or
// more files at the given level.
func NewMultiLogger(name string, files []string, level Level) *Logger {
	logger := NewLogger(name)
	logger.MultiAppend(files, level);
	return logger;
}

// NewMultiWriterLogger returns a *Logger instance that's been initialized with one or
// more writers at the given level.
func NewMultiWriterLogger(name string, writers []io.Writer, level Level) *Logger {
	logger := NewLogger(name)
	logger.MultiAppendWriter(writers, level);
	return logger;
}

// NewFormattedLogger returns a *Logger instance using the provided formatter.
func NewFormattedLogger(formatter Formatter) *Logger {
	return &Logger{
		Enabled: true,
		Formatter: formatter,
		Loggers: NewDefaultLoggerMap(),
		pointers: make([]*os.File, 0),
		closed: false,
	}
}

// SetName sets the name of the logger.
func (l *Logger) SetName(name string) {
	l.Formatter.SetName(name)
}

// Append adds a file that will be written to at the given level or greater.
// The file argument may be either the full path to a system file, or one of the
// aliases "stdout", "stdin", or "stderr".
func (l *Logger) Append(file string, level Level) {
	if w, ok := Aliases[file]; ok {
		l.Loggers.Append(newLogger(w), level)
	} else {
		w := l.open(file)
		if w != nil {
			l.Loggers.Append(newLogger(w), level)
			l.pointers = append(l.pointers, w)
		}
	}
}

// MultiAppend adds one or more files to the logger.
func (l *Logger) MultiAppend(files []string, level Level) {
	for _, file := range files {
		l.Append(file, level)
	}
}

// AppendWriter adds a writer that will be written to at the given level or greater.
func (l *Logger) AppendWriter(w io.Writer, level Level) {
	l.Loggers.Append(newLogger(w), level)
}

// MultiAppendWriter adds one or more io.Writer instances to the logger.
func (l *Logger) MultiAppendWriter(writers []io.Writer, level Level) {
	for _, writer := range writers {
		l.AppendWriter(writer, level)
	}
}

// Close disables logging and frees up resources used by the logger.
// Note this method only closes files opened by the logger. It's the user's
// responsibility to close files that were passed to the logger via the
// AppendWriter method.
func (l *Logger) Close() {
	if !l.closed {
		for _, pointer := range l.pointers {
			pointer.Close()
		}

		l.Enabled = false
		l.Loggers = nil
		l.pointers = nil
	}
}

// Writable returns true when logging is enabled, and the logger hasn't been closed.
func (l *Logger) Writable() bool {
	return l.Enabled && !l.closed
}

// Log writes the message to each logger appended at the given level or higher.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Log(level Level, v ...interface{}) {
	if l.Writable() {
		message := l.Formatter.Format(level, v...)
		if message != "" {
			for _, logger := range l.Loggers.FindByLevel(level) {
				logger.Print(message)
			}
		}

		if FatalOn&level > 0 {
			os.Exit(1)
		} else if PanicOn&level > 0 {
			panic(message)
		}
	}
}

// Log writes the message to each logger appended at the given level or higher.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Logf(level Level, format string, v ...interface{}) {
	l.Log(level, fmt.Sprintf(format, v...))
}

// Debug prints to each log file at the Debug level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Debug(v ...interface{}) {
	l.Log(Debug, v...)
}

// Debugf prints to each log file at the Debug level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Debugf(format string, v ...interface{}) {
	l.Logf(Debug, format, v...)
}

// Info prints to each log file at the Info level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Info(v ...interface{}) {
	l.Log(Info, v...)
}

// Infof prints to each log file at the Info level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Infof(format string, v ...interface{}) {
	l.Logf(Info, format, v...)
}

// Notice prints to each log file at the Notice level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Notice(v ...interface{}) {
	l.Log(Notice, v...)
}

// Noticef prints to each log file at the Notice level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Noticef(format string, v ...interface{}) {
	l.Logf(Notice, format, v...)
}

// Warning prints to each log file at the Warning level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Warning(v ...interface{}) {
	l.Log(Warning, v...)
}

// Warningf prints to each log file at the Warning level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Warningf(format string, v ...interface{}) {
	l.Logf(Warning, format, v...)
}

// Error prints to each log file at the Error level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Error(v ...interface{}) {
	l.Log(Error, v...)
}

// Errorf prints to each log file at the Error level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Errorf(format string, v ...interface{}) {
	l.Logf(Error, format, v...)
}

// Critical prints to each log file at the Critical level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Critical(v ...interface{}) {
	l.Log(Critical, v...)
}

// Criticalf prints to each log file at the Critical level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Criticalf(format string, v ...interface{}) {
	l.Logf(Critical, format, v...)
}

// Alert prints to each log file at the Alert level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Alert(v ...interface{}) {
	l.Log(Alert, v...)
}

// Alertf prints to each log file at the Alert level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Alertf(format string, v ...interface{}) {
	l.Logf(Alert, format, v...)
}

// Emergency prints to each log file at the Emergency level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Emergency(v ...interface{}) {
	l.Log(Emergency, v...)
}

// Emergencyf prints to each log file at the Emergency level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Emergencyf(format string, v ...interface{}) {
	l.Logf(Emergency, format, v...)
}

// open returns a file that logs can be written to.
func (l *Logger) open(name string) *os.File {
	w, err := os.OpenFile(name, FileOpenFlags, FileOpenMode)
	if err != nil {
		if PanicOnFileErrors {
			panic(err)
		} else {
			w = nil
		}
	}

	return w
}

// newLogger returns a *log.Logger instance configured with the default options.
func newLogger(w io.Writer) *log.Logger {
	return log.New(w, "", 0)
}

<commit_msg>Changed the name of a variable<commit_after>package xlog

import (
	"log"
	"os"
	"fmt"
	"io"
)

// Level describes a logging level.
type Level int

const (
	Debug Level = 1 << iota
	Info        = 1 << iota
	Notice      = 1 << iota
	Warning     = 1 << iota
	Error       = 1 << iota
	Critical    = 1 << iota
	Alert       = 1 << iota
	Emergency   = 1 << iota
)

// Levels maps Level to a string representation.
var Levels = map[Level]string{
	Debug: "DEBUG",
	Info: "INFO",
	Notice: "NOTICE",
	Warning: "WARNING",
	Error: "ERROR",
	Critical: "CRITICAL",
	Alert: "ALERT",
	Emergency: "EMERGENCY",
}

// Aliases maps file aliases to real file pointers.
var Aliases = map[string]*os.File{
	"stdout": os.Stdout,
	"stdin": os.Stdin,
	"stderr": os.Stderr,
}

var (
	// DefaultDateFormat is the date format to use when none has been specified.
	DefaultDateFormat = "2006-01-02 15:04:05.000"

	// DefaultMessageFormat is the message format to use when none has been specified.
	DefaultMessageFormat = "{date|2006-01-02 15:04:05.000} {name}.{level} {message}"

	// FileFlags defines the file open options.
	FileOpenFlags int = os.O_RDWR|os.O_CREATE|os.O_APPEND

	// FileMode defines the mode files are opened in.
	FileOpenMode os.FileMode = 0666

	// PanicOnFileErrors defines whether the logger should panic when opening a file
	// fails. When set to false, any file open errors are ignored, and the file won't be
	// appended.
	PanicOnFileErrors = true

	// InitialLoggerCapacity defines the initial capacity for each type of logger.
	InitialLoggerCapacity = 4

	// FatalOn represents levels that causes the application to exit.
	FatalOn Level = 0

	// PanicOn represents levels that causes the application to panic.
	PanicOn Level = 0
)

// Loggable is an interface that provides methods for logging messages to
// various levels.
type Loggable interface {
	Log(level Level, v ...interface{})
	Logf(level Level, format string, v ...interface{})
	Debug(v ...interface{})
	Debugf(format string, v ...interface{})
	Info(v ...interface{})
	Infof(format string, v ...interface{})
	Warning(v ...interface{})
	Warningf(format string, v ...interface{})
	Error(v ...interface{})
	Errorf(format string, v ...interface{})
	Critical(v ...interface{})
	Criticalf(format string, v ...interface{})
	Alert(v ...interface{})
	Alertf(format string, v ...interface{})
	Emergency(v ...interface{})
	Emergencyf(format string, v ...interface{})
}

// Logger is a light weight logger designed to write to multiple files at different
// log levels.
type Logger struct {
	// Enabled defines whether logging is enabled.
	Enabled  bool

	// Formatter is used to format the log messages.
	Formatter Formatter

	// Loggers holds the appended file loggers.
	Loggers LoggerMap

	// pointers contains any files that have been opened for logging.
	pointers []*os.File

	// closed defines whether the logger has been closed.
	closed bool
}

// NewLogger returns a *Logger instance that's been initialized with default values.
func NewLogger(name string) *Logger {
	return &Logger{
		Enabled: true,
		Formatter: NewDefaultFormatter(DefaultMessageFormat, name),
		Loggers: NewDefaultLoggerMap(),
		pointers: make([]*os.File, 0),
		closed: false,
	}
}

// NewMultiLogger returns a *Logger instance that's been initialized with one or
// more files at the given level.
func NewMultiLogger(name string, files []string, level Level) *Logger {
	logger := NewLogger(name)
	logger.MultiAppend(files, level);
	return logger;
}

// NewMultiWriterLogger returns a *Logger instance that's been initialized with one or
// more writers at the given level.
func NewMultiWriterLogger(name string, writers []io.Writer, level Level) *Logger {
	logger := NewLogger(name)
	logger.MultiAppendWriter(writers, level);
	return logger;
}

// NewFormattedLogger returns a *Logger instance using the provided formatter.
func NewFormattedLogger(formatter Formatter) *Logger {
	return &Logger{
		Enabled: true,
		Formatter: formatter,
		Loggers: NewDefaultLoggerMap(),
		pointers: make([]*os.File, 0),
		closed: false,
	}
}

// SetName sets the name of the logger.
func (l *Logger) SetName(name string) {
	l.Formatter.SetName(name)
}

// Append adds a file that will be written to at the given level or greater.
// The file argument may be either the full path to a system file, or one of the
// aliases "stdout", "stdin", or "stderr".
func (l *Logger) Append(file string, level Level) {
	if w, ok := Aliases[file]; ok {
		l.Loggers.Append(newLogger(w), level)
	} else {
		w := l.open(file)
		if w != nil {
			l.Loggers.Append(newLogger(w), level)
			l.pointers = append(l.pointers, w)
		}
	}
}

// MultiAppend adds one or more files to the logger.
func (l *Logger) MultiAppend(files []string, level Level) {
	for _, file := range files {
		l.Append(file, level)
	}
}

// AppendWriter adds a writer that will be written to at the given level or greater.
func (l *Logger) AppendWriter(writer io.Writer, level Level) {
	l.Loggers.Append(newLogger(writer), level)
}

// MultiAppendWriter adds one or more io.Writer instances to the logger.
func (l *Logger) MultiAppendWriter(writers []io.Writer, level Level) {
	for _, writer := range writers {
		l.AppendWriter(writer, level)
	}
}

// Close disables logging and frees up resources used by the logger.
// Note this method only closes files opened by the logger. It's the user's
// responsibility to close files that were passed to the logger via the
// AppendWriter method.
func (l *Logger) Close() {
	if !l.closed {
		for _, pointer := range l.pointers {
			pointer.Close()
		}

		l.Enabled = false
		l.Loggers = nil
		l.pointers = nil
	}
}

// Writable returns true when logging is enabled, and the logger hasn't been closed.
func (l *Logger) Writable() bool {
	return l.Enabled && !l.closed
}

// Log writes the message to each logger appended at the given level or higher.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Log(level Level, v ...interface{}) {
	if l.Writable() {
		message := l.Formatter.Format(level, v...)
		if message != "" {
			for _, logger := range l.Loggers.FindByLevel(level) {
				logger.Print(message)
			}
		}

		if FatalOn&level > 0 {
			os.Exit(1)
		} else if PanicOn&level > 0 {
			panic(message)
		}
	}
}

// Log writes the message to each logger appended at the given level or higher.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Logf(level Level, format string, v ...interface{}) {
	l.Log(level, fmt.Sprintf(format, v...))
}

// Debug prints to each log file at the Debug level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Debug(v ...interface{}) {
	l.Log(Debug, v...)
}

// Debugf prints to each log file at the Debug level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Debugf(format string, v ...interface{}) {
	l.Logf(Debug, format, v...)
}

// Info prints to each log file at the Info level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Info(v ...interface{}) {
	l.Log(Info, v...)
}

// Infof prints to each log file at the Info level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Infof(format string, v ...interface{}) {
	l.Logf(Info, format, v...)
}

// Notice prints to each log file at the Notice level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Notice(v ...interface{}) {
	l.Log(Notice, v...)
}

// Noticef prints to each log file at the Notice level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Noticef(format string, v ...interface{}) {
	l.Logf(Notice, format, v...)
}

// Warning prints to each log file at the Warning level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Warning(v ...interface{}) {
	l.Log(Warning, v...)
}

// Warningf prints to each log file at the Warning level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Warningf(format string, v ...interface{}) {
	l.Logf(Warning, format, v...)
}

// Error prints to each log file at the Error level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Error(v ...interface{}) {
	l.Log(Error, v...)
}

// Errorf prints to each log file at the Error level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Errorf(format string, v ...interface{}) {
	l.Logf(Error, format, v...)
}

// Critical prints to each log file at the Critical level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Critical(v ...interface{}) {
	l.Log(Critical, v...)
}

// Criticalf prints to each log file at the Critical level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Criticalf(format string, v ...interface{}) {
	l.Logf(Critical, format, v...)
}

// Alert prints to each log file at the Alert level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Alert(v ...interface{}) {
	l.Log(Alert, v...)
}

// Alertf prints to each log file at the Alert level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Alertf(format string, v ...interface{}) {
	l.Logf(Alert, format, v...)
}

// Emergency prints to each log file at the Emergency level.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Emergency(v ...interface{}) {
	l.Log(Emergency, v...)
}

// Emergencyf prints to each log file at the Emergency level.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Emergencyf(format string, v ...interface{}) {
	l.Logf(Emergency, format, v...)
}

// open returns a file that logs can be written to.
func (l *Logger) open(name string) *os.File {
	w, err := os.OpenFile(name, FileOpenFlags, FileOpenMode)
	if err != nil {
		if PanicOnFileErrors {
			panic(err)
		} else {
			w = nil
		}
	}

	return w
}

// newLogger returns a *log.Logger instance configured with the default options.
func newLogger(w io.Writer) *log.Logger {
	return log.New(w, "", 0)
}

<|endoftext|>


<commit_before>/*
 * Copyright 2014 Xuyuan Pang <xuyuanp # gmail.com>
 *
 * 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 glogger

import (
	"fmt"
	"runtime"
	"time"
)

// Logger is the default Logger
type Logger struct {
	GroupFilter
	handlerGroup
	Name   string
	Level  LogLevel
	ch     chan *Record
	parent *Logger
}

// NewLogger return a new Logger with debug level as default.
func NewLogger() *Logger {
	l := &Logger{
		Level: DebugLevel,
		ch:    make(chan *Record, 100000),
	}
	return l
}

// Default functions return a logger registered by name 'root',
// or a new Logger with default Handler and Formatter, and registered as 'root' automatically.
func Default() *Logger {
	if l := GetLogger("root"); l != nil {
		return l
	}
	l := NewLogger()
	h := NewStreamHandler()
	l.AddHandler(h)
	RegisterLogger("root", l)
	return l
}

var std = Default()

// Debug see details in Logger interface
func (l *Logger) Debug(f string, v ...interface{}) {
	l.log(DebugLevel, fmt.Sprintf(f, v...))
}

// Info see details in Logger interface
func (l *Logger) Info(f string, v ...interface{}) {
	l.log(InfoLevel, fmt.Sprintf(f, v...))
}

// Warning see details in Logger interface
func (l *Logger) Warning(f string, v ...interface{}) {
	l.log(WarnLevel, fmt.Sprintf(f, v...))
}

// Error see details in Logger interface
func (l *Logger) Error(f string, v ...interface{}) {
	l.log(ErrorLevel, fmt.Sprintf(f, v...))
}

// Critical see details in Logger interface
func (l *Logger) Critical(f string, v ...interface{}) {
	l.log(CriticalLevel, fmt.Sprintf(f, v...))
}

func (l *Logger) log(level LogLevel, msg string) {
	if level < l.Level {
		return
	}
	now := time.Now()
	pc, file, line, ok := runtime.Caller(2)
	var funcname string
	if !ok {
		file = "???"
		line = 0
		funcname = "???"
	} else {
		funcname = runtime.FuncForPC(pc).Name()
	}
	rec := NewRecord(l.Name, now, level, file, funcname, line, msg)
	if !l.Filter(rec) {
		return
	}
	l.Handle(rec)
}

// Debug function calls default logger's Debug method
func Debug(f string, v ...interface{}) {
	Default().Debug(f, v...)
}

// Info function calls default logger's Info method
func Info(f string, v ...interface{}) {
	Default().Info(f, v...)
}

// Warning function calls default logger's Warning method
func Warning(f string, v ...interface{}) {
	Default().Warning(f, v...)
}

// Error function calls default logger's Error method
func Error(f string, v ...interface{}) {
	Default().Error(f, v...)
}

// Critical function calls default logger's Critical method
func Critical(f string, v ...interface{}) {
	Default().Critical(f, v...)
}

func (l *Logger) run() {
	for {
		select {
		case rec := <-l.ch:
			l.Handle(rec)
		}
	}
}

func (l *Logger) LoadConfig(config map[string]interface{}) error {
	// Load log level, default is DebugLevel
	if blevel, ok := config["level"]; ok {
		if level, ok := StringToLevel[blevel.(string)]; ok {
			l.Level = level
		} else {
			return fmt.Errorf("unknown log level: %s", blevel.(string))
		}
	} else {
		l.Level = DebugLevel
	}
	// Load handlers, default is StreamHandler
	if handlers, ok := config["handlers"]; ok && len(handlers.([]interface{})) > 0 {
		l.ClearHandlers()
		for _, hname := range handlers.([]interface{}) {
			if handler := GetHandler(hname.(string)); handler != nil {
				l.AddHandler(handler)
			} else {
				return fmt.Errorf("unknown handler name: %s", hname.(string))
			}
		}
	} else {
		h := NewStreamHandler()
		l.SetHandlers(h)
	}
	// Load filters
	if filters, ok := config["filters"]; ok {
		if len(filters.([]interface{})) > 0 {
			for _, fname := range filters.([]interface{}) {
				if filter := GetFilter(fname.(string)); filter != nil {
					l.AddFilter(filter)
				} else {
					return fmt.Errorf("unknown filter name: %s", fname.(string))
				}
			}
		}
	}
	return nil
}
<commit_msg>Remove quick log method<commit_after>/*
 * Copyright 2014 Xuyuan Pang <xuyuanp # gmail.com>
 *
 * 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 glogger

import (
	"fmt"
	"runtime"
	"time"
)

// Logger is the default Logger
type Logger struct {
	GroupFilter
	handlerGroup
	Name   string
	Level  LogLevel
	ch     chan *Record
	parent *Logger
}

// NewLogger return a new Logger with debug level as default.
func NewLogger() *Logger {
	l := &Logger{
		Level: DebugLevel,
		ch:    make(chan *Record, 100000),
	}
	return l
}

// Default functions return a logger registered by name 'root',
// or a new Logger with default Handler and Formatter, and registered as 'root' automatically.
func Default() *Logger {
	if l := GetLogger("root"); l != nil {
		return l
	}
	l := NewLogger()
	h := NewStreamHandler()
	l.AddHandler(h)
	RegisterLogger("root", l)
	return l
}

var std = Default()

// Debug see details in Logger interface
func (l *Logger) Debug(f string, v ...interface{}) {
	l.log(DebugLevel, fmt.Sprintf(f, v...))
}

// Info see details in Logger interface
func (l *Logger) Info(f string, v ...interface{}) {
	l.log(InfoLevel, fmt.Sprintf(f, v...))
}

// Warning see details in Logger interface
func (l *Logger) Warning(f string, v ...interface{}) {
	l.log(WarnLevel, fmt.Sprintf(f, v...))
}

// Error see details in Logger interface
func (l *Logger) Error(f string, v ...interface{}) {
	l.log(ErrorLevel, fmt.Sprintf(f, v...))
}

// Critical see details in Logger interface
func (l *Logger) Critical(f string, v ...interface{}) {
	l.log(CriticalLevel, fmt.Sprintf(f, v...))
}

func (l *Logger) log(level LogLevel, msg string) {
	if level < l.Level {
		return
	}
	now := time.Now()
	pc, file, line, ok := runtime.Caller(2)
	var funcname string
	if !ok {
		file = "???"
		line = 0
		funcname = "???"
	} else {
		funcname = runtime.FuncForPC(pc).Name()
	}
	rec := NewRecord(l.Name, now, level, file, funcname, line, msg)
	if !l.Filter(rec) {
		return
	}
	l.Handle(rec)
}

func (l *Logger) run() {
	for {
		select {
		case rec := <-l.ch:
			l.Handle(rec)
		}
	}
}

func (l *Logger) LoadConfig(config map[string]interface{}) error {
	// Load log level, default is DebugLevel
	if blevel, ok := config["level"]; ok {
		if level, ok := StringToLevel[blevel.(string)]; ok {
			l.Level = level
		} else {
			return fmt.Errorf("unknown log level: %s", blevel.(string))
		}
	} else {
		l.Level = DebugLevel
	}
	// Load handlers, default is StreamHandler
	if handlers, ok := config["handlers"]; ok && len(handlers.([]interface{})) > 0 {
		l.ClearHandlers()
		for _, hname := range handlers.([]interface{}) {
			if handler := GetHandler(hname.(string)); handler != nil {
				l.AddHandler(handler)
			} else {
				return fmt.Errorf("unknown handler name: %s", hname.(string))
			}
		}
	} else {
		h := NewStreamHandler()
		l.SetHandlers(h)
	}
	// Load filters
	if filters, ok := config["filters"]; ok {
		if len(filters.([]interface{})) > 0 {
			for _, fname := range filters.([]interface{}) {
				if filter := GetFilter(fname.(string)); filter != nil {
					l.AddFilter(filter)
				} else {
					return fmt.Errorf("unknown filter name: %s", fname.(string))
				}
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package google_now_test

import (
	"bytes"
	"io/ioutil"
	"net"
	"net/http"
	"path/filepath"
	"runtime"
	"testing"
	"time"

	"encoding/json"

	"github.com/pkg/errors"
	"github.com/stretchr/testify/assert"
	"github.com/uber/zanzibar/test/lib/bench_gateway"
	"github.com/uber/zanzibar/test/lib/test_gateway"
)

var benchBytes = []byte("{\"authCode\":\"abcdef\"}")
var noAuthCodeBytes = []byte("{}")

func BenchmarkGoogleNowAddCredentials(b *testing.B) {
	gateway, err := benchGateway.CreateGateway(nil, &testGateway.Options{
		KnownBackends: []string{"googleNow"},
	})
	if err != nil {
		b.Error("got bootstrap err: " + err.Error())
		return
	}

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials", func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(200)
			if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
				panic(errors.New("can't write fake response"))
			}
		},
	)

	b.ResetTimer()

	// b.SetParallelism(100)
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			res, err := gateway.MakeRequest(
				"POST", "/googlenow/add-credentials",
				bytes.NewReader(benchBytes),
			)
			if err != nil {
				b.Error("got http error: " + err.Error())
				break
			}
			if res.Status != "200 OK" {
				b.Error("got bad status error: " + res.Status)
				break
			}

			_, err = ioutil.ReadAll(res.Body)
			if err != nil {
				b.Error("could not write response: " + res.Status)
				break
			}
			_ = res.Body.Close()
		}
	})

	b.StopTimer()
	gateway.Close()
	b.StartTimer()
}

func getDirName() string {
	_, file, _, _ := runtime.Caller(0)

	return filepath.Dir(file)
}

func TestAddCredentials(t *testing.T) {
	var counter int = 0

	gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{
		KnownBackends: []string{"googleNow"},
		TestBinary: filepath.Join(
			getDirName(), "..", "..", "..",
			"examples", "example-gateway", "build", "main.go",
		),
	})
	if !assert.NoError(t, err, "got bootstrap err") {
		return
	}
	defer gateway.Close()

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials", func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(200)
			if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
				t.Fatal("can't write fake response")
			}
			counter++
		},
	)

	res, err := gateway.MakeRequest(
		"POST", "/googlenow/add-credentials", bytes.NewReader(benchBytes),
	)
	if !assert.NoError(t, err, "got http error") {
		return
	}

	assert.Equal(t, "200 OK", res.Status)
	assert.Equal(t, 1, counter)
}

type failingConn struct {
	net.Conn
}

func (conn *failingConn) Write(b []byte) (int, error) {
	b = b[0 : len(b)-1]
	n, err := conn.Conn.Write(b)

	_ = conn.Conn.Close()
	return n, err
}

func TestGoogleNowFailReadAllCall(t *testing.T) {
	var counter int = 0

	gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{
		LogWhitelist: map[string]bool{
			"Could not ReadAll() body": true,
		},
		KnownBackends: []string{"googleNow"},
		TestBinary: filepath.Join(
			getDirName(), "..", "..", "..",
			"examples", "example-gateway", "build", "main.go",
		),
	})
	if !assert.NoError(t, err, "got bootstrap err") {
		return
	}
	defer gateway.Close()

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials",
		func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(200)
			if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
				t.Fatal("can't write fake response")
			}
			counter++
		},
	)

	cgateway := gateway.(*testGateway.ChildProcessGateway)
	cgateway.HTTPClient.Transport = &http.Transport{
		DisableKeepAlives:   false,
		MaxIdleConns:        500,
		MaxIdleConnsPerHost: 500,
		Dial: func(network string, addr string) (net.Conn, error) {
			dialer := &net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}

			conn, err := dialer.Dial(network, addr)
			if err != nil {
				return nil, err
			}

			return &failingConn{conn}, nil
		},
	}

	res, err := gateway.MakeRequest(
		"POST", "/googlenow/add-credentials",
		bytes.NewReader([]byte("junk data")),
	)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "short write")
	assert.Nil(t, res)
	assert.Equal(t, 0, counter)

	time.Sleep(10 * time.Millisecond)

	errLogs := gateway.GetErrorLogs()

	logLines := errLogs["Could not ReadAll() body"]
	assert.NotNil(t, logLines)
	assert.Equal(t, 1, len(logLines))

	line := logLines[0]
	lineStruct := map[string]interface{}{}
	jsonErr := json.Unmarshal([]byte(line), &lineStruct)
	if !assert.NoError(t, jsonErr, "cannot decode json lines") {
		return
	}

	errorField := lineStruct["error"].(string)
	assert.Equal(t, "unexpected EOF", errorField)
}

func TestAddCredentialsMissingAuthCode(t *testing.T) {
	var counter int = 0

	gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{
		KnownBackends: []string{"googleNow"},
		TestBinary: filepath.Join(
			getDirName(), "..", "..", "..",
			"examples", "example-gateway", "build", "main.go",
		),
	})

	if !assert.NoError(t, err, "got bootstrap err") {
		return
	}
	defer gateway.Close()

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials", func(w http.ResponseWriter, r *http.Request) {
			if r.FormValue("authCode") != "" {
				if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
					t.Fatal("can't write fake response")
				}
				counter++
			} else {
				if _, err := w.Write([]byte("{\"statusCode\":500}")); err != nil {
					t.Fatal("can't write fake response")
				}
			}
		},
	)

	res, err := gateway.MakeRequest(
		"POST", "/googlenow/add-credentials", bytes.NewReader(noAuthCodeBytes),
	)
	if !assert.NoError(t, err, "got http error") {
		return
	}

	assert.Equal(t, "200 OK", res.Status)
	assert.Equal(t, 0, counter)
}
<commit_msg>tests: add failing test for bad json payload<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package google_now_test

import (
	"bytes"
	"io/ioutil"
	"net"
	"net/http"
	"path/filepath"
	"runtime"
	"testing"
	"time"

	"encoding/json"

	"github.com/pkg/errors"
	"github.com/stretchr/testify/assert"
	"github.com/uber/zanzibar/test/lib/bench_gateway"
	"github.com/uber/zanzibar/test/lib/test_gateway"
)

var benchBytes = []byte("{\"authCode\":\"abcdef\"}")
var noAuthCodeBytes = []byte("{}")

func BenchmarkGoogleNowAddCredentials(b *testing.B) {
	gateway, err := benchGateway.CreateGateway(nil, &testGateway.Options{
		KnownBackends: []string{"googleNow"},
	})
	if err != nil {
		b.Error("got bootstrap err: " + err.Error())
		return
	}

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials", func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(200)
			if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
				panic(errors.New("can't write fake response"))
			}
		},
	)

	b.ResetTimer()

	// b.SetParallelism(100)
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			res, err := gateway.MakeRequest(
				"POST", "/googlenow/add-credentials",
				bytes.NewReader(benchBytes),
			)
			if err != nil {
				b.Error("got http error: " + err.Error())
				break
			}
			if res.Status != "200 OK" {
				b.Error("got bad status error: " + res.Status)
				break
			}

			_, err = ioutil.ReadAll(res.Body)
			if err != nil {
				b.Error("could not write response: " + res.Status)
				break
			}
			_ = res.Body.Close()
		}
	})

	b.StopTimer()
	gateway.Close()
	b.StartTimer()
}

func getDirName() string {
	_, file, _, _ := runtime.Caller(0)

	return filepath.Dir(file)
}

func TestAddCredentials(t *testing.T) {
	var counter int = 0

	gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{
		KnownBackends: []string{"googleNow"},
		TestBinary: filepath.Join(
			getDirName(), "..", "..", "..",
			"examples", "example-gateway", "build", "main.go",
		),
	})
	if !assert.NoError(t, err, "got bootstrap err") {
		return
	}
	defer gateway.Close()

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials", func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(200)
			if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
				t.Fatal("can't write fake response")
			}
			counter++
		},
	)

	res, err := gateway.MakeRequest(
		"POST", "/googlenow/add-credentials", bytes.NewReader(benchBytes),
	)
	if !assert.NoError(t, err, "got http error") {
		return
	}

	assert.Equal(t, "200 OK", res.Status)
	assert.Equal(t, 1, counter)
}

type failingConn struct {
	net.Conn
}

func (conn *failingConn) Write(b []byte) (int, error) {
	b = b[0 : len(b)-1]
	n, err := conn.Conn.Write(b)

	_ = conn.Conn.Close()
	return n, err
}

func TestGoogleNowFailReadAllCall(t *testing.T) {
	var counter int = 0

	gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{
		LogWhitelist: map[string]bool{
			"Could not ReadAll() body": true,
		},
		KnownBackends: []string{"googleNow"},
		TestBinary: filepath.Join(
			getDirName(), "..", "..", "..",
			"examples", "example-gateway", "build", "main.go",
		),
	})
	if !assert.NoError(t, err, "got bootstrap err") {
		return
	}
	defer gateway.Close()

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials",
		func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(200)
			if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
				t.Fatal("can't write fake response")
			}
			counter++
		},
	)

	cgateway := gateway.(*testGateway.ChildProcessGateway)
	cgateway.HTTPClient.Transport = &http.Transport{
		DisableKeepAlives:   false,
		MaxIdleConns:        500,
		MaxIdleConnsPerHost: 500,
		Dial: func(network string, addr string) (net.Conn, error) {
			dialer := &net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}

			conn, err := dialer.Dial(network, addr)
			if err != nil {
				return nil, err
			}

			return &failingConn{conn}, nil
		},
	}

	res, err := gateway.MakeRequest(
		"POST", "/googlenow/add-credentials",
		bytes.NewReader([]byte("junk data")),
	)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "short write")
	assert.Nil(t, res)
	assert.Equal(t, 0, counter)

	time.Sleep(10 * time.Millisecond)

	errLogs := gateway.GetErrorLogs()

	logLines := errLogs["Could not ReadAll() body"]
	assert.NotNil(t, logLines)
	assert.Equal(t, 1, len(logLines))

	line := logLines[0]
	lineStruct := map[string]interface{}{}
	jsonErr := json.Unmarshal([]byte(line), &lineStruct)
	if !assert.NoError(t, jsonErr, "cannot decode json lines") {
		return
	}

	errorField := lineStruct["error"].(string)
	assert.Equal(t, "unexpected EOF", errorField)
}

func TestGoogleNowFailJSONParsing(t *testing.T) {
	var counter int = 0

	gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{
		KnownBackends: []string{"googleNow"},
		TestBinary: filepath.Join(
			getDirName(), "..", "..", "..",
			"examples", "example-gateway", "build", "main.go",
		),
	})
	if !assert.NoError(t, err, "got bootstrap err") {
		return
	}
	defer gateway.Close()

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials", func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(200)
			if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
				t.Fatal("can't write fake response")
			}
			counter++
		},
	)

	res, err := gateway.MakeRequest(
		"POST", "/googlenow/add-credentials",
		bytes.NewReader([]byte("bad bytes")),
	)
	if !assert.NoError(t, err, "got http error") {
		return
	}

	assert.Equal(t, "400 Bad Request", res.Status)
	assert.Equal(t, 0, counter)

	respBytes, err := ioutil.ReadAll(res.Body)
	if !assert.NoError(t, err, "got http resp error") {
		return
	}

	assert.Equal(t,
		"Could not parse json: parse error: "+
			"invalid character 'b' after top-level value "+
			"near offset 0 of 'bad bytes'",
		string(respBytes),
	)
}

func TestAddCredentialsMissingAuthCode(t *testing.T) {
	var counter int = 0

	gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{
		KnownBackends: []string{"googleNow"},
		TestBinary: filepath.Join(
			getDirName(), "..", "..", "..",
			"examples", "example-gateway", "build", "main.go",
		),
	})

	if !assert.NoError(t, err, "got bootstrap err") {
		return
	}
	defer gateway.Close()

	gateway.Backends()["googleNow"].HandleFunc(
		"POST", "/add-credentials", func(w http.ResponseWriter, r *http.Request) {
			if r.FormValue("authCode") != "" {
				if _, err := w.Write([]byte("{\"statusCode\":200}")); err != nil {
					t.Fatal("can't write fake response")
				}
				counter++
			} else {
				if _, err := w.Write([]byte("{\"statusCode\":500}")); err != nil {
					t.Fatal("can't write fake response")
				}
			}
		},
	)

	res, err := gateway.MakeRequest(
		"POST", "/googlenow/add-credentials", bytes.NewReader(noAuthCodeBytes),
	)
	if !assert.NoError(t, err, "got http error") {
		return
	}

	assert.Equal(t, "200 OK", res.Status)
	assert.Equal(t, 0, counter)
}
<|endoftext|>


<commit_before>package logplus

import (
	"fmt"
	"io"
	"os"
	"sync"
	"time"
)

type Logger struct {
	output     io.Writer
	timeFormat string
	logLevel   LogLevel
	formatter  Formatter
	mutex      *sync.Mutex
}

func NewLogger(o io.Writer, tf string, l LogLevel, f Formatter) *Logger {
	return &Logger{
		output:     o,
		timeFormat: tf,
		logLevel:   l,
		formatter:  f,
		mutex:      new(sync.Mutex),
	}
}

func (logger *Logger) setTimeFormat(tf string) {
	logger.mutex.Lock()
	logger.timeFormat = tf
	logger.mutex.Unlock()
}

func (logger *Logger) setLevel(level LogLevel) {
	logger.mutex.Lock()
	logger.logLevel = level
	logger.mutex.Unlock()
}

func (logger *Logger) setOutput(out io.Writer) {
	logger.mutex.Lock()
	logger.output = out
	logger.mutex.Unlock()
}

func (logger *Logger) setFormatter(formatter Formatter) {
	logger.mutex.Lock()
	logger.formatter = formatter
	logger.mutex.Unlock()
}

func (logger *Logger) print(log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewLogMessage(NoColor, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	//info := fmt.Sprintf("%s [%s] <%d>", t, caller, pid)
	//s := fmt.Sprint(log...)
	//fmt.Fprint(logger.output, concat(": ", info, s))
	fmt.Fprint(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) printf(format string, log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewFormattedLogMessage(NoColor, format, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	//info := fmt.Sprintf("%s [%s] <%d>", t, caller, pid)
	//s := fmt.Sprintf(format, log...)
	//fmt.Fprintf(logger.output, concat(": ", info, s))
	fmt.Fprint(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) println(log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewLogMessage(NoColor, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	//info := fmt.Sprintf("%s [%s] <%d>", t, caller, pid)
	//s := fmt.Sprint(log...)
	//fmt.Fprintln(logger.output, concat(": ", info, s))
	fmt.Fprintln(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) coloredPrint(color Color, log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewLogMessage(color, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	//info := fmt.Sprintf("%s [%s] <%d>", t, caller, pid)
	//s := fmt.Sprint(log...)
	//fmt.Fprint(logger.output, concat(": ", info, concat("", color.String(), s, resetAll)))
	fmt.Fprint(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) coloredPrintf(color Color, format string, log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewFormattedLogMessage(color, format, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	//info := fmt.Sprintf("%s [%s] <%d>", t, caller, pid)
	//s := fmt.Sprintf(format, log...)
	//fmt.Fprint(logger.output, concat(": ", info, concat("", color.String(), s, resetAll)))

	fmt.Fprint(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) coloredPrintln(color Color, log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewLogMessage(color, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	//info := fmt.Sprintf("%s [%s] <%d>", t, caller, pid)
	//s := fmt.Sprint(log...)
	//fmt.Fprintln(logger.output, concat(": ", info, concat("", color.String(), s, resetAll)))

	fmt.Fprintln(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) leveledPrint(level LogLevel, log ...interface{}) {
	logger.mutex.Lock()

	if logger.isLogAvailable(level) {
		t := time.Now().Format(logger.timeFormat)
		caller := getCallInfo(4)
		pid := os.Getpid()

		msg := NewLogMessage(NoColor, log...)
		entry := NewLogEntry(level, t, caller, pid, msg)
		fmtLog := logger.formatter.Format(entry)

		fmt.Fprint(logger.output, fmtLog)

		switch level {
		case FATAL:
			os.Exit(1)
		case PANIC:
			panic(fmt.Sprint(log...))
		default:
		}
	}

	logger.mutex.Unlock()
}

func (logger *Logger) leveledPrintf(level LogLevel, format string, log ...interface{}) {
	logger.mutex.Lock()

	if logger.isLogAvailable(level) {
		t := time.Now().Format(logger.timeFormat)
		caller := getCallInfo(4)
		pid := os.Getpid()

		msg := NewFormattedLogMessage(NoColor, format, log...)
		entry := NewLogEntry(level, t, caller, pid, msg)
		fmtLog := logger.formatter.Format(entry)

		fmt.Fprint(logger.output, fmtLog)

		switch level {
		case FATAL:
			os.Exit(1)
		case PANIC:
			panic(fmt.Sprintf(format, log...))
		default:
		}
	}

	logger.mutex.Unlock()
}

func (logger *Logger) leveledPrintln(level LogLevel, log ...interface{}) {
	logger.mutex.Lock()

	if logger.isLogAvailable(level) {
		t := time.Now().Format(logger.timeFormat)
		caller := getCallInfo(4)
		pid := os.Getpid()

		msg := NewLogMessage(NoColor, log...)
		entry := NewLogEntry(level, t, caller, pid, msg)
		fmtLog := logger.formatter.Format(entry)

		fmt.Fprintln(logger.output, fmtLog)

		switch level {
		case FATAL:
			os.Exit(1)
		case PANIC:
			panic(fmt.Sprintln(log...))
		default:
		}
	}

	logger.mutex.Unlock()
}

func (logger *Logger) isLogAvailable(level LogLevel) bool {
	if level <= logger.logLevel {
		return true
	}
	return false
}
<commit_msg>refactoring<commit_after>package logplus

import (
	"fmt"
	"io"
	"os"
	"sync"
	"time"
)

type Logger struct {
	output     io.Writer
	timeFormat string
	logLevel   LogLevel
	formatter  Formatter
	mutex      *sync.Mutex
}

func NewLogger(o io.Writer, tf string, l LogLevel, f Formatter) *Logger {
	return &Logger{
		output:     o,
		timeFormat: tf,
		logLevel:   l,
		formatter:  f,
		mutex:      new(sync.Mutex),
	}
}

func (logger *Logger) setTimeFormat(tf string) {
	logger.mutex.Lock()
	logger.timeFormat = tf
	logger.mutex.Unlock()
}

func (logger *Logger) setLevel(level LogLevel) {
	logger.mutex.Lock()
	logger.logLevel = level
	logger.mutex.Unlock()
}

func (logger *Logger) setOutput(out io.Writer) {
	logger.mutex.Lock()
	logger.output = out
	logger.mutex.Unlock()
}

func (logger *Logger) setFormatter(formatter Formatter) {
	logger.mutex.Lock()
	logger.formatter = formatter
	logger.mutex.Unlock()
}

func (logger *Logger) print(log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewLogMessage(NoColor, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	fmt.Fprint(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) printf(format string, log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewFormattedLogMessage(NoColor, format, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	fmt.Fprint(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) println(log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewLogMessage(NoColor, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	fmt.Fprintln(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) coloredPrint(color Color, log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewLogMessage(color, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	fmt.Fprint(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) coloredPrintf(color Color, format string, log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewFormattedLogMessage(color, format, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	fmt.Fprint(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) coloredPrintln(color Color, log ...interface{}) {
	logger.mutex.Lock()

	t := time.Now().Format(logger.timeFormat)
	caller := getCallInfo(3)
	pid := os.Getpid()

	msg := NewLogMessage(color, log...)
	entry := NewLogEntry(none, t, caller, pid, msg)
	fmtLog := logger.formatter.Format(entry)

	fmt.Fprintln(logger.output, fmtLog)

	logger.mutex.Unlock()
}

func (logger *Logger) leveledPrint(level LogLevel, log ...interface{}) {
	logger.mutex.Lock()

	if logger.isLogAvailable(level) {
		t := time.Now().Format(logger.timeFormat)
		caller := getCallInfo(4)
		pid := os.Getpid()

		msg := NewLogMessage(NoColor, log...)
		entry := NewLogEntry(level, t, caller, pid, msg)
		fmtLog := logger.formatter.Format(entry)

		fmt.Fprint(logger.output, fmtLog)

		switch level {
		case FATAL:
			os.Exit(1)
		case PANIC:
			panic(fmt.Sprint(log...))
		default:
		}
	}

	logger.mutex.Unlock()
}

func (logger *Logger) leveledPrintf(level LogLevel, format string, log ...interface{}) {
	logger.mutex.Lock()

	if logger.isLogAvailable(level) {
		t := time.Now().Format(logger.timeFormat)
		caller := getCallInfo(4)
		pid := os.Getpid()

		msg := NewFormattedLogMessage(NoColor, format, log...)
		entry := NewLogEntry(level, t, caller, pid, msg)
		fmtLog := logger.formatter.Format(entry)

		fmt.Fprint(logger.output, fmtLog)

		switch level {
		case FATAL:
			os.Exit(1)
		case PANIC:
			panic(fmt.Sprintf(format, log...))
		default:
		}
	}

	logger.mutex.Unlock()
}

func (logger *Logger) leveledPrintln(level LogLevel, log ...interface{}) {
	logger.mutex.Lock()

	if logger.isLogAvailable(level) {
		t := time.Now().Format(logger.timeFormat)
		caller := getCallInfo(4)
		pid := os.Getpid()

		msg := NewLogMessage(NoColor, log...)
		entry := NewLogEntry(level, t, caller, pid, msg)
		fmtLog := logger.formatter.Format(entry)

		fmt.Fprintln(logger.output, fmtLog)

		switch level {
		case FATAL:
			os.Exit(1)
		case PANIC:
			panic(fmt.Sprintln(log...))
		default:
		}
	}

	logger.mutex.Unlock()
}

func (logger *Logger) isLogAvailable(level LogLevel) bool {
	if level <= logger.logLevel {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha256"
	"encoding/hex"
	"github.com/codegangsta/cli"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func cmdGet(c *cli.Context) {

	verbose = c.GlobalBool("verbose")

	path := c.Args().Get(0)
	key := c.String("key")
	file := c.String("file")

	if len(path) < 1 {
		path = "." // default to current directory
	}

	if len(file) < 1 {
		printFatal("Dependency file is not provided.")
	}

	if _, err := os.Stat(file); os.IsNotExist(err) {
		printFatal("Dependency file '%s' does not exist.", file)
	}

	if len(key) < 1 {
		key = strings.ToLower(filepath.Base(file))
	}
	hash := checksum(file)
	fullPath := filepath.Join(CachePath, strings.Join([]string{key, hash}, "-")) + ".tar.gz"

	// get cache if exists
	if _, err := os.Stat(fullPath); err == nil {
		printInfo("Fetching cache '%s'. Please, wait...", key)

		args := []string{
			"-xzf",
			fullPath,
			"-C",
			path,
		}

		err := exec.Command("tar", args...).Run()
		checkError(err)
	}
}

func cmdSet(c *cli.Context) {

	verbose = c.GlobalBool("verbose")

	path := c.Args().Get(0)
	key := c.String("key")
	file := c.String("file")

	if len(path) < 1 {
		printFatal("Path to content is not provided as an argument.")
	}

	if _, err := os.Stat(path); os.IsNotExist(err) {
		printFatal("Content '%s' does not exist.", path)
	}

	if len(file) < 1 {
		printFatal("Dependency file is not provided.")
	}

	if _, err := os.Stat(file); os.IsNotExist(err) {
		printFatal("Dependency file '%s' does not exist.", file)
	}

	if _, err := os.Stat(CachePath); os.IsNotExist(err) {
		if os.MkdirAll(CachePath, dirMode) != nil {
			printFatal("Couldn't create cache directory. "+
				"Is the %s directory writable?", CachePath)
		}
	}

	if len(key) < 1 {
		key = strings.ToLower(filepath.Base(file))
	}

	hash := checksum(file)
	fullPath := filepath.Join(CachePath, strings.Join([]string{key, hash}, "-")) + ".tar.gz"

	// cache contents only if it doesn't exist already
	if _, err := os.Stat(fullPath); os.IsNotExist(err) {
		printInfo("Caching '%s'. Please, wait...", key)

		args := []string{
			"-czf",
			fullPath,
			path,
		}

		err := exec.Command("tar", args...).Run()
		checkError(err)
	}
	go clean(key)
}

/*
 * Calculates SHA256 checksum of a file
 */
func checksum(file string) string {
	hasher := sha256.New()
	contents, err := ioutil.ReadFile(file)
	checkError(err)

	hasher.Write(contents)
	return hex.EncodeToString(hasher.Sum(nil))
}

/*
 * Cleans old caches
 */
func clean(key string) {
	files := fileSorter(CachePath, "^"+key+"-")

	for index, file := range files {
		if index+1 > CacheKeep {
			os.Remove(file.Path)
		}
	}
}
<commit_msg>Fix cleaning up cache<commit_after>package main

import (
	"crypto/sha256"
	"encoding/hex"
	"github.com/codegangsta/cli"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func cmdGet(c *cli.Context) {

	verbose = c.GlobalBool("verbose")

	path := c.Args().Get(0)
	key := c.String("key")
	file := c.String("file")

	if len(path) < 1 {
		path = "." // default to current directory
	}

	if len(file) < 1 {
		printFatal("Dependency file is not provided.")
	}

	if _, err := os.Stat(file); os.IsNotExist(err) {
		printFatal("Dependency file '%s' does not exist.", file)
	}

	if len(key) < 1 {
		key = strings.ToLower(filepath.Base(file))
	}
	hash := checksum(file)
	fullPath := filepath.Join(CachePath, strings.Join([]string{key, hash}, "-")) + ".tar.gz"

	// get cache if exists
	if _, err := os.Stat(fullPath); err == nil {
		printInfo("Fetching cache '%s'. Please, wait...", key)

		args := []string{
			"-xzf",
			fullPath,
			"-C",
			path,
		}

		err := exec.Command("tar", args...).Run()
		checkError(err)
	}
}

func cmdSet(c *cli.Context) {

	verbose = c.GlobalBool("verbose")

	path := c.Args().Get(0)
	key := c.String("key")
	file := c.String("file")

	if len(path) < 1 {
		printFatal("Path to content is not provided as an argument.")
	}

	if _, err := os.Stat(path); os.IsNotExist(err) {
		printFatal("Content '%s' does not exist.", path)
	}

	if len(file) < 1 {
		printFatal("Dependency file is not provided.")
	}

	if _, err := os.Stat(file); os.IsNotExist(err) {
		printFatal("Dependency file '%s' does not exist.", file)
	}

	if _, err := os.Stat(CachePath); os.IsNotExist(err) {
		if os.MkdirAll(CachePath, dirMode) != nil {
			printFatal("Couldn't create cache directory. "+
				"Is the %s directory writable?", CachePath)
		}
	}

	if len(key) < 1 {
		key = strings.ToLower(filepath.Base(file))
	}

	hash := checksum(file)
	fullPath := filepath.Join(CachePath, strings.Join([]string{key, hash}, "-")) + ".tar.gz"

	// cache contents only if it doesn't exist already
	if _, err := os.Stat(fullPath); os.IsNotExist(err) {
		printInfo("Caching '%s'. Please, wait...", key)

		args := []string{
			"-czf",
			fullPath,
			path,
		}

		err := exec.Command("tar", args...).Run()
		checkError(err)
	}
	clean(key)
}

/*
 * Calculates SHA256 checksum of a file
 */
func checksum(file string) string {
	hasher := sha256.New()
	contents, err := ioutil.ReadFile(file)
	checkError(err)

	hasher.Write(contents)
	return hex.EncodeToString(hasher.Sum(nil))
}

/*
 * Cleans old caches
 */
func clean(key string) {
	files := fileSorter(CachePath, "^"+key+"-")

	for index, file := range files {
		if index+1 > CacheKeep {
			os.Remove(file.Path)
		}
	}
}
<|endoftext|>