Skip to content

Commit

Permalink
blob: add tracing (#1143)
Browse files Browse the repository at this point in the history
* blob: add tracing

Add tracing to methods that (a) make RPCs to the service, and (b) are
unlikely to be called in an inner loop. Specifically, do NOT trace:

- SignedURL, because it doesn't make an RPC
- Read and Write, because they are likely to be called frequently,
  so the trace information would be voluminous.
  • Loading branch information
jba committed Jan 20, 2019
1 parent f1a0042 commit a52ca32
Showing 1 changed file with 39 additions and 11 deletions.
50 changes: 39 additions & 11 deletions blob/blob.go
Expand Up @@ -61,14 +61,16 @@ import (
"time"

"gocloud.dev/blob/driver"
"gocloud.dev/internal/trace"
)

// Reader reads bytes from a blob.
// It implements io.ReadCloser, and must be closed after
// reads are finished.
type Reader struct {
b driver.Bucket
r driver.Reader
b driver.Bucket
r driver.Reader
tctx context.Context // trace context
}

// Read implements io.Reader (https://golang.org/pkg/io/#Reader).
Expand All @@ -79,7 +81,9 @@ func (r *Reader) Read(p []byte) (int, error) {

// Close implements io.Closer (https://golang.org/pkg/io/#Closer).
func (r *Reader) Close() error {
return wrapError(r.b, r.r.Close())
err := wrapError(r.b, r.r.Close())
trace.EndSpan(r.tctx, err)
return err
}

// ContentType returns the MIME type of the blob.
Expand Down Expand Up @@ -170,6 +174,7 @@ type Writer struct {
key string
opts *driver.WriterOptions
buf *bytes.Buffer
tctx context.Context // context for tracing only
}

// sniffLen is the byte size of Writer.buf used to detect content-type.
Expand Down Expand Up @@ -212,7 +217,8 @@ func (w *Writer) Write(p []byte) (n int, err error) {
// Close returns with no error.
// Close may return an error if the context provided to create the Writer is
// canceled or reaches its deadline.
func (w *Writer) Close() error {
func (w *Writer) Close() (err error) {
defer func() { trace.EndSpan(w.tctx, err) }()
if len(w.contentMD5) > 0 {
// Verify the MD5 hash of what was written matches the ContentMD5 provided
// by the user.
Expand Down Expand Up @@ -401,7 +407,9 @@ func (b *Bucket) As(i interface{}) bool {

// ReadAll is a shortcut for creating a Reader via NewReader with nil
// ReaderOptions, and reading the entire blob.
func (b *Bucket) ReadAll(ctx context.Context, key string) ([]byte, error) {
func (b *Bucket) ReadAll(ctx context.Context, key string) (_ []byte, err error) {
defer func() { trace.EndSpan(ctx, err) }()

r, err := b.NewReader(ctx, key, nil)
if err != nil {
return nil, err
Expand Down Expand Up @@ -434,7 +442,10 @@ func (b *Bucket) List(opts *ListOptions) *ListIterator {
//
// If the blob does not exist, Attributes returns an error for which
// IsNotExist will return true.
func (b *Bucket) Attributes(ctx context.Context, key string) (Attributes, error) {
func (b *Bucket) Attributes(ctx context.Context, key string) (_ Attributes, err error) {
ctx = trace.StartSpan(ctx, "gocloud.dev/blob.Attributes")
defer func() { trace.EndSpan(ctx, err) }()

a, err := b.b.Attributes(ctx, key)
if err != nil {
return Attributes{}, wrapError(b.b, err)
Expand Down Expand Up @@ -479,23 +490,29 @@ func (b *Bucket) NewReader(ctx context.Context, key string, opts *ReaderOptions)
// A nil ReaderOptions is treated the same as the zero value.
//
// The caller must call Close on the returned Reader when done reading.
func (b *Bucket) NewRangeReader(ctx context.Context, key string, offset, length int64, opts *ReaderOptions) (*Reader, error) {
func (b *Bucket) NewRangeReader(ctx context.Context, key string, offset, length int64, opts *ReaderOptions) (_ *Reader, err error) {
if offset < 0 {
return nil, errors.New("blob.NewRangeReader: offset must be non-negative")
}
if opts == nil {
opts = &ReaderOptions{}
}
dopts := &driver.ReaderOptions{}
tctx := trace.StartSpan(ctx, "gocloud.dev/blob.NewRangeReader")
defer func() {
if err != nil {
trace.EndSpan(tctx, err)
}
}()
r, err := b.b.NewRangeReader(ctx, key, offset, length, dopts)
if err != nil {
return nil, wrapError(b.b, err)
}
return &Reader{b: b.b, r: r}, nil
return &Reader{b: b.b, r: r, tctx: tctx}, nil
}

// WriteAll is a shortcut for creating a Writer via NewWriter and writing p.
func (b *Bucket) WriteAll(ctx context.Context, key string, p []byte, opts *WriterOptions) error {
func (b *Bucket) WriteAll(ctx context.Context, key string, p []byte, opts *WriterOptions) (err error) {
w, err := b.NewWriter(ctx, key, opts)
if err != nil {
return err
Expand All @@ -522,7 +539,7 @@ func (b *Bucket) WriteAll(ctx context.Context, key string, p []byte, opts *Write
//
// The caller must call Close on the returned Writer, even if the write is
// aborted.
func (b *Bucket) NewWriter(ctx context.Context, key string, opts *WriterOptions) (*Writer, error) {
func (b *Bucket) NewWriter(ctx context.Context, key string, opts *WriterOptions) (_ *Writer, err error) {
var dopts *driver.WriterOptions
var w driver.Writer
if opts == nil {
Expand Down Expand Up @@ -555,6 +572,13 @@ func (b *Bucket) NewWriter(ctx context.Context, key string, opts *WriterOptions)
dopts.Metadata = md
}
ctx, cancel := context.WithCancel(ctx)
tctx := trace.StartSpan(ctx, "gocloud.dev/blob.NewWriter")
defer func() {
if err != nil {
trace.EndSpan(tctx, err)
}
}()

if opts.ContentType != "" {
t, p, err := mime.ParseMediaType(opts.ContentType)
if err != nil {
Expand All @@ -573,6 +597,7 @@ func (b *Bucket) NewWriter(ctx context.Context, key string, opts *WriterOptions)
cancel: cancel,
contentMD5: opts.ContentMD5,
md5hash: md5.New(),
tctx: tctx,
}, nil
}
return &Writer{
Expand All @@ -584,14 +609,17 @@ func (b *Bucket) NewWriter(ctx context.Context, key string, opts *WriterOptions)
buf: bytes.NewBuffer([]byte{}),
contentMD5: opts.ContentMD5,
md5hash: md5.New(),
tctx: tctx,
}, nil
}

// Delete deletes the blob stored at key.
//
// If the blob does not exist, Delete returns an error for which
// IsNotExist will return true.
func (b *Bucket) Delete(ctx context.Context, key string) error {
func (b *Bucket) Delete(ctx context.Context, key string) (err error) {
ctx = trace.StartSpan(ctx, "gocloud.dev/blob.Delete")
defer func() { trace.EndSpan(ctx, err) }()
return wrapError(b.b, b.b.Delete(ctx, key))
}

Expand Down

0 comments on commit a52ca32

Please sign in to comment.