Skip to content

Commit

Permalink
feat(util:context) add error logging to context
Browse files Browse the repository at this point in the history
This commit...

is a second attempt at: #68

partially addresses: #66

is the result of discussion at:

    https://gist.github.com/perfmode/f2951c1ed3a02c484d0b
  • Loading branch information
Brian Tiger Chow committed Sep 23, 2014
1 parent 7228786 commit 5b779a0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
35 changes: 35 additions & 0 deletions util/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package util

import (
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
)

// privateChanType protects the channel. Since this is a package-private type,
// only methods defined in this package can get the error value from the
// context.
type privateChanType chan error

const errLogKey = "the key used to extract the error log from the context"

// ContextWithErrorLog returns a copy of parent and an error channel that can
// be used to receive errors sent with the LogError method.
func ContextWithErrorLog(parent context.Context) (context.Context, <-chan error) {
errs := make(privateChanType)
ctx := context.WithValue(parent, errLogKey, errs)
return ctx, errs
}

// LogError logs the error to the owner of the context.
//
// If this context was created with ContextWithErrorLog, then this method
// passes the error to context creator over an unbuffered channel.
//
// If this context was created by other means, this method is a no-op.
func LogError(ctx context.Context, err error) {
v := ctx.Value(errLogKey)
errs, ok := v.(privateChanType)
if !ok {
return
}
errs <- err
}
28 changes: 28 additions & 0 deletions util/context_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package util

import (
"errors"
"testing"

context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
)

func TestLogErrorDoesNotBlockWhenCtxIsNotSetUpForLogging(t *testing.T) {
ctx := context.Background()
LogError(ctx, errors.New("ignore me"))
}

func TestLogErrorReceivedByParent(t *testing.T) {

expected := errors.New("From child to parent")

ctx, errs := ContextWithErrorLog(context.Background())

go func() {
LogError(ctx, expected)
}()

if err := <-errs; err != expected {
t.Fatal("didn't receive the expected error")
}
}

0 comments on commit 5b779a0

Please sign in to comment.