Merge upstream
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..66be63a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+logrus
diff --git a/README.md b/README.md
index ef107e7..3a6aced 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,10 @@
 # Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>&nbsp;[![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus)
 
 Logrus is a structured logger for Go (golang), completely API compatible with
-the standard library logger. [Godoc][godoc].
+the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
+yet stable (pre 1.0), the core API is unlikely change much but please version
+control your Logrus to make sure you aren't fetching latest `master` on every
+build.**
 
 Nicely color-coded in development (when a TTY is attached, otherwise just
 plain text):
@@ -42,9 +45,71 @@
 
 #### Example
 
-Note again that Logrus is API compatible with the stdlib logger, so if you
-remove the `log` import and create a global `log` variable as below it will just
-work.
+The simplest way to use Logrus is simply the package-level exported logger:
+
+```go
+package main
+
+import (
+  log "github.com/Sirupsen/logrus"
+)
+
+func main() {
+  log.WithFields(log.Fields{
+    "animal": "walrus",
+  }).Info("A walrus appears")
+}
+```
+
+Note that it's completely api-compatible with the stdlib logger, so you can
+replace your `log` imports everywhere with `log "github.com/Sirupsen/logrus"`
+and you'll now have the flexibility of Logrus. You can customize it all you
+want:
+
+```go
+package main
+
+import (
+  "os"
+  log "github.com/Sirupsen/logrus"
+  "github.com/Sirupsen/logrus/hooks/airbrake"
+)
+
+func init() {
+  // Log as JSON instead of the default ASCII formatter.
+  log.SetFormatter(logrus.JSONFormatter)
+
+  // Use the Airbrake hook to report errors that have Error severity or above to
+  // an exception tracker. You can create custom hooks, see the Hooks section.
+  log.AddHook(logrus_airbrake.AirbrakeHook)
+
+  // Output to stderr instead of stdout, could also be a file.
+  log.SetOuput(os.Stderr)
+
+  // Only log the warning severity or above.
+  log.SetLevel(logrus.WarnLevel)
+}
+
+func main() {
+  log.WithFields(log.Fields{
+    "animal": "walrus",
+    "size":   10,
+  }).Info("A group of walrus emerges from the ocean")
+
+  log.WithFields(log.Fields{
+    "omg":    true,
+    "number": 122,
+  }).Warn("The group's number increased tremendously!")
+
+  log.WithFields(log.Fields{
+    "omg":    true,
+    "number": 100,
+  }).Fatal("The ice breaks!")
+}
+```
+
+For more advanced usage such as logging to multiple locations from the same
+application, you can also create an instance of the `logrus` Logger:
 
 ```go
 package main
@@ -53,28 +118,18 @@
   "github.com/Sirupsen/logrus"
 )
 
+// Create a new instance of the logger. You can have any number of instances.
 var log = logrus.New()
 
-func init() {
-  log.Formatter = new(logrus.JSONFormatter)
-  log.Formatter = new(logrus.TextFormatter) // default
-}
-
 func main() {
-  log.WithFields(logrus.Fields{
+  // The API for setting attributes is a little different than the package level
+  // exported logger. See Godoc.
+  log.Out = os.Stderr
+
+  log.WithFields(log.Fields{
     "animal": "walrus",
     "size":   10,
   }).Info("A group of walrus emerges from the ocean")
-
-  log.WithFields(logrus.Fields{
-    "omg":    true,
-    "number": 122,
-  }).Warn("The group's number increased tremendously!")
-
-  log.WithFields(logrus.Fields{
-    "omg":    true,
-    "number": 100,
-  }).Fatal("The ice breaks!")
 }
 ```
 
@@ -86,12 +141,10 @@
 discoverable:
 
 ```go
-log = logrus.New()
-
-log.WithFields(logrus.Fields{
+log.WithFields(log.Fields{
   "event": event,
   "topic": topic,
-  "key": key
+  "key": key,
 }).Fatal("Failed to send event")
 ```
 
@@ -112,10 +165,12 @@
 
 ```go
 // Not the real implementation of the Airbrake hook. Just a simple sample.
-var log = logrus.New()
+import (
+  log "github.com/Sirupsen/logrus"
+)
 
 func init() {
-  log.Hooks.Add(new(AirbrakeHook))
+  log.AddHook(new(AirbrakeHook))
 }
 
 type AirbrakeHook struct{}
@@ -125,7 +180,7 @@
 func (hook *AirbrakeHook) Fire(entry *logrus.Entry) error {
   err := airbrake.Notify(entry.Data["error"].(error))
   if err != nil {
-    log.WithFields(logrus.Fields{
+    log.WithFields(log.Fields{
       "source":   "airbrake",
       "endpoint": airbrake.Endpoint,
     }).Info("Failed to send error to Airbrake")
@@ -135,11 +190,11 @@
 }
 
 // `Levels()` returns a slice of `Levels` the hook is fired for.
-func (hook *AirbrakeHook) Levels() []logrus.Level {
-  return []logrus.Level{
-    logrus.Error,
-    logrus.Fatal,
-    logrus.Panic,
+func (hook *AirbrakeHook) Levels() []log.Level {
+  return []log.Level{
+    log.ErrorLevel,
+    log.FatalLevel,
+    log.PanicLevel,
   }
 }
 ```
@@ -148,15 +203,14 @@
 
 ```go
 import (
-  "log/syslog"
-  "github.com/Sirupsen/logrus"
+  log "github.com/Sirupsen/logrus"
   "github.com/Sirupsen/logrus/hooks/airbrake"
   "github.com/Sirupsen/logrus/hooks/syslog"
 )
 
 func init() {
-  log.Hooks.Add(new(logrus_airbrake.AirbrakeHook))
-  log.Hooks.Add(logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, ""))
+  log.AddHook(new(logrus_airbrake.AirbrakeHook))
+  log.AddHook(logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, ""))
 }
 ```
 
@@ -188,10 +242,10 @@
 
 ```go
 // Will log anything that is info or above (warn, error, fatal, panic). Default.
-log.Level = logrus.Info
+log.SetLevel(log.InfoLevel)
 ```
 
-It may be useful to set `log.Level = logrus.Debug` in a debug or verbose
+It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose
 environment if your application has that.
 
 #### Entries
@@ -214,16 +268,18 @@
 could do:
 
 ```go
+import (
+  log "github.com/Sirupsen/logrus"
+)
+
 init() {
   // do something here to set environment depending on an environment variable
   // or command-line flag
-  log := logrus.New()
-
   if Environment == "production" {
-    log.Formatter = new(logrus.JSONFormatter)
+    log.SetFormatter(logrus.JSONFormatter)
   } else {
     // The TextFormatter is default, you don't actually have to do this.
-    log.Formatter = new(logrus.TextFormatter)
+    log.SetFormatter(logrus.TextFormatter)
   }
 }
 ```
@@ -255,9 +311,12 @@
 type MyJSONFormatter struct {
 }
 
-log.Formatter = new(MyJSONFormatter)
+log.SetFormatter(new(MyJSONFormatter))
 
 func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
+  // Note this doesn't include Time, Level and Message which are available on
+  // the Entry. Consult `godoc` on information about those fields or read the
+  // source of the official loggers.
   serialized, err := json.Marshal(entry.Data)
     if err != nil {
       return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
@@ -266,4 +325,11 @@
 }
 ```
 
+#### Rotation
+
+Log rotation is not provided with Logrus. Log rotation should be done by an
+external program (like `logrotated(8)`) that can compress and delete old log
+entries. It should not be a feature of the application-level logger.
+
+
 [godoc]: https://godoc.org/github.com/Sirupsen/logrus
diff --git a/entry.go b/entry.go
index 08cc15f..44ff056 100644
--- a/entry.go
+++ b/entry.go
@@ -8,9 +8,24 @@
 	"time"
 )
 
+// An entry is the final or intermediate Logrus logging entry. It containts all
+// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
+// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
+// passed around as much as you wish to avoid field duplication.
 type Entry struct {
 	Logger *Logger
-	Data   Fields
+
+	// Contains all the fields set by the user.
+	Data Fields
+
+	// Time at which the log entry was created
+	Time time.Time
+
+	// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
+	Level Level
+
+	// Message passed to Debug, Info, Warn, Error, Fatal or Panic
+	Message string
 }
 
 var baseTimestamp time.Time
@@ -23,11 +38,14 @@
 	}
 }
 
+// Returns a reader for the entry, which is a proxy to the formatter.
 func (entry *Entry) Reader() (*bytes.Buffer, error) {
 	serialized, err := entry.Logger.Formatter.Format(entry)
 	return bytes.NewBuffer(serialized), err
 }
 
+// Returns the string representation from the reader and ultimately the
+// formatter.
 func (entry *Entry) String() (string, error) {
 	reader, err := entry.Reader()
 	if err != nil {
@@ -37,10 +55,12 @@
 	return reader.String(), err
 }
 
+// Add a single field to the Entry.
 func (entry *Entry) WithField(key string, value interface{}) *Entry {
 	return entry.WithFields(Fields{key: value})
 }
 
+// Add a map of fields to the Entry.
 func (entry *Entry) WithFields(fields Fields) *Entry {
 	data := Fields{}
 	for k, v := range entry.Data {
@@ -52,12 +72,12 @@
 	return &Entry{Logger: entry.Logger, Data: data}
 }
 
-func (entry *Entry) log(level string, levelInt Level, msg string) string {
-	entry.Data["time"] = time.Now().String()
-	entry.Data["level"] = level
-	entry.Data["msg"] = msg
+func (entry *Entry) log(level Level, msg string) string {
+	entry.Time = time.Now()
+	entry.Level = level
+	entry.Message = msg
 
-	if err := entry.Logger.Hooks.Fire(levelInt, entry); err != nil {
+	if err := entry.Logger.Hooks.Fire(level, entry); err != nil {
 		fmt.Fprintf(os.Stderr, "Failed to fire hook", err)
 	}
 
@@ -78,8 +98,8 @@
 }
 
 func (entry *Entry) Debug(args ...interface{}) {
-	if entry.Logger.Level >= Debug {
-		entry.log("debug", Debug, fmt.Sprint(args...))
+	if entry.Logger.Level >= DebugLevel {
+		entry.log(DebugLevel, fmt.Sprint(args...))
 	}
 }
 
@@ -88,33 +108,33 @@
 }
 
 func (entry *Entry) Info(args ...interface{}) {
-	if entry.Logger.Level >= Info {
-		entry.log("info", Info, fmt.Sprint(args...))
+	if entry.Logger.Level >= InfoLevel {
+		entry.log(InfoLevel, fmt.Sprint(args...))
 	}
 }
 
 func (entry *Entry) Warn(args ...interface{}) {
-	if entry.Logger.Level >= Warn {
-		entry.log("warning", Warn, fmt.Sprint(args...))
+	if entry.Logger.Level >= WarnLevel {
+		entry.log(WarnLevel, fmt.Sprint(args...))
 	}
 }
 
 func (entry *Entry) Error(args ...interface{}) {
-	if entry.Logger.Level >= Error {
-		entry.log("error", Error, fmt.Sprint(args...))
+	if entry.Logger.Level >= ErrorLevel {
+		entry.log(ErrorLevel, fmt.Sprint(args...))
 	}
 }
 
 func (entry *Entry) Fatal(args ...interface{}) {
-	if entry.Logger.Level >= Fatal {
-		entry.log("fatal", Fatal, fmt.Sprint(args...))
+	if entry.Logger.Level >= FatalLevel {
+		entry.log(FatalLevel, fmt.Sprint(args...))
 	}
 	os.Exit(1)
 }
 
 func (entry *Entry) Panic(args ...interface{}) {
-	if entry.Logger.Level >= Panic {
-		msg := entry.log("panic", Panic, fmt.Sprint(args...))
+	if entry.Logger.Level >= PanicLevel {
+		msg := entry.log(PanicLevel, fmt.Sprint(args...))
 		panic(msg)
 	}
 	panic(fmt.Sprint(args...))
@@ -123,13 +143,13 @@
 // Entry Printf family functions
 
 func (entry *Entry) Debugf(format string, args ...interface{}) {
-	if entry.Logger.Level >= Debug {
+	if entry.Logger.Level >= DebugLevel {
 		entry.Debug(fmt.Sprintf(format, args...))
 	}
 }
 
 func (entry *Entry) Infof(format string, args ...interface{}) {
-	if entry.Logger.Level >= Info {
+	if entry.Logger.Level >= InfoLevel {
 		entry.Info(fmt.Sprintf(format, args...))
 	}
 }
@@ -139,7 +159,7 @@
 }
 
 func (entry *Entry) Warnf(format string, args ...interface{}) {
-	if entry.Logger.Level >= Warn {
+	if entry.Logger.Level >= WarnLevel {
 		entry.Warn(fmt.Sprintf(format, args...))
 	}
 }
@@ -149,19 +169,19 @@
 }
 
 func (entry *Entry) Errorf(format string, args ...interface{}) {
-	if entry.Logger.Level >= Error {
+	if entry.Logger.Level >= ErrorLevel {
 		entry.Error(fmt.Sprintf(format, args...))
 	}
 }
 
 func (entry *Entry) Fatalf(format string, args ...interface{}) {
-	if entry.Logger.Level >= Fatal {
+	if entry.Logger.Level >= FatalLevel {
 		entry.Fatal(fmt.Sprintf(format, args...))
 	}
 }
 
 func (entry *Entry) Panicf(format string, args ...interface{}) {
-	if entry.Logger.Level >= Panic {
+	if entry.Logger.Level >= PanicLevel {
 		entry.Panic(fmt.Sprintf(format, args...))
 	}
 }
@@ -169,13 +189,13 @@
 // Entry Println family functions
 
 func (entry *Entry) Debugln(args ...interface{}) {
-	if entry.Logger.Level >= Debug {
+	if entry.Logger.Level >= DebugLevel {
 		entry.Debug(entry.sprintlnn(args...))
 	}
 }
 
 func (entry *Entry) Infoln(args ...interface{}) {
-	if entry.Logger.Level >= Info {
+	if entry.Logger.Level >= InfoLevel {
 		entry.Info(entry.sprintlnn(args...))
 	}
 }
@@ -185,7 +205,7 @@
 }
 
 func (entry *Entry) Warnln(args ...interface{}) {
-	if entry.Logger.Level >= Warn {
+	if entry.Logger.Level >= WarnLevel {
 		entry.Warn(entry.sprintlnn(args...))
 	}
 }
@@ -195,19 +215,19 @@
 }
 
 func (entry *Entry) Errorln(args ...interface{}) {
-	if entry.Logger.Level >= Error {
+	if entry.Logger.Level >= ErrorLevel {
 		entry.Error(entry.sprintlnn(args...))
 	}
 }
 
 func (entry *Entry) Fatalln(args ...interface{}) {
-	if entry.Logger.Level >= Fatal {
+	if entry.Logger.Level >= FatalLevel {
 		entry.Fatal(entry.sprintlnn(args...))
 	}
 }
 
 func (entry *Entry) Panicln(args ...interface{}) {
-	if entry.Logger.Level >= Panic {
+	if entry.Logger.Level >= PanicLevel {
 		entry.Panic(entry.sprintlnn(args...))
 	}
 }
diff --git a/exported.go b/exported.go
new file mode 100644
index 0000000..383ce93
--- /dev/null
+++ b/exported.go
@@ -0,0 +1,177 @@
+package logrus
+
+import (
+	"io"
+)
+
+var (
+	// std is the name of the standard logger in stdlib `log`
+	std = New()
+)
+
+// SetOutput sets the standard logger output.
+func SetOutput(out io.Writer) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.Out = out
+}
+
+// SetFormatter sets the standard logger formatter.
+func SetFormatter(formatter Formatter) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.Formatter = formatter
+}
+
+// SetLevel sets the standard logger level.
+func SetLevel(level Level) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.Level = level
+}
+
+// AddHook adds a hook to the standard logger hooks.
+func AddHook(hook Hook) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.Hooks.Add(hook)
+}
+
+// WithField creates an entry from the standard logger and adds a field to
+// it. If you want multiple fields, use `WithFields`.
+//
+// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
+// or Panic on the Entry it returns.
+func WithField(key string, value interface{}) *Entry {
+	return std.WithField(key, value)
+}
+
+// WithFields creates an entry from the standard logger and adds multiple
+// fields to it. This is simply a helper for `WithField`, invoking it
+// once for each field.
+//
+// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
+// or Panic on the Entry it returns.
+func WithFields(fields Fields) *Entry {
+	return std.WithFields(fields)
+}
+
+// Debug logs a message at level Debug on the standard logger.
+func Debug(args ...interface{}) {
+	std.Debug(args...)
+}
+
+// Print logs a message at level Info on the standard logger.
+func Print(args ...interface{}) {
+	std.Print(args...)
+}
+
+// Info logs a message at level Info on the standard logger.
+func Info(args ...interface{}) {
+	std.Info(args...)
+}
+
+// Warn logs a message at level Warn on the standard logger.
+func Warn(args ...interface{}) {
+	std.Warn(args...)
+}
+
+// Warning logs a message at level Warn on the standard logger.
+func Warning(args ...interface{}) {
+	std.Warning(args...)
+}
+
+// Error logs a message at level Error on the standard logger.
+func Error(args ...interface{}) {
+	std.Error(args...)
+}
+
+// Panic logs a message at level Panic on the standard logger.
+func Panic(args ...interface{}) {
+	std.Panic(args...)
+}
+
+// Fatal logs a message at level Fatal on the standard logger.
+func Fatal(args ...interface{}) {
+	std.Fatal(args...)
+}
+
+// Debugf logs a message at level Debugf on the standard logger.
+func Debugf(format string, args ...interface{}) {
+	std.Debugf(format, args...)
+}
+
+// Printf logs a message at level Info on the standard logger.
+func Printf(format string, args ...interface{}) {
+	std.Printf(format, args...)
+}
+
+// Infof logs a message at level Info on the standard logger.
+func Infof(format string, args ...interface{}) {
+	std.Infof(format, args...)
+}
+
+// Warnf logs a message at level Warn on the standard logger.
+func Warnf(format string, args ...interface{}) {
+	std.Warnf(format, args...)
+}
+
+// Warningf logs a message at level Warn on the standard logger.
+func Warningf(format string, args ...interface{}) {
+	std.Warningf(format, args...)
+}
+
+// Errorf logs a message at level Error on the standard logger.
+func Errorf(format string, args ...interface{}) {
+	std.Errorf(format, args...)
+}
+
+// Panicf logs a message at level Pancf on the standard logger.
+func Panicf(format string, args ...interface{}) {
+	std.Panicf(format, args...)
+}
+
+// Fatalf logs a message at level Fatal on the standard logger.
+func Fatalf(format string, args ...interface{}) {
+	std.Fatalf(format, args...)
+}
+
+// Debugln logs a message at level Debug on the standard logger.
+func Debugln(args ...interface{}) {
+	std.Debugln(args...)
+}
+
+// Println logs a message at level Info on the standard logger.
+func Println(args ...interface{}) {
+	std.Println(args...)
+}
+
+// Infoln logs a message at level Info on the standard logger.
+func Infoln(args ...interface{}) {
+	std.Infoln(args...)
+}
+
+// Warnln logs a message at level Warn on the standard logger.
+func Warnln(args ...interface{}) {
+	std.Warnln(args...)
+}
+
+// Warningln logs a message at level Warn on the standard logger.
+func Warningln(args ...interface{}) {
+	std.Warningln(args...)
+}
+
+// Errorln logs a message at level Error on the standard logger.
+func Errorln(args ...interface{}) {
+	std.Errorln(args...)
+}
+
+// Panicln logs a message at level Panic on the standard logger.
+func Panicln(args ...interface{}) {
+	std.Panicln(args...)
+}
+
+// Fatalln logs a message at level Fatal on the standard logger.
+func Fatalln(args ...interface{}) {
+	std.Fatalln(args...)
+}
diff --git a/formatter.go b/formatter.go
index 3a2eff5..fc0ebd7 100644
--- a/formatter.go
+++ b/formatter.go
@@ -1,5 +1,9 @@
 package logrus
 
+import (
+	"time"
+)
+
 // The Formatter interface is used to implement a custom Formatter. It takes an
 // `Entry`. It exposes all the fields, including the default ones:
 //
@@ -13,3 +17,38 @@
 type Formatter interface {
 	Format(*Entry) ([]byte, error)
 }
+
+// This is to not silently overwrite `time`, `msg` and `level` fields when
+// dumping it. If this code wasn't there doing:
+//
+//  logrus.WithField("level", 1).Info("hello")
+//
+// Would just silently drop the user provided level. Instead with this code
+// it'll logged as:
+//
+//  {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
+//
+// It's not exported because it's still using Data in an opionated way. It's to
+// avoid code duplication between the two default formatters.
+func prefixFieldClashes(entry *Entry) {
+	_, ok := entry.Data["time"]
+	if ok {
+		entry.Data["fields.time"] = entry.Data["time"]
+	}
+
+	entry.Data["time"] = entry.Time.Format(time.RFC3339)
+
+	_, ok = entry.Data["msg"]
+	if ok {
+		entry.Data["fields.msg"] = entry.Data["msg"]
+	}
+
+	entry.Data["msg"] = entry.Message
+
+	_, ok = entry.Data["level"]
+	if ok {
+		entry.Data["fields.level"] = entry.Data["level"]
+	}
+
+	entry.Data["level"] = entry.Level.String()
+}
diff --git a/hook_test.go b/hook_test.go
index 24a02c3..13f34cb 100644
--- a/hook_test.go
+++ b/hook_test.go
@@ -17,12 +17,12 @@
 
 func (hook *TestHook) Levels() []Level {
 	return []Level{
-		Debug,
-		Info,
-		Warn,
-		Error,
-		Fatal,
-		Panic,
+		DebugLevel,
+		InfoLevel,
+		WarnLevel,
+		ErrorLevel,
+		FatalLevel,
+		PanicLevel,
 	}
 }
 
@@ -49,12 +49,12 @@
 
 func (hook *ModifyHook) Levels() []Level {
 	return []Level{
-		Debug,
-		Info,
-		Warn,
-		Error,
-		Fatal,
-		Panic,
+		DebugLevel,
+		InfoLevel,
+		WarnLevel,
+		ErrorLevel,
+		FatalLevel,
+		PanicLevel,
 	}
 }
 
@@ -95,7 +95,7 @@
 
 func (hook *ErrorHook) Levels() []Level {
 	return []Level{
-		Error,
+		ErrorLevel,
 	}
 }
 
diff --git a/hooks/airbrake/airbrake.go b/hooks/airbrake/airbrake.go
index d92dc88..880d21e 100644
--- a/hooks/airbrake/airbrake.go
+++ b/hooks/airbrake/airbrake.go
@@ -47,8 +47,8 @@
 
 func (hook *AirbrakeHook) Levels() []logrus.Level {
 	return []logrus.Level{
-		logrus.Error,
-		logrus.Fatal,
-		logrus.Panic,
+		logrus.ErrorLevel,
+		logrus.FatalLevel,
+		logrus.PanicLevel,
 	}
 }
diff --git a/json_formatter.go b/json_formatter.go
index cb3489e..c0e2d18 100644
--- a/json_formatter.go
+++ b/json_formatter.go
@@ -9,6 +9,8 @@
 }
 
 func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
+	prefixFieldClashes(entry)
+
 	serialized, err := json.Marshal(entry.Data)
 	if err != nil {
 		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
diff --git a/logger.go b/logger.go
index a545afd..7374fe3 100644
--- a/logger.go
+++ b/logger.go
@@ -47,7 +47,7 @@
 		Out:       os.Stdout,
 		Formatter: new(TextFormatter),
 		Hooks:     make(levelHooks),
-		Level:     Info,
+		Level:     InfoLevel,
 	}
 }
 
diff --git a/logrus.go b/logrus.go
index 2376db3..79df39c 100644
--- a/logrus.go
+++ b/logrus.go
@@ -10,25 +10,45 @@
 // Level type
 type Level uint8
 
+// Convert the Level to a string. E.g. PanicLevel becomes "panic".
+func (level Level) String() string {
+	switch level {
+	case DebugLevel:
+		return "debug"
+	case InfoLevel:
+		return "info"
+	case WarnLevel:
+		return "warning"
+	case ErrorLevel:
+		return "error"
+	case FatalLevel:
+		return "fatal"
+	case PanicLevel:
+		return "panic"
+	}
+
+	return "unknown"
+}
+
 // These are the different logging levels. You can set the logging level to log
 // on your instance of logger, obtained with `logrus.New()`.
 const (
-	// Panic level, highest level of severity. Logs and then calls panic with the
+	// PanicLevel level, highest level of severity. Logs and then calls panic with the
 	// message passed to Debug, Info, ...
-	Panic Level = iota
-	// Fatal level. Logs and then calls `os.Exit(1)`. It will exit even if the
+	PanicLevel Level = iota
+	// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
 	// logging level is set to Panic.
-	Fatal
-	// Error level. Logs. Used for errors that should definitely be noted.
+	FatalLevel
+	// ErrorLevel level. Logs. Used for errors that should definitely be noted.
 	// Commonly used for hooks to send errors to an error tracking service.
-	Error
-	// Warn level. Non-critical entries that deserve eyes.
-	Warn
-	// Info level. General operational entries about what's going on inside the
+	ErrorLevel
+	// WarnLevel level. Non-critical entries that deserve eyes.
+	WarnLevel
+	// InfoLevel level. General operational entries about what's going on inside the
 	// application.
-	Info
-	// Debug level. Usually only enabled when debugging. Very verbose logging.
-	Debug
+	InfoLevel
+	// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
+	DebugLevel
 )
 
 // Won't compile if StdLogger can't be realized by a log.Logger
diff --git a/logrus_test.go b/logrus_test.go
index 82187ae..6202300 100644
--- a/logrus_test.go
+++ b/logrus_test.go
@@ -128,3 +128,46 @@
 	assert.Equal(t, false, ok)
 	assert.Equal(t, "value1", fields["key1"])
 }
+
+func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("msg", "hello").Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test")
+	})
+}
+
+func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("msg", "hello").Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test")
+		assert.Equal(t, fields["fields.msg"], "hello")
+	})
+}
+
+func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("time", "hello").Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["fields.time"], "hello")
+	})
+}
+
+func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("level", 1).Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["level"], "info")
+		assert.Equal(t, fields["fields.level"], 1)
+	})
+}
+
+func TestConvertLevelToString(t *testing.T) {
+	assert.Equal(t, "debug", DebugLevel.String())
+	assert.Equal(t, "info", InfoLevel.String())
+	assert.Equal(t, "warning", WarnLevel.String())
+	assert.Equal(t, "error", ErrorLevel.String())
+	assert.Equal(t, "fatal", FatalLevel.String())
+	assert.Equal(t, "panic", PanicLevel.String())
+}
diff --git a/text_formatter.go b/text_formatter.go
index 06b4970..d71eba1 100644
--- a/text_formatter.go
+++ b/text_formatter.go
@@ -32,6 +32,8 @@
 func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
 	b := &bytes.Buffer{}
 
+	prefixFieldClashes(entry)
+
 	if f.ForceColors || IsTerminal() {
 		levelText := strings.ToUpper(entry.Data["level"].(string))[0:4]