Compare commits
	
		
			6 Commits
		
	
	
		
			6c9dbc77dd
			...
			v3.11.43
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| fa636ef6a9 | |||
| cdb81a9ba3 | |||
| 413c6cc2f0 | |||
|  | f56bd70136 | ||
| b51b4107a8 | |||
| 2067c9de6b | 
| @@ -1,5 +1,5 @@ | ||||
| # Micro | ||||
|  | ||||
|  | ||||
| [](https://opensource.org/licenses/Apache-2.0) | ||||
| [](https://pkg.go.dev/go.unistack.org/micro/v3?tab=overview) | ||||
| [](https://git.unistack.org/unistack-org/micro/actions?query=workflow%3Abuild+branch%3Av3+event%3Apush) | ||||
|   | ||||
| @@ -99,6 +99,7 @@ func WithAddFields(fields ...interface{}) Option { | ||||
| 					iv, iok := o.Fields[i].(string) | ||||
| 					jv, jok := fields[j].(string) | ||||
| 					if iok && jok && iv == jv { | ||||
| 						o.Fields[i+1] = fields[j+1] | ||||
| 						fields = slices.Delete(fields, j, j+2) | ||||
| 					} | ||||
| 				} | ||||
|   | ||||
| @@ -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), | ||||
| 	) | ||||
| @@ -124,7 +124,7 @@ func TestWithDedupKeysWithAddFields(t *testing.T) { | ||||
|  | ||||
| 	l.Info(ctx, "msg3") | ||||
|  | ||||
| 	if !bytes.Contains(buf.Bytes(), []byte(`msg=msg3 key1=val1 key2=val2`)) { | ||||
| 	if !bytes.Contains(buf.Bytes(), []byte(`msg=msg3 key1=val4 key2=val3`)) { | ||||
| 		t.Fatalf("logger error not works, buf contains: %s", buf.Bytes()) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -89,6 +89,10 @@ func (s *Span) Tracer() tracer.Tracer { | ||||
| 	return s.tracer | ||||
| } | ||||
|  | ||||
| func (s *Span) IsRecording() bool { | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| type Event struct { | ||||
| 	name   string | ||||
| 	labels []interface{} | ||||
|   | ||||
| @@ -120,6 +120,10 @@ func (s *noopSpan) SetStatus(st SpanStatus, msg string) { | ||||
| 	s.statusMsg = msg | ||||
| } | ||||
|  | ||||
| func (s *noopSpan) IsRecording() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // NewTracer returns new memory tracer | ||||
| func NewTracer(opts ...Option) Tracer { | ||||
| 	return &noopTracer{ | ||||
|   | ||||
| @@ -78,4 +78,6 @@ type Span interface { | ||||
| 	TraceID() string | ||||
| 	// SpanID returns span id | ||||
| 	SpanID() string | ||||
| 	// IsRecording returns the recording state of the Span. | ||||
| 	IsRecording() bool | ||||
| } | ||||
|   | ||||
							
								
								
									
										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