1//go:build example 2// +build example 3 4package main 5 6import ( 7 "fmt" 8 "io" 9 "log" 10 "os" 11 "runtime/debug" 12 13 "github.com/aws/aws-sdk-go/aws/request" 14 "github.com/aws/aws-sdk-go/aws/session" 15 "github.com/aws/aws-sdk-go/service/s3/s3manager" 16) 17 18// Usage: 19// go run -tags example <bucket> <key> <file to upload> 20// 21// Example: 22// AWS_REGION=us-west-2 AWS_PROFILE=default go run . "mybucket" "10MB.file" ./10MB.file 23func main() { 24 sess, err := session.NewSession() 25 if err != nil { 26 log.Fatalf("failed to load session, %v", err) 27 } 28 29 uploader := s3manager.NewUploader(sess) 30 31 file, err := os.Open(os.Args[3]) 32 if err != nil { 33 log.Fatalf("failed to open file, %v", err) 34 } 35 defer file.Close() 36 37 // Wrap the readSeeker with a logger that will log usage, and stack traces 38 // on errors. 39 readLogger := NewReadLogger(file, sess.Config.Logger) 40 41 // Upload with read logger 42 resp, err := uploader.Upload(&s3manager.UploadInput{ 43 Bucket: &os.Args[1], 44 Key: &os.Args[2], 45 Body: readLogger, 46 }, func(u *s3manager.Uploader) { 47 u.Concurrency = 1 48 u.RequestOptions = append(u.RequestOptions, func(r *request.Request) { 49 }) 50 }) 51 52 fmt.Println(resp, err) 53} 54 55// Logger is a logger use for logging the readers usage. 56type Logger interface { 57 Log(args ...interface{}) 58} 59 60// ReadSeeker interface provides the interface for a Reader, Seeker, and ReadAt. 61type ReadSeeker interface { 62 io.ReadSeeker 63 io.ReaderAt 64} 65 66// ReadLogger wraps an reader with logging for access. 67type ReadLogger struct { 68 reader ReadSeeker 69 logger Logger 70} 71 72// NewReadLogger a ReadLogger that wraps the passed in ReadSeeker (Reader, 73// Seeker, ReadAt) with a logger. 74func NewReadLogger(r ReadSeeker, logger Logger) *ReadLogger { 75 return &ReadLogger{ 76 reader: r, 77 logger: logger, 78 } 79} 80 81// Seek offsets the reader's current position for the next read. 82func (s *ReadLogger) Seek(offset int64, mode int) (int64, error) { 83 newOffset, err := s.reader.Seek(offset, mode) 84 msg := fmt.Sprintf( 85 "ReadLogger.Seek(offset:%d, mode:%d) (newOffset:%d, err:%v)", 86 offset, mode, newOffset, err) 87 if err != nil { 88 msg += fmt.Sprintf("\n\tStack:\n%s", string(debug.Stack())) 89 } 90 91 s.logger.Log(msg) 92 return newOffset, err 93} 94 95// Read attempts to read from the reader, returning the bytes read, or error. 96func (s *ReadLogger) Read(b []byte) (int, error) { 97 n, err := s.reader.Read(b) 98 msg := fmt.Sprintf( 99 "ReadLogger.Read(len(bytes):%d) (read:%d, err:%v)", 100 len(b), n, err) 101 if err != nil { 102 msg += fmt.Sprintf("\n\tStack:\n%s", string(debug.Stack())) 103 } 104 105 s.logger.Log(msg) 106 return n, err 107} 108 109// ReadAt will read the underlying reader starting at the offset. 110func (s *ReadLogger) ReadAt(b []byte, offset int64) (int, error) { 111 n, err := s.reader.ReadAt(b, offset) 112 msg := fmt.Sprintf( 113 "ReadLogger.ReadAt(len(bytes):%d, offset:%d) (read:%d, err:%v)", 114 len(b), offset, n, err) 115 if err != nil { 116 msg += fmt.Sprintf("\n\tStack:\n%s", string(debug.Stack())) 117 } 118 119 s.logger.Log(msg) 120 return n, err 121} 122