private static void InitializeActivityTrackerIfNeeded(Context context, DistributedContentSettings settings) { if (settings.EnableCacheActivityTracker) { CacheActivityTracker.Start(context, SystemClock.Instance, settings.TrackingActivityWindow, settings.TrackingSnapshotPeriod, settings.TrackingReportPeriod); } }
private async Task ProcessEventsAsync(OperationContext context, List <EventData> messages) { // Tracking raw messages count. Counters[ReceivedEventHubEventsCount].Add(messages.Count); CacheActivityTracker.AddValue(CaSaaSActivityTrackingCounters.ReceivedEventHubMessages, messages.Count); // Creating nested context for all the processing operations. context = context.CreateNested(nameof(EventHubContentLocationEventStore)); if (messages.Count == 0) { // This probably does not actually occur, but just in case, ignore empty message batch. // NOTE: We do this after logging to ensure we notice if the we are getting empty message batches. return; } var state = new SharedEventProcessingState(context, this, messages); if (_eventProcessingBlocks != null) { await context .CreateOperation(Tracer, () => sendToActionBlockAsync(state)) .WithOptions(traceOperationStarted: false, endMessageFactory: r => $"TotalQueueSize={Interlocked.Read(ref _queueSize)}") .RunAsync(caller: "SendToActionBlockAsync") .TraceIfFailure(context); } else { await ProcessEventsCoreAsync(new ProcessEventsInput(state, messages, actionBlockIndex : -1, store : this), EventDataSerializer); } async Task <BoolResult> sendToActionBlockAsync(SharedEventProcessingState st) { // This local function "sends" a message into an action block based on the sender's hash code to process events in parallel from different machines. // (keep in mind, that the data from the same machine should be processed sequentially, because events order matters). // Then, it creates a local counter for each processing operation to track the results for the entire batch. foreach (var messageGroup in messages.GroupBy(GetProcessingIndex)) { int actionBlockIndex = messageGroup.Key; var eventProcessingBlock = _eventProcessingBlocks ![actionBlockIndex]; var input = new ProcessEventsInput(st, messageGroup, actionBlockIndex, this); var sendAsyncTask = eventProcessingBlock.SendAsync(input); if (sendAsyncTask.Status == TaskStatus.WaitingForActivation) { // The action block is busy. It means that its most likely full. Tracer.Debug(context, $"Action block {actionBlockIndex} is busy. Block's queue size={eventProcessingBlock.InputCount}."); } bool success = await sendAsyncTask; if (!success) { // NOTE: This case should not actually occur. // Complete the operation in case we couldn't send to the action block to prevent pending event queue from getting backlogged. input.Complete(); return(new BoolResult("Failed to add message to an action block.")); } }
private static void ReportServiceStopped(Context context, IDistributedCacheServiceHost host, BoolResult result) { CacheActivityTracker.Stop(); LifetimeTracker.ServiceStopped(context, result); host.OnTeardownCompleted(); }
private static void TrackBytesReceived(long bytesTransferredPerIteration) => CacheActivityTracker.AddValue(CaSaaSActivityTrackingCounters.RemoteCopyBytes, bytesTransferredPerIteration);