public async ValueTask <int> AppendAsync(SpanData span, CancellationToken cancellationToken) { if (this.processCache == null) { this.Process.Message = this.BuildThriftMessage(this.Process).ToArray(); this.processCache = new Dictionary <string, Process> { [this.Process.ServiceName] = this.Process, }; } var jaegerSpan = span.ToJaegerSpan(); string spanServiceName = jaegerSpan.PeerServiceName ?? this.Process.ServiceName; if (!this.processCache.TryGetValue(spanServiceName, out var spanProcess)) { spanProcess = new Process(spanServiceName, this.Process.Tags); spanProcess.Message = this.BuildThriftMessage(spanProcess).ToArray(); this.processCache.Add(spanServiceName, spanProcess); } var spanMessage = this.BuildThriftMessage(jaegerSpan); jaegerSpan.Return(); if (spanMessage.Count + spanProcess.Message.Length > this.maxPacketSize) { throw new JaegerExporterException($"ThriftSender received a span that was too large, size = {spanMessage.Count + spanProcess.Message.Length}, max = {this.maxPacketSize}", null); } int spanTotalBytesNeeded = spanMessage.Count; if (!this.CurrentBatches.TryGetValue(spanServiceName, out var spanBatch)) { spanBatch = new Batch(spanProcess) { SpanMessages = new List <BufferWriterMemory>(), }; this.CurrentBatches.Add(spanServiceName, spanBatch); spanTotalBytesNeeded += spanProcess.Message.Length; } var flushedSpanCount = 0; await this.flushLock.WaitAsync().ConfigureAwait(false); try { // flush if current batch size plus new span size equals or exceeds max batch size if (this.batchByteSize + spanTotalBytesNeeded >= this.maxPacketSize) { flushedSpanCount = await this.FlushAsyncInternal(true, cancellationToken).ConfigureAwait(false); // Flushing effectively erases the spanBatch we were working on, so we have to rebuild it. spanBatch.SpanMessages.Clear(); spanTotalBytesNeeded = spanMessage.Count + spanProcess.Message.Length; this.CurrentBatches.Add(spanServiceName, spanBatch); } else { this.maxFlushIntervalTimer.Enabled = true; } // add span to batch and wait for more spans spanBatch.SpanMessages.Add(spanMessage); this.batchByteSize += spanTotalBytesNeeded; } finally { this.flushLock.Release(); } return(flushedSpanCount); }