Merge pull request #179 from yawn/with-error

Added WithError(err)
diff --git a/entry.go b/entry.go
index 04673a0..1e97f99 100644
--- a/entry.go
+++ b/entry.go
@@ -8,6 +8,9 @@
 	"time"
 )
 
+// Defines the key when adding errors using WithError.
+var ErrorKey = "error"
+
 // An entry is the final or intermediate Logrus logging entry. It contains 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
@@ -53,6 +56,19 @@
 	return reader.String(), err
 }
 
+// ToError returns the field value of ErrorKey (nil)
+func (entry *Entry) ToError() error {
+	if err, ok := entry.Data[ErrorKey].(error); ok {
+		return err
+	}
+	return nil
+}
+
+// Add an error as single field (using the key defined in ErrorKey) to the Entry.
+func (entry *Entry) WithError(err error) *Entry {
+	return entry.WithField(ErrorKey, err)
+}
+
 // Add a single field to the Entry.
 func (entry *Entry) WithField(key string, value interface{}) *Entry {
 	return entry.WithFields(Fields{key: value})
@@ -106,36 +122,40 @@
 	}
 }
 
-func (entry *Entry) Debug(args ...interface{}) {
+func (entry *Entry) Debug(args ...interface{}) *Entry {
 	if entry.Logger.Level >= DebugLevel {
 		entry.log(DebugLevel, fmt.Sprint(args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Print(args ...interface{}) {
-	entry.Info(args...)
+func (entry *Entry) Print(args ...interface{}) *Entry {
+	return entry.Info(args...)
 }
 
-func (entry *Entry) Info(args ...interface{}) {
+func (entry *Entry) Info(args ...interface{}) *Entry {
 	if entry.Logger.Level >= InfoLevel {
 		entry.log(InfoLevel, fmt.Sprint(args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Warn(args ...interface{}) {
+func (entry *Entry) Warn(args ...interface{}) *Entry {
 	if entry.Logger.Level >= WarnLevel {
 		entry.log(WarnLevel, fmt.Sprint(args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Warning(args ...interface{}) {
-	entry.Warn(args...)
+func (entry *Entry) Warning(args ...interface{}) *Entry {
+	return entry.Warn(args...)
 }
 
-func (entry *Entry) Error(args ...interface{}) {
+func (entry *Entry) Error(args ...interface{}) *Entry {
 	if entry.Logger.Level >= ErrorLevel {
 		entry.log(ErrorLevel, fmt.Sprint(args...))
 	}
+	return entry
 }
 
 func (entry *Entry) Fatal(args ...interface{}) {
@@ -154,36 +174,40 @@
 
 // Entry Printf family functions
 
-func (entry *Entry) Debugf(format string, args ...interface{}) {
+func (entry *Entry) Debugf(format string, args ...interface{}) *Entry {
 	if entry.Logger.Level >= DebugLevel {
 		entry.Debug(fmt.Sprintf(format, args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Infof(format string, args ...interface{}) {
+func (entry *Entry) Infof(format string, args ...interface{}) *Entry {
 	if entry.Logger.Level >= InfoLevel {
 		entry.Info(fmt.Sprintf(format, args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Printf(format string, args ...interface{}) {
-	entry.Infof(format, args...)
+func (entry *Entry) Printf(format string, args ...interface{}) *Entry {
+	return entry.Infof(format, args...)
 }
 
-func (entry *Entry) Warnf(format string, args ...interface{}) {
+func (entry *Entry) Warnf(format string, args ...interface{}) *Entry {
 	if entry.Logger.Level >= WarnLevel {
 		entry.Warn(fmt.Sprintf(format, args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Warningf(format string, args ...interface{}) {
-	entry.Warnf(format, args...)
+func (entry *Entry) Warningf(format string, args ...interface{}) *Entry {
+	return entry.Warnf(format, args...)
 }
 
-func (entry *Entry) Errorf(format string, args ...interface{}) {
+func (entry *Entry) Errorf(format string, args ...interface{}) *Entry {
 	if entry.Logger.Level >= ErrorLevel {
 		entry.Error(fmt.Sprintf(format, args...))
 	}
+	return entry
 }
 
 func (entry *Entry) Fatalf(format string, args ...interface{}) {
@@ -201,36 +225,40 @@
 
 // Entry Println family functions
 
-func (entry *Entry) Debugln(args ...interface{}) {
+func (entry *Entry) Debugln(args ...interface{}) *Entry {
 	if entry.Logger.Level >= DebugLevel {
 		entry.Debug(entry.sprintlnn(args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Infoln(args ...interface{}) {
+func (entry *Entry) Infoln(args ...interface{}) *Entry {
 	if entry.Logger.Level >= InfoLevel {
 		entry.Info(entry.sprintlnn(args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Println(args ...interface{}) {
-	entry.Infoln(args...)
+func (entry *Entry) Println(args ...interface{}) *Entry {
+	return entry.Infoln(args...)
 }
 
-func (entry *Entry) Warnln(args ...interface{}) {
+func (entry *Entry) Warnln(args ...interface{}) *Entry {
 	if entry.Logger.Level >= WarnLevel {
 		entry.Warn(entry.sprintlnn(args...))
 	}
+	return entry
 }
 
-func (entry *Entry) Warningln(args ...interface{}) {
-	entry.Warnln(args...)
+func (entry *Entry) Warningln(args ...interface{}) *Entry {
+	return entry.Warnln(args...)
 }
 
-func (entry *Entry) Errorln(args ...interface{}) {
+func (entry *Entry) Errorln(args ...interface{}) *Entry {
 	if entry.Logger.Level >= ErrorLevel {
 		entry.Error(entry.sprintlnn(args...))
 	}
+	return entry
 }
 
 func (entry *Entry) Fatalln(args ...interface{}) {
diff --git a/entry_test.go b/entry_test.go
index 98717df..3473ffb 100644
--- a/entry_test.go
+++ b/entry_test.go
@@ -8,6 +8,45 @@
 	"github.com/stretchr/testify/assert"
 )
 
+var err = fmt.Errorf("kaboom at layer %d", 4711)
+
+func TestToError(t *testing.T) {
+
+	assert := assert.New(t)
+
+	ctx := WithField("foo", "bar")
+	assert.Equal(nil, ctx.Debug("Hello").ToError())
+
+	ctx.Data[ErrorKey] = "error"
+	assert.Equal(nil, ctx.Debug("Hello").ToError())
+
+	ctx = ctx.WithError(err)
+	assert.Equal(err, ctx.Debug("Hello").ToError())
+
+}
+
+func TestEntryWithError(t *testing.T) {
+
+	assert := assert.New(t)
+
+	defer func() {
+		ErrorKey = "error"
+	}()
+
+	assert.Equal(err, WithError(err).Data["error"])
+
+	logger := New()
+	logger.Out = &bytes.Buffer{}
+	entry := NewEntry(logger)
+
+	assert.Equal(err, entry.WithError(err).Data["error"])
+
+	ErrorKey = "err"
+
+	assert.Equal(err, entry.WithError(err).Data["err"])
+
+}
+
 func TestEntryPanicln(t *testing.T) {
 	errBoom := fmt.Errorf("boom time")
 
diff --git a/exported.go b/exported.go
index a67e1b8..9a0120a 100644
--- a/exported.go
+++ b/exported.go
@@ -48,6 +48,11 @@
 	std.Hooks.Add(hook)
 }
 
+// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
+func WithError(err error) *Entry {
+	return std.WithField(ErrorKey, err)
+}
+
 // WithField creates an entry from the standard logger and adds a field to
 // it. If you want multiple fields, use `WithFields`.
 //