private void WriteEvent(string eventName, EventLevel level, Keywords keywords, EventMetadata metadata, EventOpcode opcode) { string jsonPayload = metadata != null?JsonConvert.SerializeObject(metadata) : null; if (this.isDisposed) { throw new ObjectDisposedException(nameof(JsonTracer)); } var message = new TraceEventMessage { EventName = eventName, ActivityId = this.activityId, ParentActivityId = this.parentActivityId, Level = level, Keywords = keywords, Opcode = opcode, Payload = jsonPayload }; // Iterating over the bag is thread-safe as the enumerator returned here // is of a snapshot of the bag. foreach (EventListener listener in this.listeners) { listener.RecordMessage(message); } }
private void LogMessageToNonFailedListeners(TraceEventMessage message) { foreach (EventListener listener in this.listeners.Except(this.failedListeners.Keys)) { // To prevent infinitely recursive failures, we won't try and log that we failed to log that a listener failed :) listener.RecordMessage(message); } }
protected override void RecordMessageInternal(TraceEventMessage message) { string pipeMessage = this.CreatePipeMessage(message); bool dropped = !this.pipeWriter.TryEnqueue(pipeMessage); if (dropped) { this.RaiseListenerFailure("Pipe delivery queue is full. Message was dropped."); } }
void IEventListenerEventSink.OnListenerFailure(EventListener listener, string errorMessage) { if (!this.failedListeners.TryAdd(listener, errorMessage)) { // We've already logged that this listener has failed so there is no need to do it again return; } TraceEventMessage message = CreateListenerFailureMessage(listener, errorMessage); this.LogMessageToNonFailedListeners(message); }
public void RecordMessage(TraceEventMessage message) { if (this.IsEnabled(message.Level, message.Keywords)) { try { this.RecordMessageInternal(message); } catch (Exception ex) { this.RaiseListenerFailure(ex.ToString()); } } }
public void AddEventListener(EventListener listener) { if (this.isDisposed) { throw new ObjectDisposedException(nameof(JsonTracer)); } this.listeners.Add(listener); // Tell the new listener about others who have previously failed foreach (KeyValuePair <EventListener, string> kvp in this.failedListeners) { TraceEventMessage failureMessage = CreateListenerFailureMessage(kvp.Key, kvp.Value); listener.RecordMessage(failureMessage); } }
void IEventListenerEventSink.OnListenerRecovery(EventListener listener) { // Check ContainsKey first (rather than always calling TryRemove) because ContainsKey // is lock-free and recoveredListener should rarely be in failedListeners if (!this.failedListeners.ContainsKey(listener)) { // This listener has not failed since the last time it was called, so no need to log recovery return; } if (this.failedListeners.TryRemove(listener, out _)) { TraceEventMessage message = CreateListenerRecoveryMessage(listener); this.LogMessageToNonFailedListeners(message); } }
protected override void RecordMessageInternal(TraceEventMessage message) { if (string.IsNullOrEmpty(message.Payload)) { return; } ConsoleOutputPayload payload = JsonConvert.DeserializeObject <ConsoleOutputPayload>(message.Payload); if (string.IsNullOrEmpty(payload.ErrorMessage)) { return; } // It's necessary to do a lock here because this can be called in a multi-threaded // environment and we want to make sure that ForegroundColor is restored correctly. lock (consoleLock) { ConsoleColor prevColor = Console.ForegroundColor; string prefix; switch (message.Level) { case EventLevel.Critical: case EventLevel.Error: case EventLevel.LogAlways: prefix = "Error"; Console.ForegroundColor = ConsoleColor.Red; break; case EventLevel.Warning: prefix = "Warning"; Console.ForegroundColor = ConsoleColor.Yellow; break; default: prefix = "Info"; break; } // The leading \r interacts with the spinner, which always leaves the // cursor at the end of the line, rather than the start. Console.WriteLine($"\r{prefix}: {payload.ErrorMessage}"); Console.ForegroundColor = prevColor; } }
private string CreatePipeMessage(TraceEventMessage message) { var pipeMessage = new PipeMessage { Version = this.vfsVersion, ProviderName = this.providerName, EventName = message.EventName, EventLevel = message.Level, EventOpcode = message.Opcode, Payload = new PipeMessage.PipeMessagePayload { EnlistmentId = this.enlistmentId, MountId = this.mountId, GitCommandSessionId = this.GitCommandSessionId, Json = message.Payload }, // Other TraceEventMessage properties are not used }; return(pipeMessage.ToJson()); }
protected override void RecordMessageInternal(TraceEventMessage message) { this.writer.WriteLine(this.GetLogString(message.EventName, message.Opcode, message.Payload)); this.writer.Flush(); }
protected abstract void RecordMessageInternal(TraceEventMessage message);