Exemple #1
0
        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);
        }
Exemple #3
0
        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));
        }
Exemple #5
0
        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);
                }
            }
        }
Exemple #7
0
        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);
        }
Exemple #9
0
        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);
        }
Exemple #10
0
        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);
        }
Exemple #14
0
        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);
        }
Exemple #19
0
        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);
        }