Compare commits
	
		
			2 Commits
		
	
	
		
			6c9dbc77dd
			...
			v3.11.40
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b51b4107a8 | |||
| 2067c9de6b | 
| @@ -278,7 +278,7 @@ func (s *slogLogger) printLog(ctx context.Context, lvl logger.Level, msg string, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (s.opts.AddStacktrace || lvl == logger.FatalLevel) || (s.opts.AddStacktrace && lvl == logger.ErrorLevel) { | ||||
| 	if s.opts.AddStacktrace && (lvl == logger.FatalLevel || lvl == logger.ErrorLevel) { | ||||
| 		stackInfo := make([]byte, 1024*1024) | ||||
| 		if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 { | ||||
| 			traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1) | ||||
|   | ||||
| @@ -21,7 +21,7 @@ import ( | ||||
| func TestStacktrace(t *testing.T) { | ||||
| 	ctx := context.TODO() | ||||
| 	buf := bytes.NewBuffer(nil) | ||||
| 	l := NewLogger(logger.WithLevel(logger.ErrorLevel), logger.WithOutput(buf), | ||||
| 	l := NewLogger(logger.WithLevel(logger.DebugLevel), logger.WithOutput(buf), | ||||
| 		WithHandlerFunc(slog.NewTextHandler), | ||||
| 		logger.WithAddStacktrace(true), | ||||
| 	) | ||||
|   | ||||
							
								
								
									
										78
									
								
								util/buffer/seeker_buffer.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								util/buffer/seeker_buffer.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| package buffer | ||||
|  | ||||
| import "io" | ||||
|  | ||||
| var _ interface { | ||||
| 	io.ReadCloser | ||||
| 	io.ReadSeeker | ||||
| } = (*SeekerBuffer)(nil) | ||||
|  | ||||
| // Buffer is a ReadWriteCloser that supports seeking. It's intended to | ||||
| // replicate the functionality of bytes.Buffer that I use in my projects. | ||||
| // | ||||
| // Note that the seeking is limited to the read marker; all writes are | ||||
| // append-only. | ||||
| type SeekerBuffer struct { | ||||
| 	data []byte | ||||
| 	pos  int64 | ||||
| } | ||||
|  | ||||
| func NewSeekerBuffer(data []byte) *SeekerBuffer { | ||||
| 	return &SeekerBuffer{ | ||||
| 		data: data, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *SeekerBuffer) Read(p []byte) (int, error) { | ||||
| 	if b.pos >= int64(len(b.data)) { | ||||
| 		return 0, io.EOF | ||||
| 	} | ||||
|  | ||||
| 	n := copy(p, b.data[b.pos:]) | ||||
| 	b.pos += int64(n) | ||||
| 	return n, nil | ||||
| } | ||||
|  | ||||
| func (b *SeekerBuffer) Write(p []byte) (int, error) { | ||||
| 	b.data = append(b.data, p...) | ||||
| 	return len(p), nil | ||||
| } | ||||
|  | ||||
| // Seek sets the read pointer to pos. | ||||
| func (b *SeekerBuffer) Seek(offset int64, whence int) (int64, error) { | ||||
| 	switch whence { | ||||
| 	case io.SeekStart: | ||||
| 		b.pos = offset | ||||
| 	case io.SeekEnd: | ||||
| 		b.pos = int64(len(b.data)) + offset | ||||
| 	case io.SeekCurrent: | ||||
| 		b.pos += offset | ||||
| 	} | ||||
|  | ||||
| 	return b.pos, nil | ||||
| } | ||||
|  | ||||
| // Rewind resets the read pointer to 0. | ||||
| func (b *SeekerBuffer) Rewind() error { | ||||
| 	if _, err := b.Seek(0, io.SeekStart); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Close clears all the data out of the buffer and sets the read position to 0. | ||||
| func (b *SeekerBuffer) Close() error { | ||||
| 	b.data = nil | ||||
| 	b.pos = 0 | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Len returns the length of data remaining to be read. | ||||
| func (b *SeekerBuffer) Len() int { | ||||
| 	return len(b.data[b.pos:]) | ||||
| } | ||||
|  | ||||
| // Bytes returns the underlying bytes from the current position. | ||||
| func (b *SeekerBuffer) Bytes() []byte { | ||||
| 	return b.data[b.pos:] | ||||
| } | ||||
							
								
								
									
										55
									
								
								util/buffer/seeker_buffer_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								util/buffer/seeker_buffer_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| package buffer | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func noErrorT(t *testing.T, err error) { | ||||
| 	if nil != err { | ||||
| 		t.Fatalf("%s", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func boolT(t *testing.T, cond bool, s ...string) { | ||||
| 	if !cond { | ||||
| 		what := strings.Join(s, ", ") | ||||
| 		if len(what) > 0 { | ||||
| 			what = ": " + what | ||||
| 		} | ||||
| 		t.Fatalf("assert.Bool failed%s", what) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSeeking(t *testing.T) { | ||||
| 	partA := []byte("hello, ") | ||||
| 	partB := []byte("world!") | ||||
|  | ||||
| 	buf := NewSeekerBuffer(partA) | ||||
|  | ||||
| 	boolT(t, buf.Len() == len(partA), fmt.Sprintf("on init: have length %d, want length %d", buf.Len(), len(partA))) | ||||
|  | ||||
| 	b := make([]byte, 32) | ||||
|  | ||||
| 	n, err := buf.Read(b) | ||||
| 	noErrorT(t, err) | ||||
| 	boolT(t, buf.Len() == 0, fmt.Sprintf("after reading 1: have length %d, want length 0", buf.Len())) | ||||
| 	boolT(t, n == len(partA), fmt.Sprintf("after reading 2: have length %d, want length %d", n, len(partA))) | ||||
|  | ||||
| 	n, err = buf.Write(partB) | ||||
| 	noErrorT(t, err) | ||||
| 	boolT(t, n == len(partB), fmt.Sprintf("after writing: have length %d, want length %d", n, len(partB))) | ||||
|  | ||||
| 	n, err = buf.Read(b) | ||||
| 	noErrorT(t, err) | ||||
| 	boolT(t, buf.Len() == 0, fmt.Sprintf("after rereading 1: have length %d, want length 0", buf.Len())) | ||||
| 	boolT(t, n == len(partB), fmt.Sprintf("after rereading 2: have length %d, want length %d", n, len(partB))) | ||||
|  | ||||
| 	partsLen := len(partA) + len(partB) | ||||
| 	_ = buf.Rewind() | ||||
| 	boolT(t, buf.Len() == partsLen, fmt.Sprintf("after rewinding: have length %d, want length %d", buf.Len(), partsLen)) | ||||
|  | ||||
| 	buf.Close() | ||||
| 	boolT(t, buf.Len() == 0, fmt.Sprintf("after closing, have length %d, want length 0", buf.Len())) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user