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) { // 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) { int maximumFieldCount = tableData.QueryOutput <int>( DataOutputPath.ForSource(PerfConstants.SourceId, PerfGenericEventDataCooker.Identifier, nameof(PerfGenericEventDataCooker.MaximumEventFieldCount))); var events = tableData.QueryOutput <ProcessedEventData <PerfGenericEvent> >( DataOutputPath.ForSource(PerfConstants.SourceId, PerfGenericEventDataCooker.Identifier, nameof(PerfGenericEventDataCooker.Events))); var tableGenerator = tableBuilder.SetRowCount((int)events.Count); var genericEventProjection = new EventProjection <PerfGenericEvent>(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 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 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(Common.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); } }