Beispiel #1
0
        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);
        }