public override DataProcessingResult CookDataElement(LTTngEvent data, LTTngContext context, CancellationToken cancellationToken) { try { if (this.discardedEventsTracker.EventsDiscardedBetweenLastTwoEvents(data, context) > 0) { this.threadTracker.ReportEventsDiscarded(context.CurrentCpu); } this.threadTracker.ProcessEvent(data, context); if (data.Name.StartsWith("module")) { this.moduleEvents.Add(new ModuleEvent(data, context, this.threadTracker)); return(DataProcessingResult.Processed); } else { return(DataProcessingResult.Ignored); } } catch (CtfPlaybackException e) { Console.Error.WriteLine(e); return(DataProcessingResult.CorruptData); } }
public override DataProcessingResult CookDataElement(LTTngEvent data, LTTngContext context, CancellationToken cancellationToken) { try { if (this.discardedEventsTracker.EventsDiscardedBetweenLastTwoEvents(data, context) > 0) { this.discardedEventsTimestamps.Add(data.Timestamp); this.threadTracker.ReportEventsDiscarded(context.CurrentCpu); } this.threadTracker.ProcessEvent(data, context); if (data.Name.StartsWith("syscall") || LTTngSyscallDataCooker.UknownSyscallExit.Equals(data.Name)) { this.ProcessSyscall(new SyscallEvent(data, context, this.threadTracker)); return(DataProcessingResult.Processed); } else { return(DataProcessingResult.Ignored); } } catch (CtfPlaybackException e) { Console.Error.WriteLine(e); return(DataProcessingResult.CorruptData); } }
public override DataProcessingResult CookDataElement( LTTngEvent data, LTTngContext context, CancellationToken cancellationToken) { try { ContextSwitchUserData parsed = ContextSwitchUserData.Read(data.Payload); ContextSwitches.AddEvent( new ContextSwitch( data.Timestamp, parsed.PrevComm, parsed.PrevTid, parsed.PrevPrio, parsed.NextComm, parsed.NextTid, parsed.NextPrio)); } catch (Exception e) { Console.Error.WriteLine(e); return(DataProcessingResult.CorruptData); } return(DataProcessingResult.Processed); }
public LTTngGenericEvent(LTTngEvent data, LTTngContext context) { if (!(data.Payload is CtfStructValue payload)) { throw new CtfPlaybackException("Event data is corrupt."); } this.Timestamp = data.Timestamp; this.CpuId = context.CurrentCpu; this.DiscardedEvents = data.DiscardedEvents; if (!EventKind.RegisteredKinds.TryGetValue(data.Id, out this.kind)) { this.kind = new EventKind(data.Id, data.Name, payload.Fields); EventKind.RegisteredKinds.Add(data.Id, this.kind); } // As this is being written, all columns are of type 'T', so all rows are the same. For generic events, // where columns have different types for different rows, this means everything becomes a string. // // We don't want to keep around each event in memory, that would use too much memory. So for now convert // each field value to a string, which would happen anyways. // // If the consumer is smarter in the future and allows for multi-type columns, we can re-evaluate this // approach. We could probably generate a type from each event descriptor, and convert to that type. // this.FieldValues = new List <string>(payload.Fields.Count); foreach (var field in payload.Fields) { this.FieldValues.Add(field.GetValueAsString()); } }
public ModuleEvent(LTTngEvent data, LTTngContext context, ExecutingThreadTracker threadTracker) { this.eventType = ParseEventType(data.Name); if (data.Payload.FieldsByName.ContainsKey("_ip")) { this.instructionPointer = string.Format("0x{0:X}", data.Payload.ReadFieldAsUInt64("_ip")); } else { this.instructionPointer = String.Empty; } if (data.StreamDefinedEventContext != null && data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid")) { this.tid = data.StreamDefinedEventContext.ReadFieldAsInt32("_tid"); } else { this.tid = threadTracker.CurrentTidAsInt(context.CurrentCpu); } this.threadId = this.tid.ToString(); if (data.Payload.FieldsByName.ContainsKey("_refcnt")) { this.refCount = data.Payload.ReadFieldAsInt32("_refcnt"); } else { this.refCount = 0; } this.moduleName = data.Payload.FieldsByName["_name"].GetValueAsString(); this.time = data.Timestamp; }
public void ProcessThreadCloneSyscallEntry(LTTngEvent data, LTTngContext context) { ThreadInfo threadInExecution = this.EventCreatorThread(data, context.CurrentCpu); if (threadInExecution != null) { if (this.closingEventsToBeSkipped.TryGetValue(threadInExecution.Tid, out int eventsToBeSkipped) && eventsToBeSkipped > 0) { this.closingEventsToBeSkipped[threadInExecution.Tid] = eventsToBeSkipped + 1; return; } uint flags = data.Payload.ReadFieldAsUInt32("_clone_flags"); if (cloneSyscallFlagsPerTid.TryGetValue(threadInExecution.Tid, out Dictionary <uint, int> lastCalls)) { if (lastCalls.TryGetValue(flags, out int timesUsed)) { lastCalls[flags] = timesUsed + 1; } else { lastCalls[flags] = 1; } } else { cloneSyscallFlagsPerTid[threadInExecution.Tid] = new Dictionary <uint, int>() { [flags] = 1 }; } } }
public void ProcessEvent(LTTngEvent data, LTTngContext context) { if (ContextSwitchEventName.Equals(data.Name)) { while (this.executingThreadPerCpu.Count <= context.CurrentCpu) { this.executingThreadPerCpu.Add(-1); } this.executingThreadPerCpu[(int)context.CurrentCpu] = data.Payload.ReadFieldAsInt32("_next_tid"); } }
public void ProcessThreadWakeUp(LTTngEvent data, LTTngContext context) { int tid = data.Payload.ReadFieldAsInt32("_tid"); if (runningThreads.TryGetValue(tid, out ThreadInfo nextThread)) { nextThread.Wakeup(data.Timestamp); } else { ThreadInfo readyingThread = this.EventCreatorThread(data, context.CurrentCpu); this.AddNewThread(new ThreadInfo(tid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING, readyingThread)); } }
public void ProcessThreadCloneSyscallEntry(LTTngEvent data, LTTngContext context) { ThreadInfo threadInExecution = this.EventCreatorThread(data, context.CurrentCpu); if (threadInExecution != null) { if (this.closingEventsToBeSkipped.TryGetValue(threadInExecution.Tid, out int eventsToBeSkipped) && eventsToBeSkipped > 0) { this.closingEventsToBeSkipped[threadInExecution.Tid] = eventsToBeSkipped + 1; return; } uint? cloneFlags = null; const string SysCallCloneFlags = "_clone_flags"; const string SysCallFlagsAsStruct = "_flags"; // https://lttng.org/docs/v2.13/#doc-whats-new & https://github.com/lttng/lttng-modules/commit/d775625e2ba4825b73b5897e7701ad6e2bdba115 if (data.Payload.FieldsByName.ContainsKey(SysCallCloneFlags)) { cloneFlags = data.Payload.ReadFieldAsUInt32(SysCallCloneFlags); } else if (data.Payload.FieldsByName.ContainsKey(SysCallFlagsAsStruct)) // New since v2.13 { var flags = data.Payload.ReadFieldAsUInt32(SysCallFlagsAsStruct); // var exitSignal = flags & 0xFF; // the least significant byte of the `unsigned long` is the signal the kernel need to send to the parent process on child exit cloneFlags = flags & 0xFFFFFF00; // the remaining bytes of the `unsigned long` is used a bitwise flag for the clone options. } if (cloneFlags.HasValue) { if (cloneSyscallFlagsPerTid.TryGetValue(threadInExecution.Tid, out Dictionary <uint, int> lastCalls)) { if (lastCalls.TryGetValue(cloneFlags.Value, out int timesUsed)) { lastCalls[cloneFlags.Value] = timesUsed + 1; } else { lastCalls[cloneFlags.Value] = 1; } } else { cloneSyscallFlagsPerTid[threadInExecution.Tid] = new Dictionary <uint, int>() { [cloneFlags.Value] = 1 }; } } } }
public SyscallEvent(LTTngEvent data, LTTngContext context, ExecutingThreadTracker threadTracker) { this.name = EventNameToSyscallName(data.Name, out this.isEntry); this.timestamp = data.Timestamp; this.fields = data.Payload.FieldsByName; if (data.StreamDefinedEventContext != null && data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid")) { this.tid = data.StreamDefinedEventContext.ReadFieldAsInt32("_tid"); } else { this.tid = threadTracker.CurrentTidAsInt(context.CurrentCpu); } }
public uint EventsDiscardedBetweenLastTwoEvents(LTTngEvent data, LTTngContext context) { while (this.discardedEventsPerCpu.Count <= context.CurrentCpu) { this.discardedEventsPerCpu.Add(0); } uint previousDiscardedEvents = this.discardedEventsPerCpu[(int)context.CurrentCpu]; if (previousDiscardedEvents < data.DiscardedEvents) { discardedEventsPerCpu[(int)context.CurrentCpu] = data.DiscardedEvents; return(data.DiscardedEvents - previousDiscardedEvents); } return(0); }
private void ProcessGetPidSyscallExit(LTTngEvent data, LTTngContext context) { if (data.StreamDefinedEventContext == null || !data.StreamDefinedEventContext.FieldsByName.ContainsKey("_pid") || !data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid")) { ///This heuristic is activated when the event context does not have metadata regarding to tid and pid ThreadInfo executingThread = CurrentExecutingThread(context.CurrentCpu); int pid = data.Payload.ReadFieldAsInt32("_ret"); if (executingThread != null && executingThread.Pid < 0) { this.RecoverPid(executingThread, pid); } } }
private void ProcessEventDrop(LTTngEvent data, LTTngContext context) { uint discardedEventsBetweenLastTwoEvents = this.discardedEventsTracker.EventsDiscardedBetweenLastTwoEvents(data, context); if (discardedEventsBetweenLastTwoEvents > 0) { if (this.lastContextSwitch.TryGetValue(context.CurrentCpu, out ContextSwitch lastContextSwitchOnCpu)) { processedExecutionEvents.Add(new ExecutionEvent(lastContextSwitchOnCpu, lastContextSwitchOnCpu.SwitchInTime)); this.lastContextSwitch.Remove(context.CurrentCpu); } this.cloneSyscallFlagsPerTid.Clear(); this.closingEventsToBeSkipped.Clear(); } }
public void ProcessEvent(ICtfEvent ctfEvent, ICtfPacket eventPacket, ICtfTraceInput traceInput, ICtfInputStream ctfEventStream) { var eventDescriptor = ctfEvent.EventDescriptor as EventDescriptor; Debug.Assert(eventDescriptor != null); if (eventDescriptor == null) { throw new LTTngPlaybackException("EventDescriptor is not an LTTng descriptor."); } if (!this.streamToCpu.TryGetValue(ctfEventStream, out var cpuId)) { var cpuIndex = ctfEventStream.StreamSource.LastIndexOf('_'); string cpu = ctfEventStream.StreamSource.Substring(cpuIndex + 1); if (!uint.TryParse(cpu, out cpuId)) { Debug.Assert(false, "Unable to parse cpu from LTTng stream channel"); cpuId = uint.MaxValue; } this.streamToCpu.Add(ctfEventStream, cpuId); } if (!this.traceContexts.TryGetValue(traceInput, out var traceContext)) { traceContext = new TraceContext(this.metadataCustomization.LTTngMetadata); this.traceContexts.Add(traceInput, traceContext); } var callbackEvent = new LTTngEvent(ctfEvent); var callbackContext = new LTTngContext(this.metadataCustomization, ctfEventStream, traceContext) { // todo: when supporting multiple traces, this timestamp needs to become relative to the earliest timestamp all traces // todo: when supporting multiple traces, this one event number needs to become cumulative across traces, and one specific to the current trace CurrentCpu = cpuId, Timestamp = (long)ctfEvent.Timestamp.NanosecondsFromClockBase,/// - this.baseTimestamp, CurrentEventNumber = this.eventNumber, CurrentEventNumberWithinTrace = this.eventNumber, }; foreach (var callback in this.eventCallbacks) { callback(callbackEvent, callbackContext); } ++this.eventNumber; }
public override DataProcessingResult CookDataElement(LTTngEvent data, LTTngContext context, CancellationToken cancellationToken) { try { if (DmesgDataKey.Equals(data.Name)) { ProcessDiagnosticMessage(data); return(DataProcessingResult.Processed); } else { return(DataProcessingResult.Ignored); } } catch (CtfPlaybackException e) { Console.Error.WriteLine(e); return(DataProcessingResult.CorruptData); } }
public override DataProcessingResult CookDataElement( LTTngEvent data, LTTngContext context, CancellationToken cancellationToken) { try { Events.AddEvent(new LTTngGenericEvent(data, context)); this.MaximumEventFieldCount = Math.Max(data.Payload.Fields.Count, this.MaximumEventFieldCount); } catch (CtfPlaybackException e) { Console.Error.WriteLine($"Error consuming event: {e.Message}"); return(DataProcessingResult.CorruptData); } return(DataProcessingResult.Processed); }
public void ProcessSchedForkEvent(LTTngEvent data, LTTngContext context) { int newTid = data.Payload.ReadFieldAsInt32("_child_tid"); if (runningThreads.TryGetValue(newTid, out ThreadInfo oldThreadWithSamePid)) { this.terminatedThreads.Add(new Thread(oldThreadWithSamePid)); } ThreadInfo parentThread = null; int parentTid = data.Payload.ReadFieldAsInt32("_parent_tid"); if (runningThreads.ContainsKey(parentTid)) { parentThread = runningThreads[parentTid]; if (parentThread.Pid < 0) { this.RecoverPid(parentThread, data.Payload.ReadFieldAsInt32("_parent_pid")); } } this.AddNewThread(new ThreadInfo(newTid, data.Timestamp, ThreadInfo.ThreadState.TASK_NEW, parentThread)); }
public void ProcessThreadCloneSyscallExit(LTTngEvent data, LTTngContext context) { int newThreadTid = data.Payload.ReadFieldAsInt32("_ret"); if (newThreadTid == 0) { ///This is the returning syscall for the newly created child return; } ThreadInfo threadInExecution = this.EventCreatorThread(data, context.CurrentCpu); if (threadInExecution != null) { if (this.closingEventsToBeSkipped.TryGetValue(threadInExecution.Tid, out int eventsToBeSkipped) && eventsToBeSkipped > 0) { if (eventsToBeSkipped == 1) { this.closingEventsToBeSkipped.Remove(threadInExecution.Tid); } else { this.closingEventsToBeSkipped[threadInExecution.Tid] = eventsToBeSkipped - 1; } } else if (cloneSyscallFlagsPerTid.TryGetValue(threadInExecution.Tid, out Dictionary <uint, int> lastCalls)) { if (lastCalls.Count == 1) { uint flag = new List <uint>(lastCalls.Keys)[0]; if (newThreadTid > 0 && (flag & 0x00010000) > 0 && runningThreads.TryGetValue(threadInExecution.Tid, out ThreadInfo parentThread)) { if (runningThreads.TryGetValue(newThreadTid, out ThreadInfo newThread)) { newThread.Pid = parentThread.Pid; } else { this.AddNewThread(new ThreadInfo(newThreadTid, data.Timestamp, ThreadInfo.ThreadState.TASK_NEW, threadInExecution, true)); } } int amountOfEntries = lastCalls[flag]; if (amountOfEntries <= 1) { lastCalls.Remove(flag); } else { lastCalls[flag] = amountOfEntries - 1; } } else if (lastCalls.Count > 1) { int pendingEntryEvents = 0; foreach (var entry in lastCalls) { pendingEntryEvents += entry.Value; } closingEventsToBeSkipped[threadInExecution.Tid] = pendingEntryEvents - 1; ///Decrease one for the current closing event lastCalls.Clear(); } } } }
public void ProcessContextSwitch(LTTngEvent data, LTTngContext context) { int prevTid = data.Payload.ReadFieldAsInt32("_prev_tid"); if (lastContextSwitch.TryGetValue(context.CurrentCpu, out ContextSwitch previousContextSwitch)) { if (prevTid == previousContextSwitch.NextTid) { processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, data.Timestamp)); } else { ///If we missed context switch events, processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, previousContextSwitch.SwitchInTime)); } } int nextTid = data.Payload.ReadFieldAsInt32("_next_tid"); ThreadInfo.ThreadState switchOutState; var prevStateValue = data.Payload.FieldsByName["_prev_state"]; if (prevStateValue.FieldType == CtfTypes.Enum) { ((CtfEnumValue)prevStateValue).IntegerValue.TryGetInt32(out int enumValue); switchOutState = (ThreadInfo.ThreadState)enumValue; } else { switchOutState = (ThreadInfo.ThreadState)data.Payload.ReadFieldAsInt32("_prev_state"); } ThreadInfo prevThread; if (runningThreads.TryGetValue(prevTid, out prevThread)) { prevThread.SwitchOut(data, switchOutState); } else { prevThread = new ThreadInfo(prevTid, data.Timestamp, switchOutState); this.AddNewThread(prevThread); } if (this.EventHasMetadata(data)) { this.ProcessThreadMetadata(data, prevThread); } ThreadInfo nextThread; if (runningThreads.TryGetValue(nextTid, out nextThread)) { lastContextSwitch[context.CurrentCpu] = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu); nextThread.SwitchIn(data.Timestamp); } else { nextThread = new ThreadInfo(nextTid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING); lastContextSwitch[context.CurrentCpu] = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu); this.AddNewThread(nextThread); } }
public override DataProcessingResult CookDataElement(LTTngEvent data, LTTngContext context, CancellationToken cancellationToken) { this.lastEventTimestamp = data.Timestamp; this.ProcessEventDrop(data, context); var result = DataProcessingResult.Ignored; try { if (data.Name.StartsWith("syscall") && this.EventHasMetadata(data)) { this.ProcessSyscallEventMetadata(data); result = DataProcessingResult.Processed; } switch (data.Name) { case SchedulerDataKeys.Switch: this.ProcessContextSwitch(data, context); return(DataProcessingResult.Processed); case SchedulerDataKeys.Wakeup: case SchedulerDataKeys.NewWakeup: this.ProcessThreadWakeUp(data, context); return(DataProcessingResult.Processed); case SchedulerDataKeys.Waking: this.ProcessThreadWaking(data, context); return(DataProcessingResult.Processed); case SchedulerDataKeys.ProcessFork: this.ProcessSchedForkEvent(data, context); return(DataProcessingResult.Processed); case SchedulerDataKeys.ProcessExit: this.ProcessThreadExit(data); return(DataProcessingResult.Processed); case SchedulerDataKeys.ProcessExec: this.ProcessThreadExec(data); return(DataProcessingResult.Processed); case ThreadCreationDataKeys.CloneEntry: this.ProcessThreadCloneSyscallEntry(data, context); return(DataProcessingResult.Processed); case ThreadCreationDataKeys.CloneExit: this.ProcessThreadCloneSyscallExit(data, context); return(DataProcessingResult.Processed); case LTTngThreadDataCooker.GetPidExit: this.ProcessGetPidSyscallExit(data, context); return(DataProcessingResult.Processed); case StatedumpDataKeys.ProcessState: this.ProcessStatedump(data); return(DataProcessingResult.Processed); } } catch (CtfPlaybackException e) { Console.Error.WriteLine(e); return(DataProcessingResult.CorruptData); } return(result); }