public AsyncQueueWorker(DatadogClient client, int bufferingCount = 10, int bufferingTimeMilliseconds = 5000, Action <Exception> logException = null) { this.globalQueue = new StructBuffer <Span[]>(16); this.client = client; this.logException = logException ?? ((Exception ex) => { }); this.bufferingCount = bufferingCount; this.bufferingTime = TimeSpan.FromMilliseconds(bufferingTimeMilliseconds); // Start this.processingTask = Task.Factory.StartNew(ConsumeQueue, TaskCreationOptions.LongRunning).Unwrap(); }
public TracingScope(string name, string resource, string service, string type, TracingManager manager, ulong traceId, ulong?parentId) { this.Name = name; this.Resource = resource; this.Service = service; this.Type = type; this.TraceId = traceId; this.SpanId = Span.BuildRandomId(); this.start = Span.ToNanoseconds(DateTime.UtcNow); this.duration = ThreadSafeUtil.RentStopwatchStartNew(); this.manager = manager; this.spans = new StructBuffer <Span>(4); this.parentId = parentId; }
async Task ConsumeQueue() { var buffer = new StructBuffer <Span[]>(bufferingCount); while (!cancellationTokenSource.IsCancellationRequested) { try { buffer.Clear(); var addCount = 0; for (int i = 0; i < bufferingCount; i++) { Span[] nextTrace; if (q.TryDequeue(out nextTrace)) { addCount++; buffer.Add(ref nextTrace); } else { break; } } if (addCount == 0) { await Task.Delay(bufferingTime).ConfigureAwait(false); } else { var traces = buffer.ToArray(); await client.Traces(traces).ConfigureAwait(false); } } catch (OperationCanceledException) { break; } catch (ObjectDisposedException) { break; } } }
async Task ConsumeQueue() { var buffer = new StructBuffer <Span[]>(bufferingCount); while (!cancellationTokenSource.IsCancellationRequested) { try { Task waiter = null; Span[][] singleTraces = null; Span[][] multipleTraces = null; lock (queueLock) { var rawEnqueuedArray = globalQueue.GetBuffer(); if (rawEnqueuedArray.Count == 0) { waiter = Task.Delay(bufferingTime, cancellationTokenSource.Token); } else if (rawEnqueuedArray.Count < bufferingCount) { singleTraces = new Span[rawEnqueuedArray.Count][]; Array.Copy(rawEnqueuedArray.Array, singleTraces, singleTraces.Length); globalQueue.ClearStrict(); } else { multipleTraces = new Span[rawEnqueuedArray.Count][]; Array.Copy(rawEnqueuedArray.Array, multipleTraces, multipleTraces.Length); globalQueue.ClearStrict(); } } if (waiter != null) { await waiter.ConfigureAwait(false); } else if (singleTraces != null) { // does not pass cancellation token. await client.Traces(singleTraces).ConfigureAwait(false); } else if (multipleTraces != null) { for (int i = 0; i < multipleTraces.Length;) { var tasks = new Task[Math.Min(ConcurrentRequestCountLimit, multipleTraces.Length - i)]; for (int j = 0; j < tasks.Length; j++) { var len = Math.Min(bufferingCount, multipleTraces.Length - i); if (len <= 0) { Array.Resize(ref tasks, j); break; } var segment = new ArraySegment <Span[]>(multipleTraces, i, len); i += len; tasks[j] = client.Traces(segment); } await Task.WhenAll(tasks).ConfigureAwait(false); } } } catch (TaskCanceledException) { } catch (OperationCanceledException) { await Task.Delay(bufferingTime, cancellationTokenSource.Token).ConfigureAwait(false); } catch (ObjectDisposedException) { await Task.Delay(bufferingTime, cancellationTokenSource.Token).ConfigureAwait(false); } catch (Exception ex) { logException(ex); await Task.Delay(bufferingTime, cancellationTokenSource.Token).ConfigureAwait(false); } } }