public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { Debug.Assert(!(tableBuilder is null) && !(tableData is null)); var quicState = tableData.QueryOutput <QuicState>(new DataOutputPath(QuicEventCooker.CookerPath, "State")); var data = quicState.Connections.SelectMany( x => x.GetRawTputEvents().Select(y => new ValueTuple <QuicConnection, QuicRawTputData>(x, y))).ToArray(); var table = tableBuilder.SetRowCount(data.Length); var dataProjection = Projection.Index(data); table.AddColumn(connectionColumnConfig, dataProjection.Compose(ProjectId)); table.AddColumn(processIdColumnConfig, dataProjection.Compose(ProjectProcessId)); table.AddColumn(typeColumnConfig, dataProjection.Compose(ProjectType)); table.AddColumn(timeColumnConfig, dataProjection.Compose(ProjectTime)); table.AddColumn(durationColumnConfig, dataProjection.Compose(ProjectDuration)); table.AddColumn(bitsColumnConfig, dataProjection.Compose(ProjectBits)); table.AddColumn(bytesColumnConfig, dataProjection.Compose(ProjectBytes)); table.AddColumn(rttColumnConfig, dataProjection.Compose(ProjectRtt)); tableConfig1.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig1.InitialSelectionQuery = "[Series Name]:=\"Type\""; tableConfig1.InitialFilterQuery = "[Type]:<>\"Tx\" AND [Type]:<>\"Rx\""; tableBuilder.AddTableConfiguration(tableConfig1); tableConfig2.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig2.AddColumnRole(ColumnRole.Duration, durationColumnConfig); tableConfig2.InitialSelectionQuery = "[Type]:=\"InFlight\""; tableConfig2.InitialFilterQuery = "[Type]:=\"Tx\" OR [Type]:=\"TxAck\" OR [Type]:=\"TxUdp\" OR [Type]:=\"Rx\" OR [Type]:=\"Rtt\""; tableBuilder.AddTableConfiguration(tableConfig2); tableConfig3.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig3.AddColumnRole(ColumnRole.Duration, durationColumnConfig); tableConfig3.InitialFilterQuery = "[Type]:<>\"Rtt\""; tableBuilder.AddTableConfiguration(tableConfig3); tableConfig4.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig4.InitialSelectionQuery = "[Type]:=\"Tx\" OR [Type]:=\"Rx\""; tableConfig4.InitialFilterQuery = "[Type]:<>\"Tx\" AND [Type]:<>\"TxAck\" AND [Type]:<>\"TxUdp\" AND [Type]:<>\"Rx\""; tableBuilder.AddTableConfiguration(tableConfig4); tableBuilder.SetDefaultTableConfiguration(tableConfig1); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { Debug.Assert(!(tableBuilder is null) && !(tableData is null)); var quicState = tableData.QueryOutput <QuicState>(new DataOutputPath(QuicEventCooker.CookerPath, "State")); if (quicState == null) { return; } var datapaths = quicState.Datapaths; if (datapaths.Count == 0) { return; } var data = new List <Data>(); foreach (var datapath in datapaths) { foreach (var evt in datapath.GetDatapathEvents()) { data.Add(new Data(datapath, true, evt.TimeStamp, evt.Duration, evt.TxBatchRate)); data.Add(new Data(datapath, false, evt.TimeStamp, evt.Duration, evt.RxBatchRate)); } } var table = tableBuilder.SetRowCount(data.Count); var dataProjection = Projection.Index(data); table.AddColumn(datapathColumnConfig, dataProjection.Compose(ProjectId)); table.AddColumn(processIdColumnConfig, dataProjection.Compose(ProjectProcessId)); table.AddColumn(typeColumnConfig, dataProjection.Compose(ProjectType)); table.AddColumn(timeColumnConfig, dataProjection.Compose(ProjectTime)); table.AddColumn(durationColumnConfig, dataProjection.Compose(ProjectDuration)); table.AddColumn(rateColumnConfig, dataProjection.Compose(ProjectRate)); tableConfig1.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig1.AddColumnRole(ColumnRole.Duration, durationColumnConfig); tableConfig1.InitialSelectionQuery = "[Series Name]:=\"Type\""; tableBuilder.AddTableConfiguration(tableConfig1); tableBuilder.SetDefaultTableConfiguration(tableConfig1); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoCpuFrequencyEvent> >( new DataOutputPath(PerfettoPluginConstants.CpuFrequencyEventCookerPath, nameof(PerfettoCpuFrequencyEventCooker.CpuFrequencyEvents))); // Start construction of the column order. Pivot on process and thread List <ColumnConfiguration> allColumns = new List <ColumnConfiguration>() { CpuNumColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, CpuStateColumn, DurationColumn, IsIdleColumn, TableConfiguration.GraphColumn, // Columns after this get graphed CpuFrequencyColumn }; var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var baseProjection = Projection.Index(events); tableGenerator.AddColumn(CpuNumColumn, baseProjection.Compose(x => x.CpuNum)); tableGenerator.AddColumn(CpuFrequencyColumn, baseProjection.Compose(x => x.CpuFrequency)); tableGenerator.AddColumn(StartTimestampColumn, baseProjection.Compose(x => x.StartTimestamp)); tableGenerator.AddColumn(CpuStateColumn, baseProjection.Compose(x => x.Name)); tableGenerator.AddColumn(DurationColumn, baseProjection.Compose(x => x.Duration)); tableGenerator.AddColumn(IsIdleColumn, baseProjection.Compose(x => x.IsIdle)); // We are graphing CPU frequency + duration with MAX accumulation, which gives a steady line graph of the current CPU frequency var tableConfig = new TableConfiguration("CPU Frequency") { Columns = allColumns, ChartType = ChartType.Line }; tableConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); tableConfig.AddColumnRole(ColumnRole.ResourceId, CpuNumColumn); tableConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); tableBuilder.AddTableConfiguration(tableConfig).SetDefaultTableConfiguration(tableConfig); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { var contextSwitches = tableData.QueryOutput <ProcessedEventData <IContextSwitch> >( DataOutputPath.Create("LTTng/CpuDataCooker/ContextSwitches")); if (contextSwitches.Count == 0) { return; } var table = tableBuilder.SetRowCount((int)contextSwitches.Count); table.AddColumn(oldThreadIdColumn, Projection.CreateUsingFuncAdaptor((i) => contextSwitches[(uint)i].SwitchOut.ThreadId)); table.AddColumn(oldImageNameColumn, Projection.CreateUsingFuncAdaptor((i) => contextSwitches[(uint)i].SwitchOut.ImageName)); table.AddColumn(oldPriorityColumn, Projection.CreateUsingFuncAdaptor((i) => contextSwitches[(uint)i].SwitchOut.Priority)); table.AddColumn(newThreadIdColumn, Projection.CreateUsingFuncAdaptor((i) => contextSwitches[(uint)i].SwitchIn.ThreadId)); table.AddColumn(newImageNameColumn, Projection.CreateUsingFuncAdaptor((i) => contextSwitches[(uint)i].SwitchIn.ImageName)); table.AddColumn(newPriorityColumn, Projection.CreateUsingFuncAdaptor((i) => contextSwitches[(uint)i].SwitchIn.Priority)); table.AddColumn(timestampColumn, Projection.CreateUsingFuncAdaptor((i) => contextSwitches[(uint)i].Timestamp)); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { Debug.Assert(!(tableBuilder is null) && !(tableData is null)); var quicState = tableData.QueryOutput <QuicState>(new DataOutputPath(QuicEventCooker.CookerPath, "State")); if (quicState == null) { return; } var data = quicState.GetApiCalls(); if (data.Count == 0) { return; } var table = tableBuilder.SetRowCount(data.Count); var dataProjection = Projection.Index(data); table.AddColumn(typeColumnConfig, dataProjection.Compose(ProjectType)); table.AddColumn(processIdColumnConfig, dataProjection.Compose(ProjectProcessId)); table.AddColumn(threadIdColumnConfig, dataProjection.Compose(ProjectThreadId)); table.AddColumn(cpuColumnConfig, dataProjection.Compose(ProjectCpu)); table.AddColumn(pointerColumnConfig, dataProjection.Compose(ProjectPointer)); table.AddColumn(resultColumnConfig, dataProjection.Compose(ProjectResult)); table.AddColumn(countColumnConfig, Projection.Constant <uint>(1)); table.AddColumn(timeColumnConfig, dataProjection.Compose(ProjectTime)); table.AddColumn(durationColumnConfig, dataProjection.Compose(ProjectDuration)); tableConfig1.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig1.AddColumnRole(ColumnRole.Duration, durationColumnConfig); tableBuilder.AddTableConfiguration(tableConfig1); tableConfig2.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig2.AddColumnRole(ColumnRole.Duration, durationColumnConfig); tableBuilder.AddTableConfiguration(tableConfig2); tableBuilder.SetDefaultTableConfiguration(tableConfig1); }
internal static void BuildMetadataTable(ITableBuilder tableBuilder, LTTngSourceParser sourceParser, ITableConfigurationsSerializer serializer) { ITableBuilderWithRowCount table = tableBuilder.SetRowCount(sourceParser.TraceStats.Count); IReadOnlyList <string> eventNames = sourceParser.TraceStats.Keys.ToList(); var eventNameProjection = Projection.CreateUsingFuncAdaptor(x => eventNames[x]); var traceStatsProjection = eventNameProjection.Compose(eventName => sourceParser.TraceStats[eventName]); var eventCountProjection = traceStatsProjection.Compose(traceStats => traceStats.EventCount); var payloadBitCountProjection = traceStatsProjection.Compose(traceStats => (double)traceStats.PayloadBitCount / 8); table.AddColumn( new DataColumn <string>( EventNameConfiguration, eventNameProjection)); table.AddColumn( new DataColumn <ulong>( CountConfiguration, eventCountProjection)); table.AddColumn( new DataColumn <double>( TotalPayloadSizeConfiguration, payloadBitCountProjection)); var configurations = TableConfigurations.GetPrebuiltTableConfigurations( typeof(TraceStatsTable), TableDescriptor.Guid, serializer); foreach (var configuration in configurations) { tableBuilder.AddTableConfiguration(configuration); if (StringComparer.Ordinal.Equals(configuration.Name, configurations.DefaultConfigurationName)) { tableBuilder.SetDefaultTableConfiguration(configuration); } } }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { Debug.Assert(!(tableBuilder is null) && !(tableData is null)); var quicState = tableData.QueryOutput <QuicState>(new DataOutputPath(QuicEventCooker.CookerPath, "State")); if (quicState == null) { return; } var connections = quicState.Connections; if (connections.Count == 0) { return; } var table = tableBuilder.SetRowCount(connections.Count); var dataProjection = Projection.Index(connections); table.AddColumn(connectionColumnConfig, dataProjection.Compose(ProjectId)); table.AddColumn(processIdColumnConfig, dataProjection.Compose(ProjectProcessId)); table.AddColumn(pointerColumnConfig, dataProjection.Compose(ProjectPointer)); table.AddColumn(correlationIdColumnConfig, dataProjection.Compose(ProjectCorrelationId)); table.AddColumn(isServerColumnConfig, dataProjection.Compose(ProjectIsServer)); table.AddColumn(stateColumnConfig, dataProjection.Compose(ProjectState)); table.AddColumn(bytesSentColumnConfig, dataProjection.Compose(ProjectBytesSent)); table.AddColumn(bytesReceivedColumnConfig, dataProjection.Compose(ProjectBytesReceived)); table.AddColumn(timeColumnConfig, dataProjection.Compose(ProjectTime)); table.AddColumn(durationColumnConfig, dataProjection.Compose(ProjectDuration)); tableConfig1.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig1.AddColumnRole(ColumnRole.Duration, durationColumnConfig); tableConfig1.InitialExpansionQuery = "[Series Name]:=\"Process (ID)\""; tableConfig1.InitialSelectionQuery = "[Series Name]:=\"Connection\""; tableBuilder.AddTableConfiguration(tableConfig1); tableBuilder.SetDefaultTableConfiguration(tableConfig1); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { Debug.Assert(!(tableBuilder is null) && !(tableData is null)); var quicState = tableData.QueryOutput <QuicState>(new DataOutputPath(QuicEventCooker.CookerPath, "State")); if (quicState == null) { return; } var events = quicState.Events .Where(x => x.EventId == QuicEventId.DatapathSend || x.EventId == QuicEventId.DatapathRecv).ToArray(); if (events.Length == 0) { return; } var table = tableBuilder.SetRowCount(events.Length); var dataProjection = Projection.Index(events); table.AddColumn(processIdColumnConfig, dataProjection.Compose(ProjectProcessId)); table.AddColumn(threadIdColumnConfig, dataProjection.Compose(ProjectThreadId)); table.AddColumn(cpuColumnConfig, dataProjection.Compose(ProjectCPU)); table.AddColumn(typeColumnConfig, dataProjection.Compose(ProjectType)); table.AddColumn(timeColumnConfig, dataProjection.Compose(ProjectTime)); table.AddColumn(bytesColumnConfig, dataProjection.Compose(ProjectBytes)); table.AddColumn(bitsColumnConfig, dataProjection.Compose(ProjectBits)); tableConfig1.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableBuilder.AddTableConfiguration(tableConfig1); tableConfig2.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableBuilder.AddTableConfiguration(tableConfig2); tableBuilder.SetDefaultTableConfiguration(tableConfig1); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoLogcatEvent> >( new DataOutputPath(PerfettoPluginConstants.LogcatEventCookerPath, nameof(PerfettoLogcatEventCooker.LogcatEvents))); // Start construction of the column order. Pivot on process and thread List <ColumnConfiguration> allColumns = new List <ColumnConfiguration>() { ProcessNameColumn, ThreadNameColumn, TagColumn, MessageColumn, PriorityColumn, TableConfiguration.GraphColumn, // Columns after this get graphed StartTimestampColumn }; var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var baseProjection = Projection.Index(events); tableGenerator.AddColumn(StartTimestampColumn, baseProjection.Compose(x => x.StartTimestamp)); tableGenerator.AddColumn(ProcessNameColumn, baseProjection.Compose(x => x.ProcessName)); tableGenerator.AddColumn(ThreadNameColumn, baseProjection.Compose(x => x.ThreadName)); tableGenerator.AddColumn(PriorityColumn, baseProjection.Compose(x => x.Priority)); tableGenerator.AddColumn(TagColumn, baseProjection.Compose(x => x.Tag)); tableGenerator.AddColumn(MessageColumn, baseProjection.Compose(x => x.Message)); var tableConfig = new TableConfiguration("Logcat Events") { Columns = allColumns, }; tableConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); tableBuilder.AddTableConfiguration(tableConfig).SetDefaultTableConfiguration(tableConfig); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { Debug.Assert(!(tableBuilder is null) && !(tableData is null)); var quicState = tableData.QueryOutput <QuicState>(new DataOutputPath(QuicEventCooker.CookerPath, "State")); if (quicState == null) { return; } var connections = quicState.Connections; if (connections.Count == 0) { return; } var data = connections.SelectMany( x => x.GetThroughputEvents().Select( y => new ValueTuple <QuicConnection, QuicThroughputData>(x, y))).ToArray(); var table = tableBuilder.SetRowCount(data.Length); var dataProjection = Projection.Index(data); table.AddColumn(connectionColumnConfig, dataProjection.Compose(ProjectId)); table.AddColumn(processIdColumnConfig, dataProjection.Compose(ProjectProcessId)); table.AddColumn(timeColumnConfig, dataProjection.Compose(ProjectTime)); table.AddColumn(durationColumnConfig, dataProjection.Compose(ProjectDuration)); table.AddColumn(rttColumnConfig, dataProjection.Compose(ProjectRate)); tableConfig1.AddColumnRole(ColumnRole.StartTime, timeColumnConfig); tableConfig1.AddColumnRole(ColumnRole.Duration, durationColumnConfig); tableBuilder.AddTableConfiguration(tableConfig1); tableBuilder.SetDefaultTableConfiguration(tableConfig1); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { int maximumFieldCount = tableData.QueryOutput <int>( DataOutputPath.Create("Perf/GenericEvents/MaximumEventFieldCount")); var events = tableData.QueryOutput <ProcessedEventData <PerfGenericEvent> >( DataOutputPath.Create("Perf/GenericEvents/Events")); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var genericEventProjection = new GenericEventProjection(events); var eventNameColumn = new BaseDataColumn <string>( eventNameColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.EventName)); tableGenerator.AddColumn(eventNameColumn); var eventIdColumn = new BaseDataColumn <uint>( eventIdColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Id)); tableGenerator.AddColumn(eventIdColumn); var cpuIdColumn = new BaseDataColumn <uint>( cpuIdColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.CpuId)); tableGenerator.AddColumn(cpuIdColumn); var eventTimestampColumn = new BaseDataColumn <Timestamp>( eventTimestampColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Timestamp)); tableGenerator.AddColumn(eventTimestampColumn); tableGenerator.AddColumn(countColumnConfig, Projection.Constant(1)); // Add the field columns, with column names depending on the given event for (int columnIndex = 0; columnIndex < maximumFieldCount; columnIndex++) { string fieldName = "Field " + (columnIndex + 1); var genericEventFieldProjection = new GenericEventFieldProjection(columnIndex, genericEventProjection); var genericEventFieldNameProjection = genericEventFieldProjection.Compose((field) => field.HasValue ? field.Value.Name : string.Empty); // generate a column configuration var fieldColumnConfiguration = new ColumnConfiguration( new ColumnMetadata(GenerateGuidFromName(fieldName), fieldName, genericEventFieldNameProjection, fieldName), new UIHints { IsVisible = true, Width = 80, TextAlignment = TextAlignment.Left, }); var genericEventFieldAsStringProjection = genericEventFieldProjection.Compose((field) => field.HasValue ? field.Value.Value : string.Empty); tableGenerator.AddColumn(fieldColumnConfiguration, genericEventFieldAsStringProjection); } }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // We dynamically adjust the column headers // This is the max number of fields we can expect for this table int maxFieldCount = Math.Min(AbsoluteMaxFields, tableData.QueryOutput <int>( new DataOutputPath(PerfettoPluginConstants.FtraceEventCookerPath, nameof(PerfettoFtraceEventCooker.MaximumEventFieldCount)))); // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoFtraceEvent> >( new DataOutputPath(PerfettoPluginConstants.FtraceEventCookerPath, nameof(PerfettoFtraceEventCooker.FtraceEvents))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var eventProjection = new EventProjection <PerfettoFtraceEvent>(events); var processNameColumn = new DataColumn <string>( ProcessNameColumn, eventProjection.Compose((ftraceEvent) => ftraceEvent.ProcessFormattedName)); tableGenerator.AddColumn(processNameColumn); var threadNameColumn = new DataColumn <string>( ThreadNameColumn, eventProjection.Compose((ftraceEvent) => ftraceEvent.ThreadFormattedName)); tableGenerator.AddColumn(threadNameColumn); var startTimestampColumn = new DataColumn <Timestamp>( StartTimestampColumn, eventProjection.Compose((ftraceEvent) => ftraceEvent.StartTimestamp)); tableGenerator.AddColumn(startTimestampColumn); var cpuColumn = new DataColumn <uint>( CpuColumn, eventProjection.Compose((ftraceEvent) => ftraceEvent.Cpu)); tableGenerator.AddColumn(cpuColumn); var nameColumn = new DataColumn <string>( NameColumn, eventProjection.Compose((ftraceEvent) => ftraceEvent.Name)); tableGenerator.AddColumn(nameColumn); List <ColumnConfiguration> fieldColumns = new List <ColumnConfiguration>(); // Add the field columns, with column names depending on the given event for (int index = 0; index < maxFieldCount; index++) { var colIndex = index; // This seems unncessary but causes odd runtime behavior if not done this way. Compiler is confused perhaps because w/o this func will index=event.FieldNames.Count every time. index is passed as ref but colIndex as value into func string fieldName = "Field " + (colIndex + 1); var eventFieldNameProjection = eventProjection.Compose((ftraceEvent) => colIndex < ftraceEvent.Args?.Count ? ftraceEvent.Args.ElementAt(colIndex).Key : string.Empty); // generate a column configuration var fieldColumnConfiguration = new ColumnConfiguration( new ColumnMetadata(Common.GenerateGuidFromName(fieldName), fieldName, eventFieldNameProjection, fieldName), new UIHints { IsVisible = true, Width = 150, TextAlignment = TextAlignment.Left, }); // Add this column to the column order fieldColumns.Add(fieldColumnConfiguration); var eventFieldAsStringProjection = eventProjection.Compose((ftraceEvent) => colIndex < ftraceEvent.Args?.Count ? ftraceEvent.Args.ElementAt(colIndex).Value : string.Empty); tableGenerator.AddColumn(fieldColumnConfiguration, eventFieldAsStringProjection); } // Start construction of the column order. Pivot on CPU List <ColumnConfiguration> cpuColumns = new List <ColumnConfiguration>() { CpuColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted ProcessNameColumn, ThreadNameColumn, NameColumn, }; cpuColumns.AddRange(fieldColumns); cpuColumns.Add(TableConfiguration.GraphColumn); // Columns after this get graphed cpuColumns.Add(StartTimestampColumn); var cpuConfig = new TableConfiguration("CPU") { Columns = cpuColumns, }; cpuConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); // Start construction of the column order. Pivot on process and thread List <ColumnConfiguration> processThreadColumns = new List <ColumnConfiguration>() { ProcessNameColumn, ThreadNameColumn, NameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted CpuColumn, }; processThreadColumns.AddRange(fieldColumns); processThreadColumns.Add(TableConfiguration.GraphColumn); // Columns after this get graphed processThreadColumns.Add(StartTimestampColumn); var processThreadConfig = new TableConfiguration("Process-Thread") { Columns = processThreadColumns, }; processThreadConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); tableBuilder .AddTableConfiguration(cpuConfig) .AddTableConfiguration(processThreadConfig) .SetDefaultTableConfiguration(processThreadConfig); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoProcessEvent> >( new DataOutputPath(PerfettoPluginConstants.ProcessEventCookerPath, nameof(PerfettoProcessEventCooker.ProcessEvents))); int maxArgsFieldCount = Math.Min(AbsoluteMaxFields, tableData.QueryOutput <int>( new DataOutputPath(PerfettoPluginConstants.ProcessEventCookerPath, nameof(PerfettoProcessEventCooker.MaximumArgsEventFieldCount)))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var baseProjection = Projection.Index(events); tableGenerator.AddColumn(ProcessNameColumn, baseProjection.Compose(x => x.Name)); tableGenerator.AddColumn(ProcessLabelColumn, baseProjection.Compose(x => x.Label)); tableGenerator.AddColumn(StartTimestampColumn, baseProjection.Compose(x => x.StartTimestamp)); tableGenerator.AddColumn(EndTimestampColumn, baseProjection.Compose(x => x.EndTimestamp)); tableGenerator.AddColumn(UpidColumn, baseProjection.Compose(x => x.Upid)); tableGenerator.AddColumn(PidColumn, baseProjection.Compose(x => x.Pid)); tableGenerator.AddColumn(ParentUpidColumn, baseProjection.Compose(x => x.ParentUpid)); tableGenerator.AddColumn(ParentProcessNameColumn, baseProjection.Compose(x => x.ParentProcess != null ? x.ParentProcess.Name : String.Empty)); tableGenerator.AddColumn(UidColumn, baseProjection.Compose(x => x.Uid)); tableGenerator.AddColumn(AndroidAppIdColumn, baseProjection.Compose(x => x.AndroidAppId)); tableGenerator.AddColumn(CmdLineColumn, baseProjection.Compose(x => x.CmdLine)); if (events.Any(f => !String.IsNullOrWhiteSpace(f.Label))) { ProcessLabelColumn.DisplayHints.IsVisible = true; } List <ColumnConfiguration> extraProcessArgColumns = new List <ColumnConfiguration>(); // Add the field columns, with column names depending on the given event for (int index = 0; index < maxArgsFieldCount; index++) { var colIndex = index; // This seems unncessary but causes odd runtime behavior if not done this way. Compiler is confused perhaps because w/o this func will index=genericEvent.FieldNames.Count every time. index is passed as ref but colIndex as value into func string fieldName = "Field " + (colIndex + 1); var processArgKeysFieldNameProjection = baseProjection.Compose((pe) => colIndex < pe.Args?.Count ? pe.Args.Keys.ElementAt(colIndex) : string.Empty); // generate a column configuration var fieldColumnConfiguration = new ColumnConfiguration( new ColumnMetadata(Common.GenerateGuidFromName(fieldName), fieldName, processArgKeysFieldNameProjection, fieldName) { IsDynamic = true }, new UIHints { IsVisible = true, Width = 150, TextAlignment = TextAlignment.Left, }); // Add this column to the column order extraProcessArgColumns.Add(fieldColumnConfiguration); var argsAsStringProjection = baseProjection.Compose((pe) => colIndex < pe.Args?.Count ? pe.Args.Values.ElementAt(colIndex).ToString() : string.Empty); tableGenerator.AddColumn(fieldColumnConfiguration, argsAsStringProjection); } // Default List <ColumnConfiguration> defaultColumns = new List <ColumnConfiguration>() { ProcessNameColumn, ProcessLabelColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on CmdLineColumn, PidColumn, UpidColumn, ParentUpidColumn, ParentProcessNameColumn, UidColumn, AndroidAppIdColumn, }; defaultColumns.AddRange(extraProcessArgColumns); defaultColumns.Add(TableConfiguration.GraphColumn); // Columns after this get graphed defaultColumns.Add(StartTimestampColumn); defaultColumns.Add(EndTimestampColumn); var processDefaultConfig = new TableConfiguration("Default") { Columns = defaultColumns, ChartType = ChartType.Line }; processDefaultConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn); processDefaultConfig.AddColumnRole(ColumnRole.EndTime, EndTimestampColumn);; tableBuilder.AddTableConfiguration(processDefaultConfig) .SetDefaultTableConfiguration(processDefaultConfig); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoProcessMemoryEvent> >( new DataOutputPath(PerfettoPluginConstants.ProcessMemoryEventCookerPath, nameof(PerfettoProcessMemoryEventCooker.ProcessMemoryEvents))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var baseProjection = Projection.Index(events); tableGenerator.AddColumn(StartTimestampColumn, baseProjection.Compose(x => x.StartTimestamp)); tableGenerator.AddColumn(ProcessNameColumn, baseProjection.Compose(x => x.ProcessName)); tableGenerator.AddColumn(DurationColumn, baseProjection.Compose(x => x.Duration)); tableGenerator.AddColumn(RssAnonColumn, baseProjection.Compose(x => x.RssAnon)); tableGenerator.AddColumn(LockedColumn, baseProjection.Compose(x => x.Locked)); tableGenerator.AddColumn(RssShMemColumn, baseProjection.Compose(x => x.RssShMem)); tableGenerator.AddColumn(RssFileColumn, baseProjection.Compose(x => x.RssFile)); tableGenerator.AddColumn(RssHwmColumn, baseProjection.Compose(x => x.RssHwm)); tableGenerator.AddColumn(RssColumn, baseProjection.Compose(x => x.Rss)); tableGenerator.AddColumn(SwapColumn, baseProjection.Compose(x => x.Swap)); tableGenerator.AddColumn(VirtColumn, baseProjection.Compose(x => x.Virt)); // Virtual var virtConfig = new TableConfiguration("Virtual") { Columns = new[] { ProcessNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, DurationColumn, RssAnonColumn, RssShMemColumn, RssFileColumn, RssHwmColumn, RssColumn, LockedColumn, SwapColumn, TableConfiguration.GraphColumn, // Columns after this get graphed VirtColumn }, ChartType = ChartType.Line }; virtConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); virtConfig.AddColumnRole(ColumnRole.ResourceId, ProcessNameColumn); virtConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); // Swap var swapConfig = new TableConfiguration("Swap") { Columns = new[] { ProcessNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, DurationColumn, RssAnonColumn, RssShMemColumn, RssFileColumn, RssHwmColumn, RssColumn, LockedColumn, VirtColumn, TableConfiguration.GraphColumn, // Columns after this get graphed SwapColumn }, ChartType = ChartType.Line }; swapConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); swapConfig.AddColumnRole(ColumnRole.ResourceId, ProcessNameColumn); swapConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); // Locked var lockedConfig = new TableConfiguration("Locked") { Columns = new[] { ProcessNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, DurationColumn, RssAnonColumn, RssShMemColumn, RssFileColumn, RssHwmColumn, RssColumn, SwapColumn, VirtColumn, TableConfiguration.GraphColumn, // Columns after this get graphed LockedColumn }, ChartType = ChartType.Line }; lockedConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); lockedConfig.AddColumnRole(ColumnRole.ResourceId, ProcessNameColumn); lockedConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); // Rss var rssConfig = new TableConfiguration("RSS (sum of anon, file, shared mem)") { Columns = new[] { ProcessNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, DurationColumn, RssAnonColumn, RssShMemColumn, RssFileColumn, RssHwmColumn, LockedColumn, SwapColumn, VirtColumn, TableConfiguration.GraphColumn, // Columns after this get graphed RssColumn }, ChartType = ChartType.Line }; rssConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); rssConfig.AddColumnRole(ColumnRole.ResourceId, ProcessNameColumn); rssConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); // rssHwm var rssHwmConfig = new TableConfiguration("RSS Peak (high water mark)") { Columns = new[] { ProcessNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, DurationColumn, RssAnonColumn, RssShMemColumn, RssFileColumn, RssColumn, LockedColumn, SwapColumn, VirtColumn, TableConfiguration.GraphColumn, // Columns after this get graphed RssHwmColumn }, ChartType = ChartType.Line }; rssHwmConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); rssHwmConfig.AddColumnRole(ColumnRole.ResourceId, ProcessNameColumn); rssHwmConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); // rssFile var rssFileConfig = new TableConfiguration("RSS File") { Columns = new[] { ProcessNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, DurationColumn, RssAnonColumn, RssShMemColumn, RssHwmColumn, RssColumn, LockedColumn, SwapColumn, VirtColumn, TableConfiguration.GraphColumn, // Columns after this get graphed RssFileColumn }, ChartType = ChartType.Line }; rssFileConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); rssFileConfig.AddColumnRole(ColumnRole.ResourceId, ProcessNameColumn); rssFileConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); // rssShMem var rssShMemConfig = new TableConfiguration("RSS Shared Memory") { Columns = new[] { ProcessNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, DurationColumn, RssAnonColumn, RssFileColumn, RssHwmColumn, RssColumn, LockedColumn, SwapColumn, VirtColumn, TableConfiguration.GraphColumn, // Columns after this get graphed RssShMemColumn }, ChartType = ChartType.Line }; rssShMemConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); rssShMemConfig.AddColumnRole(ColumnRole.ResourceId, ProcessNameColumn); rssShMemConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); // rssAnon var rssAnonConfig = new TableConfiguration("RSS Anonymous") { Columns = new[] { ProcessNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on StartTimestampColumn, DurationColumn, RssShMemColumn, RssFileColumn, RssHwmColumn, RssColumn, LockedColumn, SwapColumn, VirtColumn, TableConfiguration.GraphColumn, // Columns after this get graphed RssAnonColumn }, ChartType = ChartType.Line }; rssAnonConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); rssAnonConfig.AddColumnRole(ColumnRole.ResourceId, ProcessNameColumn); rssAnonConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); tableBuilder.AddTableConfiguration(virtConfig) .AddTableConfiguration(virtConfig) .AddTableConfiguration(swapConfig) .AddTableConfiguration(lockedConfig) .AddTableConfiguration(rssConfig) .AddTableConfiguration(rssHwmConfig) .AddTableConfiguration(rssFileConfig) .AddTableConfiguration(rssShMemConfig) .AddTableConfiguration(rssAnonConfig) .SetDefaultTableConfiguration(virtConfig); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoCpuSamplingEvent> >( new DataOutputPath(PerfettoPluginConstants.CpuSamplingEventCookerPath, nameof(PerfettoCpuSamplingEventCooker.CpuSamplingEvents))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var baseProjection = Projection.Index(events); var startProjection = baseProjection.Compose(x => x.Timestamp); tableGenerator.AddColumn(CpuColumn, baseProjection.Compose(x => x.Cpu)); tableGenerator.AddColumn(ProcessNameColumn, baseProjection.Compose(x => x.ProcessName)); tableGenerator.AddColumn(ThreadNameColumn, baseProjection.Compose(x => x.ThreadName)); tableGenerator.AddColumn(UnwindErrorColumn, baseProjection.Compose(x => x.UnwindError)); tableGenerator.AddColumn(ModuleColumn, baseProjection.Compose(x => x.Module)); tableGenerator.AddColumn(FunctionColumn, baseProjection.Compose(x => x.Function)); tableGenerator.AddHierarchicalColumn(CallStackColumn, baseProjection.Compose(x => x.CallStack), new ArrayAccessProvider <string>()); tableGenerator.AddColumn(TimestampColumn, startProjection); var processStackConfig = new TableConfiguration("By Process, Stack") { Columns = new[] { ProcessNameColumn, CallStackColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on ThreadNameColumn, ModuleColumn, FunctionColumn, CpuColumn, UnwindErrorColumn, TableConfiguration.GraphColumn, // Columns after this get graphed TimestampColumn, }, }; processStackConfig.AddColumnRole(ColumnRole.StartTime, TimestampColumn.Metadata.Guid); var processThreadStackConfig = new TableConfiguration("By Process, Thread, Stack") { Columns = new[] { ProcessNameColumn, ThreadNameColumn, CallStackColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on ModuleColumn, FunctionColumn, CpuColumn, UnwindErrorColumn, TableConfiguration.GraphColumn, // Columns after this get graphed TimestampColumn, }, }; processThreadStackConfig.AddColumnRole(ColumnRole.StartTime, TimestampColumn.Metadata.Guid); tableBuilder .AddTableConfiguration(processStackConfig) .AddTableConfiguration(processThreadStackConfig) .SetDefaultTableConfiguration(processStackConfig); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // We dynamically adjust the column headers // This is the max number of fields we can expect for this table int maxFieldCount = Math.Min(AbsoluteMaxFields, tableData.QueryOutput <int>( new DataOutputPath(PerfettoPluginConstants.GenericEventCookerPath, nameof(PerfettoGenericEventCooker.MaximumEventFieldCount)))); bool hasProviders = tableData.QueryOutput <bool>( new DataOutputPath(PerfettoPluginConstants.GenericEventCookerPath, nameof(PerfettoGenericEventCooker.HasProviders))); // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoGenericEvent> >( new DataOutputPath(PerfettoPluginConstants.GenericEventCookerPath, nameof(PerfettoGenericEventCooker.GenericEvents))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var genericEventProjection = new EventProjection <PerfettoGenericEvent>(events); // Add all the data projections var sliceIdColumn = new DataColumn <int>( SliceIdColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.SliceId)); tableGenerator.AddColumn(sliceIdColumn); var processNameColumn = new DataColumn <string>( ProcessNameColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Process)); tableGenerator.AddColumn(processNameColumn); var processLabelColumn = new DataColumn <string>( ProcessLabelColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.ProcessLabel)); tableGenerator.AddColumn(processLabelColumn); if (events.Any(f => !String.IsNullOrWhiteSpace(f.ProcessLabel))) { ProcessLabelColConfig.DisplayHints.IsVisible = true; } var threadNameColumn = new DataColumn <string>( ThreadNameColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Thread)); tableGenerator.AddColumn(threadNameColumn); var eventNameColumn = new DataColumn <string>( EventNameColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.EventName)); tableGenerator.AddColumn(eventNameColumn); var startTimestampColumn = new DataColumn <Timestamp>( StartTimestampColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.StartTimestamp)); tableGenerator.AddColumn(startTimestampColumn); var endTimestampColumn = new DataColumn <Timestamp>( EndTimestampColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.EndTimestamp)); tableGenerator.AddColumn(endTimestampColumn); var durationColumn = new DataColumn <TimestampDelta>( DurationNotSortedColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Duration)); tableGenerator.AddColumn(durationColumn); var durationExColumn = new DataColumn <TimestampDelta>( DurationExSortedColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.DurationExclusive)); tableGenerator.AddColumn(durationExColumn); var categoryColumn = new DataColumn <string>( CategoryColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Category)); tableGenerator.AddColumn(categoryColumn); var typeColumn = new DataColumn <string>( TypeColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Type)); tableGenerator.AddColumn(typeColumn); var providerColumn = new DataColumn <string>( ProviderColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Provider)); tableGenerator.AddColumn(providerColumn); var trackNameIdColumn = new DataColumn <string>( TrackNameIdColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.ThreadTrack != null ? (!String.IsNullOrWhiteSpace(genericEvent.ThreadTrack.Name) ? $"{genericEvent.ThreadTrack.Name} ({genericEvent.ThreadTrack.Id})" : genericEvent.ThreadTrack.Id.ToString()) : String.Empty)); tableGenerator.AddColumn(trackNameIdColumn); var parentIdColumn = new DataColumn <int>( ParentIdColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.ParentId.HasValue ? genericEvent.ParentId.Value : -1)); tableGenerator.AddColumn(parentIdColumn); var parentDepthLevelColumn = new DataColumn <int>( ParentDepthLevelColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.ParentTreeDepthLevel)); tableGenerator.AddColumn(parentDepthLevelColumn); tableGenerator.AddHierarchicalColumn(ParentEventNameTreeBranchColConfig, genericEventProjection.Compose((genericEvent) => genericEvent.ParentEventNameTree), new ArrayAccessProvider <string>()); tableGenerator.AddColumn(CountColConfig, Projection.Constant <int>(1)); // The provider column is optionally populated depending on whether or not the user specified a ProviderGUID mapping file ProviderColConfig.DisplayHints.IsVisible = hasProviders; List <ColumnConfiguration> fieldColumns = new List <ColumnConfiguration>(); // Add the field columns, with column names depending on the given event for (int index = 0; index < maxFieldCount; index++) { var colIndex = index; // This seems unncessary but causes odd runtime behavior if not done this way. Compiler is confused perhaps because w/o this func will index=genericEvent.FieldNames.Count every time. index is passed as ref but colIndex as value into func string fieldName = "Field " + (colIndex + 1); var genericEventFieldNameProjection = genericEventProjection.Compose((genericEvent) => colIndex < genericEvent.Args?.Count ? genericEvent.Args.ElementAt(colIndex).Key : string.Empty); // generate a column configuration var fieldColumnConfiguration = new ColumnConfiguration( new ColumnMetadata(Common.GenerateGuidFromName(fieldName), fieldName, genericEventFieldNameProjection, fieldName) { IsDynamic = true }, new UIHints { IsVisible = true, Width = 150, TextAlignment = TextAlignment.Left, }); // Add this column to the column order fieldColumns.Add(fieldColumnConfiguration); var genericEventFieldAsStringProjection = genericEventProjection.Compose((genericEvent) => colIndex < genericEvent.Args?.Count ? genericEvent.Args.ElementAt(colIndex).Value : string.Empty); tableGenerator.AddColumn(fieldColumnConfiguration, genericEventFieldAsStringProjection); } List <ColumnConfiguration> defaultColumns = new List <ColumnConfiguration>() { ProviderColConfig, ProcessNameColConfig, ProcessLabelColConfig, ThreadNameColConfig, TableConfiguration.PivotColumn, // Columns before this get pivotted on EventNameColConfig, CategoryColConfig, TypeColConfig, DurationNotSortedColConfig, DurationExSortedColConfig, }; defaultColumns.AddRange(fieldColumns); defaultColumns.Add(TableConfiguration.GraphColumn); // Columns after this get graphed defaultColumns.Add(StartTimestampColConfig); defaultColumns.Add(EndTimestampColConfig); // Proces-Thread config var processThreadConfig = new TableConfiguration("Process-Thread") { Columns = defaultColumns, }; SetGraphTableConfig(processThreadConfig); tableBuilder.AddTableConfiguration(processThreadConfig); // Process-Thread by StartTime config var processThreadByStartTimeColumns = new List <ColumnConfiguration>(defaultColumns); processThreadByStartTimeColumns.Remove(EndTimestampColConfig); processThreadByStartTimeColumns.Insert(processThreadByStartTimeColumns.Count - 2, EndTimestampColConfig); var processThreadByStartTimeConfig = new TableConfiguration("Process-Thread by Start Time") { Columns = processThreadByStartTimeColumns, }; SetGraphTableConfig(processThreadByStartTimeConfig); tableBuilder.AddTableConfiguration(processThreadByStartTimeConfig); // Process-Thread Activity config var processThreadActivityColumns = new List <ColumnConfiguration>(defaultColumns); processThreadActivityColumns.Remove(StartTimestampColConfig); processThreadActivityColumns.Insert(10, StartTimestampColConfig); processThreadActivityColumns.Remove(EndTimestampColConfig); processThreadActivityColumns.Insert(11, EndTimestampColConfig); processThreadActivityColumns.Add(CountSortedColConfig); // Different sorting than default processThreadActivityColumns.Remove(DurationExSortedColConfig); processThreadActivityColumns.Insert(9, DurationExNotSortedMaxColConfig); DurationExNotSortedMaxColConfig.DisplayHints.SortPriority = 1; DurationExNotSortedMaxColConfig.DisplayHints.SortOrder = SortOrder.Descending; var processThreadActivityConfig = new TableConfiguration("Process-Thread Activity") { Columns = processThreadActivityColumns, }; SetGraphTableConfig(processThreadActivityConfig); tableBuilder.AddTableConfiguration(processThreadActivityConfig); // Default - Process-Thread-NestedSlices-Name config var processThreadNameColumns = new List <ColumnConfiguration>(defaultColumns); processThreadNameColumns.Insert(4, ParentDepthLevelColConfig); processThreadNameColumns.Remove(EventNameColConfig); processThreadNameColumns.Insert(5, EventNameColConfig); var processThreadNestedNameConfig = new TableConfiguration("Process-Thread-NestedSlices-Name") { Columns = processThreadNameColumns, }; SetGraphTableConfig(processThreadNestedNameConfig); tableBuilder.AddTableConfiguration(processThreadNestedNameConfig) .SetDefaultTableConfiguration(processThreadNestedNameConfig); // Process-Thread-EventName config var processThreadEventNameColumns = new List <ColumnConfiguration>(defaultColumns); processThreadEventNameColumns.Remove(EventNameColConfig); processThreadEventNameColumns.Insert(4, EventNameColConfig); var processThreadEventNameConfig = new TableConfiguration("Process-Thread-Name") { Columns = processThreadEventNameColumns, }; SetGraphTableConfig(processThreadEventNameConfig); tableBuilder.AddTableConfiguration(processThreadEventNameConfig); // Process-Thread-Name by StartTime config var processThreadNameByStartTimeColumns = new List <ColumnConfiguration>(defaultColumns); processThreadNameByStartTimeColumns.Insert(4, ParentDepthLevelColConfig); processThreadNameByStartTimeColumns.Remove(EventNameColConfig); processThreadNameByStartTimeColumns.Insert(5, EventNameColConfig); processThreadNameByStartTimeColumns.Remove(EndTimestampColConfig); processThreadNameByStartTimeColumns.Insert(processThreadNameByStartTimeColumns.Count - 2, EndTimestampColConfig); var processThreadNameByStartTimeConfig = new TableConfiguration("Process-Thread-Name by Start Time") { Columns = processThreadNameByStartTimeColumns, }; SetGraphTableConfig(processThreadNameByStartTimeConfig); tableBuilder.AddTableConfiguration(processThreadNameByStartTimeConfig); // Process-Thread-ParentTree config var processThreadNameTreeColumns = new List <ColumnConfiguration>(defaultColumns); processThreadNameTreeColumns.Insert(4, ParentEventNameTreeBranchColConfig); processThreadNameTreeColumns.Remove(DurationExSortedColConfig); processThreadNameTreeColumns.Insert(10, DurationExSortedSumColConfig); var processThreadParentNameTreeConfig = new TableConfiguration("Process-Thread-ParentTree") { Columns = processThreadNameTreeColumns, }; ParentEventNameTreeBranchColConfig.DisplayHints.IsVisible = true; SetGraphTableConfig(processThreadParentNameTreeConfig); tableBuilder.AddTableConfiguration(processThreadParentNameTreeConfig); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { int maximumFieldCount = tableData.QueryOutput <int>( DataOutputPath.ForSource(LTTngConstants.SourceId, LTTngGenericEventDataCooker.Identifier, nameof(LTTngGenericEventDataCooker.MaximumEventFieldCount))); var events = tableData.QueryOutput <ProcessedEventData <LTTngGenericEvent> >( DataOutputPath.ForSource(LTTngConstants.SourceId, LTTngGenericEventDataCooker.Identifier, nameof(LTTngGenericEventDataCooker.Events))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var genericEventProjection = new EventProjection <LTTngGenericEvent>(events); var eventNameColumn = new DataColumn <string>( eventNameColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.EventName)); tableGenerator.AddColumn(eventNameColumn); var eventIdColumn = new DataColumn <uint>( eventIdColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Id)); tableGenerator.AddColumn(eventIdColumn); var cpuIdColumn = new DataColumn <uint>( cpuIdColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.CpuId)); tableGenerator.AddColumn(cpuIdColumn); var discardedEventsColumn = new DataColumn <uint>( discardedEventsColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.DiscardedEvents)); tableGenerator.AddColumn(discardedEventsColumn); var eventTimestampColumn = new DataColumn <Timestamp>( eventTimestampColumnConfig, genericEventProjection.Compose((genericEvent) => genericEvent.Timestamp)); tableGenerator.AddColumn(eventTimestampColumn); tableGenerator.AddColumn(countColumnConfig, Projection.Constant(1)); // Add the field columns, with column names depending on the given event for (int index = 0; index < maximumFieldCount; index++) { var colIndex = index; // This seems unncessary but causes odd runtime behavior if not done this way. Compiler is confused perhaps because w/o this func will index=genericEvent.FieldNames.Count every time. index is passed as ref but colIndex as value into func string fieldName = "Field " + (colIndex + 1); var genericEventFieldNameProjection = genericEventProjection.Compose((genericEvent) => colIndex < genericEvent.FieldNames.Count ? genericEvent.FieldNames[colIndex] : string.Empty); // generate a column configuration var fieldColumnConfiguration = new ColumnConfiguration( new ColumnMetadata(Common.GenerateGuidFromName(fieldName), fieldName, genericEventFieldNameProjection, fieldName), new UIHints { IsVisible = true, Width = 80, TextAlignment = TextAlignment.Left, }); var genericEventFieldAsStringProjection = genericEventProjection.Compose((genericEvent) => colIndex < genericEvent.FieldNames.Count ? genericEvent.FieldValues[colIndex] : string.Empty); tableGenerator.AddColumn(fieldColumnConfiguration, genericEventFieldAsStringProjection); } }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoCpuSchedEvent> >( new DataOutputPath(PerfettoPluginConstants.CpuSchedEventCookerPath, nameof(PerfettoCpuSchedEventCooker.CpuSchedEvents))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var baseProjection = Projection.Index(events); var startProjection = baseProjection.Compose(x => x.StartTimestamp); var endProjection = baseProjection.Compose(x => x.EndTimestamp); tableGenerator.AddColumn(CpuColumn, baseProjection.Compose(x => x.Cpu)); tableGenerator.AddColumn(ProcessNameColumn, baseProjection.Compose(x => x.ProcessName)); tableGenerator.AddColumn(ThreadNameColumn, baseProjection.Compose(x => x.ThreadName)); tableGenerator.AddColumn(DurationColumn, baseProjection.Compose(x => x.Duration)); tableGenerator.AddColumn(EndStateColumn, baseProjection.Compose(x => x.EndState)); tableGenerator.AddColumn(PriorityColumn, baseProjection.Compose(x => x.Priority)); tableGenerator.AddColumn(StartTimestampColumn, startProjection); tableGenerator.AddColumn(EndTimestampColumn, endProjection); tableGenerator.AddColumn(WakeEventFoundColumn, baseProjection.Compose(x => x.WakeEvent != null)); tableGenerator.AddColumn(WakerProcessNameColumn, baseProjection.Compose(x => x.WakeEvent?.WakerProcessName ?? String.Empty)); tableGenerator.AddColumn(WakerThreadNameColumn, baseProjection.Compose(x => x.WakeEvent?.WakerThreadName ?? String.Empty)); tableGenerator.AddColumn(WakerTidColumn, baseProjection.Compose(x => x.WakeEvent?.WakerTid ?? -1)); tableGenerator.AddColumn(WakerPriorityColumn, baseProjection.Compose(x => x.WakeEvent?.Priority ?? -1)); tableGenerator.AddColumn(WakerCpuColumn, baseProjection.Compose(x => x.WakeEvent != null ? (int)x.WakeEvent.Cpu : -1)); tableGenerator.AddColumn(WakeTimestampColumn, baseProjection.Compose(x => x.WakeEvent?.Timestamp ?? Timestamp.MinValue)); tableGenerator.AddColumn(SchedulingLatencyColumn, baseProjection.Compose(x => x.SchedulingLatency)); tableGenerator.AddColumn(WaitDurationColumn, baseProjection.Compose(x => x.WaitDuration)); tableGenerator.AddColumn(PreviousEndStateColumn, baseProjection.Compose(x => x.PreviousSchedulingEvent?.EndState ?? String.Empty)); tableGenerator.AddColumn(PreviousPriorityColumn, baseProjection.Compose(x => x.PreviousSchedulingEvent?.Priority ?? -1)); tableGenerator.AddColumn(PreviousCpuColumn, baseProjection.Compose(x => x.PreviousSchedulingEvent != null ? (int)x.PreviousSchedulingEvent.Cpu : -1)); // Create projections that are used for calculating CPU usage% var startProjectionClippedToViewport = Projection.ClipTimeToVisibleDomain.Create(startProjection); var endProjectionClippedToViewport = Projection.ClipTimeToVisibleDomain.Create(endProjection); IProjection <int, TimestampDelta> cpuUsageInViewportColumn = Projection.Select( endProjectionClippedToViewport, startProjectionClippedToViewport, new ReduceTimeSinceLastDiff()); var percentCpuUsageColumn = Projection.VisibleDomainRelativePercent.Create(cpuUsageInViewportColumn); tableGenerator.AddColumn(PercentCpuUsageColumn, percentCpuUsageColumn); // We want to exclude the idle thread ('swapper' on Android/Linux) from the display because it messes up CPU usage and clutters // the scheduler view const string swapperIdleFilter = "[Thread]:=\"swapper (0)\""; var cpuSchedConfig = new TableConfiguration("CPU Scheduling") { Columns = new[] { CpuColumn, ProcessNameColumn, ThreadNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on DurationColumn, EndStateColumn, PriorityColumn, WakeEventFoundColumn, WakerProcessNameColumn, WakerThreadNameColumn, WakerTidColumn, WakerCpuColumn, WakeTimestampColumn, WaitDurationColumn, SchedulingLatencyColumn, TableConfiguration.GraphColumn, // Columns after this get graphed StartTimestampColumn, EndTimestampColumn }, InitialFilterShouldKeep = false, // This means we're not keeping what the filter matches InitialFilterQuery = swapperIdleFilter }; cpuSchedConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); cpuSchedConfig.AddColumnRole(ColumnRole.EndTime, EndTimestampColumn.Metadata.Guid); cpuSchedConfig.AddColumnRole(ColumnRole.Duration, DurationColumn.Metadata.Guid); var cpuWakeConfig = new TableConfiguration("CPU Scheduling, Wake Events") { Columns = new[] { WakeEventFoundColumn, WakerProcessNameColumn, WakerThreadNameColumn, WakerTidColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on ProcessNameColumn, ThreadNameColumn, CpuColumn, WakeTimestampColumn, DurationColumn, StartTimestampColumn, EndTimestampColumn, EndStateColumn, PriorityColumn, PreviousEndStateColumn, PreviousPriorityColumn, PreviousCpuColumn, WakerCpuColumn, WaitDurationColumn, SchedulingLatencyColumn, TableConfiguration.GraphColumn, // Columns after this get graphed WakeTimestampColumn }, InitialFilterShouldKeep = false, // This means we're not keeping what the filter matches InitialFilterQuery = swapperIdleFilter }; cpuWakeConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); cpuWakeConfig.AddColumnRole(ColumnRole.EndTime, EndTimestampColumn.Metadata.Guid); cpuWakeConfig.AddColumnRole(ColumnRole.Duration, DurationColumn.Metadata.Guid); var perCpuUsageConfig = new TableConfiguration("Utilization by CPU") { Columns = new[] { CpuColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on ProcessNameColumn, ThreadNameColumn, DurationColumn, StartTimestampColumn, EndTimestampColumn, EndStateColumn, PriorityColumn, WakeEventFoundColumn, WakerProcessNameColumn, WakerThreadNameColumn, WakerTidColumn, WakerCpuColumn, WakeTimestampColumn, WaitDurationColumn, SchedulingLatencyColumn, TableConfiguration.GraphColumn, // Columns after this get graphed PercentCpuUsageColumn }, InitialFilterShouldKeep = false, // This means we're not keeping what the filter matches InitialFilterQuery = swapperIdleFilter }; perCpuUsageConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); perCpuUsageConfig.AddColumnRole(ColumnRole.EndTime, EndTimestampColumn.Metadata.Guid); perCpuUsageConfig.AddColumnRole(ColumnRole.Duration, DurationColumn.Metadata.Guid); var perProcessUsageConfig = new TableConfiguration("Utilization by Process, Thread") { Columns = new[] { ProcessNameColumn, ThreadNameColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on CpuColumn, DurationColumn, StartTimestampColumn, EndTimestampColumn, EndStateColumn, PriorityColumn, TableConfiguration.GraphColumn, // Columns after this get graphed PercentCpuUsageColumn }, InitialFilterShouldKeep = false, // This means we're not keeping what the filter matches InitialFilterQuery = swapperIdleFilter }; perProcessUsageConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); perProcessUsageConfig.AddColumnRole(ColumnRole.EndTime, EndTimestampColumn.Metadata.Guid); perProcessUsageConfig.AddColumnRole(ColumnRole.Duration, DurationColumn.Metadata.Guid); tableBuilder .AddTableConfiguration(cpuSchedConfig) .AddTableConfiguration(perCpuUsageConfig) .AddTableConfiguration(perProcessUsageConfig) .AddTableConfiguration(cpuWakeConfig) .SetDefaultTableConfiguration(perCpuUsageConfig); }
public static void BuildTable(ITableBuilder tableBuilder, IDataExtensionRetrieval tableData) { // Get data from the cooker var events = tableData.QueryOutput <ProcessedEventData <PerfettoCpuCountersEvent> >( new DataOutputPath(PerfettoPluginConstants.CpuCountersEventCookerPath, nameof(PerfettoCpuCountersEventCooker.CpuCountersEvents))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var baseProjection = Projection.Index(events); tableGenerator.AddColumn(CpuNumColumn, baseProjection.Compose(x => x.CpuNum)); tableGenerator.AddColumn(StartTimestampColumn, baseProjection.Compose(x => x.StartTimestamp)); tableGenerator.AddColumn(DurationColumn, baseProjection.Compose(x => x.Duration)); tableGenerator.AddColumn(UserPercentColumn, baseProjection.Compose(x => x.UserPercent)); tableGenerator.AddColumn(UserNicePercentColumn, baseProjection.Compose(x => x.UserNicePercent)); tableGenerator.AddColumn(SystemModePercentColumn, baseProjection.Compose(x => x.SystemModePercent)); tableGenerator.AddColumn(IdlePercentColumn, baseProjection.Compose(x => x.IdlePercent)); tableGenerator.AddColumn(IoWaitPercentColumn, baseProjection.Compose(x => x.IoWaitPercent)); tableGenerator.AddColumn(IrqPercentColumn, baseProjection.Compose(x => x.IrqPercent)); tableGenerator.AddColumn(SoftIrqPercentColumn, baseProjection.Compose(x => x.SoftIrqPercent)); tableGenerator.AddColumn(TotalCpuUsagePercentColumn, baseProjection.Compose(x => x.CpuPercent)); tableGenerator.AddColumn(CountColumn, Projection.Constant <int>(1)); // Only display the total CPU usage column var cpuUsageConfig = new TableConfiguration("CPU Usage %") { Columns = new[] { CpuNumColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on CountColumn, StartTimestampColumn, DurationColumn, UserPercentColumn, UserNicePercentColumn, SystemModePercentColumn, IdlePercentColumn, IoWaitPercentColumn, IrqPercentColumn, SoftIrqPercentColumn, TableConfiguration.GraphColumn, // Columns after this get graphed TotalCpuUsagePercentColumn }, ChartType = ChartType.Line }; cpuUsageConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); cpuUsageConfig.AddColumnRole(ColumnRole.ResourceId, CpuNumColumn); cpuUsageConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); // Display all CPU counter columns var allCountersConfig = new TableConfiguration("CPU Counters - All") { Columns = new[] { CpuNumColumn, TableConfiguration.PivotColumn, // Columns before this get pivotted on CountColumn, StartTimestampColumn, DurationColumn, TotalCpuUsagePercentColumn, IdlePercentColumn, TableConfiguration.GraphColumn, // Columns after this get graphed UserPercentColumn, UserNicePercentColumn, SystemModePercentColumn, IoWaitPercentColumn, IrqPercentColumn, SoftIrqPercentColumn, }, ChartType = ChartType.Line }; allCountersConfig.AddColumnRole(ColumnRole.StartTime, StartTimestampColumn.Metadata.Guid); allCountersConfig.AddColumnRole(ColumnRole.ResourceId, CpuNumColumn); allCountersConfig.AddColumnRole(ColumnRole.Duration, DurationColumn); tableBuilder.AddTableConfiguration(cpuUsageConfig) .AddTableConfiguration(allCountersConfig) .SetDefaultTableConfiguration(cpuUsageConfig); }