public PerfGenericEvent(PerfEvent data, PerfContext context)
        {
            this.EventName = data.Name;
            this.Timestamp = data.Timestamp;
            this.Id        = data.Id;
            this.CpuId     = context.CurrentCpu;

            if (!(data.Payload is CtfStructValue payload))
            {
                throw new CtfPlaybackException("Event data is corrupt.");
            }

            // As this is being written, all columns are of type 'T', so all rows are the same. For generic events,
            // where columns have different types for different rows, this means everything becomes a string.
            //
            // We don't want to keep around each event in memory, that would use too much memory. So for now convert
            // each field value to a string, which would happen anyways.
            //
            // If the consumer is smarter in the future and allows for multi-type columns, we can re-evaluate this
            // approach. We could probably generate a type from each event descriptor, and convert to that type.
            //

            this.FieldCount = payload.Fields.Count;
            this.events     = new List <PerfGenericEventField>(this.FieldCount);
            foreach (var field in payload.Fields)
            {
                this.events.Add(new PerfGenericEventField(field.FieldName, field.GetValueAsString()));
            }
        }
Exemplo n.º 2
0
        public CpuClockEvent(PerfEvent data, PerfContext context, SortedList <ulong, KernelSymbol> kernelSymbols)
        {
            this.Timestamp = data.Timestamp;
            this.Cpu       = context.CurrentCpu;
            if (data.Payload != null)
            {
                if (data.Payload.FieldsByName.ContainsKey("perf_ip"))
                {
                    Ip = data.Payload.ReadFieldAsUInt64("perf_ip");

                    if (kernelSymbols.Count > 0)
                    {
                        Ip_Symbol = FindSymbolForIp(Ip, kernelSymbols);
                    }
                }
                if (data.Payload.FieldsByName.ContainsKey("perf_tid"))
                {
                    Tid = data.Payload.ReadFieldAsUInt64("perf_tid");
                }
                if (data.Payload.FieldsByName.ContainsKey("perf_pid"))
                {
                    Pid = data.Payload.ReadFieldAsUInt64("perf_pid");
                }
                if (data.Payload.FieldsByName.ContainsKey("perf_id"))
                {
                    Id = data.Payload.ReadFieldAsUInt64("perf_id");
                }
                if (data.Payload.FieldsByName.ContainsKey("perf_period"))
                {
                    Perf_Period = data.Payload.ReadFieldAsUInt64("perf_period");
                }
                if (data.Payload.FieldsByName.ContainsKey("perf_callchain_size"))
                {
                    Perf_Callchain_Size = data.Payload.ReadFieldAsUInt64("perf_callchain_size");
                }
                if (Perf_Callchain_Size > 0 && data.Payload.FieldsByName.ContainsKey("perf_callchain") && Perf_Callchain_Size < Int32.MaxValue)
                {
                    CallStack = new string[Perf_Callchain_Size + 1];
                    var perf_Callchain = data.Payload.ReadFieldAsArray("perf_callchain").ReadAsUInt64Array();

                    CallStack[0] = "[Root]";
                    for (ulong stackIdx = 1; stackIdx <= Perf_Callchain_Size; stackIdx++)
                    {
                        var sym = FindSymbolForIp(perf_Callchain[Perf_Callchain_Size - stackIdx], kernelSymbols);
                        CallStack[stackIdx] = sym != null ? sym.Name : null;
                    }
                }
            }
        }
        public void ProcessEvent(ICtfEvent ctfEvent, ICtfPacket eventPacket, ICtfTraceInput traceInput, ICtfInputStream ctfEventStream)
        {
            var eventDescriptor = ctfEvent.EventDescriptor as EventDescriptor;

            Debug.Assert(eventDescriptor != null);
            if (eventDescriptor == null)
            {
                throw new PerfPlaybackException("EventDescriptor is not an Perf descriptor.");
            }

            if (!this.streamToCpu.TryGetValue(ctfEventStream, out var cpuId))
            {
                var    cpuIndex = ctfEventStream.StreamSource.LastIndexOf('_');
                string cpu      = ctfEventStream.StreamSource.Substring(cpuIndex + 1);
                if (!uint.TryParse(cpu, out cpuId))
                {
                    Debug.Assert(false, "Unable to parse cpu from Perf stream channel");
                    cpuId = uint.MaxValue;
                }

                this.streamToCpu.Add(ctfEventStream, cpuId);
            }

            if (!this.traceContexts.TryGetValue(traceInput, out var traceContext))
            {
                traceContext = new TraceContext(this.metadataCustomization.PerfMetadata);
                this.traceContexts.Add(traceInput, traceContext);
            }

            var callbackEvent = new PerfEvent(ctfEvent);

            var callbackContext = new PerfContext(this.metadataCustomization, ctfEventStream, traceContext)
            {
                // todo: when supporting multiple traces, this timestamp needs to become relative to the earliest timestamp all traces
                // todo: when supporting multiple traces, this one event number needs to become cumulative across traces, and one specific to the current trace
                CurrentCpu                    = cpuId,
                Timestamp                     = (long)ctfEvent.Timestamp.NanosecondsFromClockBase,/// - this.baseTimestamp,
                CurrentEventNumber            = this.eventNumber,
                CurrentEventNumberWithinTrace = this.eventNumber,
            };

            foreach (var callback in this.eventCallbacks)
            {
                callback(callbackEvent, callbackContext);
            }

            ++this.eventNumber;
        }
Exemplo n.º 4
0
        public override DataProcessingResult CookDataElement(
            PerfEvent data,
            PerfContext context,
            CancellationToken cancellationToken)
        {
            try
            {
                Events.AddEvent(new PerfGenericEvent(data, context));

                this.MaximumEventFieldCount =
                    Math.Max(data.Payload.Fields.Count, this.MaximumEventFieldCount);
            }
            catch (CtfPlaybackException e)
            {
                Console.Error.WriteLine($"Error consuming event: {e.Message}");
                return(DataProcessingResult.CorruptData);
            }

            return(DataProcessingResult.Processed);
        }
        public override DataProcessingResult CookDataElement(PerfEvent data, PerfContext context, CancellationToken cancellationToken)
        {
            lock (symProcessLock)
            {
                if (!attemptedProcessSymbols)
                {
                    try
                    {
                        // TODO: This is hard-coded for now. We don't seem to have a good way to know/infer the trace path or choose this in the UI. CTF SDK change needed?

                        var kallsymsFile = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "kallsyms");
                        if (File.Exists(kallsymsFile))
                        {
                            using (StreamReader sr = new StreamReader(kallsymsFile))
                            {
                                string line;
                                while ((line = sr.ReadLine()) != null)
                                {
                                    var ks = new KernelSymbol(line);

                                    if (KernelSymbols.ContainsKey(ks.Address))
                                    {
                                        Console.Out.WriteLine($"Unable to add {line}. There is already an entry this address");
                                    }
                                    else
                                    {
                                        KernelSymbols.Add(ks.Address, ks);
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"Exception processing symbols: {e.Message}");
                    }
                    finally
                    {
                        attemptedProcessSymbols = true;
                    }
                }
            }

            try
            {
                if (data.Name == "cpu-clock")
                {
                    CpuClockEvents.Add(new CpuClockEvent(data, context, KernelSymbols));
                    return(DataProcessingResult.Processed);
                }
                else
                {
                    return(DataProcessingResult.Ignored);
                }
            }
            catch (CtfPlaybackException e)
            {
                Console.Error.WriteLine(e);
                return(DataProcessingResult.CorruptData);
            }
        }