github.com/matrixorigin/matrixone@v1.2.0/pkg/util/trace/impl/motrace/batch_span_processor.go (about) 1 // Copyright The OpenTelemetry Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Portions of this file are additionally subject to the following 16 // copyright. 17 // 18 // Copyright (C) 2022 Matrix Origin. 19 // 20 // Modified the behavior and the interface of the step. 21 22 package motrace 23 24 import ( 25 "context" 26 "github.com/matrixorigin/matrixone/pkg/util/trace" 27 "sync" 28 29 "github.com/matrixorigin/matrixone/pkg/util/batchpipe" 30 ) 31 32 var _ trace.SpanProcessor = &batchSpanProcessor{} 33 34 // batchSpanProcessor is a SpanProcessor that batches asynchronously-received 35 // spans and sends them to a trace.Exporter when complete. 36 type batchSpanProcessor struct { 37 e BatchProcessor 38 39 stopWait sync.WaitGroup 40 stopOnce sync.Once 41 stopCh chan struct{} 42 } 43 44 func NewBatchSpanProcessor(exporter BatchProcessor) trace.SpanProcessor { 45 bsp := &batchSpanProcessor{ 46 e: exporter, 47 stopCh: make(chan struct{}), 48 } 49 50 return bsp 51 } 52 53 // OnStart method does nothing. 54 func (bsp *batchSpanProcessor) OnStart(parent context.Context, s trace.Span) {} 55 56 // OnEnd method enqueues a ReadOnlySpan for later processing. 57 func (bsp *batchSpanProcessor) OnEnd(s trace.Span) { 58 // Do not enqueue spans if we are just going to drop them. 59 if bsp.e == nil { 60 return 61 } 62 if i, ok := s.(batchpipe.HasName); !ok { 63 panic("No implement batchpipe.HasName") 64 } else { 65 bsp.e.Collect(DefaultContext(), i) 66 } 67 } 68 69 // Shutdown flushes the queue and waits until all spans are processed. 70 // It only executes once. Subsequent call does nothing. 71 func (bsp *batchSpanProcessor) Shutdown(ctx context.Context) error { 72 var err error 73 bsp.stopOnce.Do(func() { 74 wait := make(chan struct{}) 75 go func() { 76 close(bsp.stopCh) 77 bsp.stopWait.Wait() 78 if bsp.e != nil { 79 // bsp.e.Shutdown(ctx) 80 if err := bsp.e.Stop(true); err != nil { 81 // TODO: otel.Handle(err) 82 panic(err) 83 } 84 } 85 close(wait) 86 }() 87 // Wait until the wait group is done or the context is cancelled 88 select { 89 case <-wait: 90 case <-ctx.Done(): 91 err = ctx.Err() 92 } 93 }) 94 return err 95 }