/// <summary> /// Give meta-data for an event, passed as a EventPipeEventMetaDataHeader and readerForParameters /// which is a StreamReader that points at serialized parameter information, decode the meta-data /// and record a template associated with this source. The readerForParameters is advanced beyond /// the event parameters information. /// </summary> internal void OnNewEventPipeEventDefinition(EventPipeEventMetaDataHeader eventMetaDataHeader, PinnedStreamReader readerForParameters) { // Convert the EventPipe data into a DynamicTraceEventData, which is how TraceEvent does dynamic event parsing. DynamicTraceEventData template = ReadEventParametersAndBuildTemplate(eventMetaDataHeader, readerForParameters); _metadataTemplates[template] = template; }
/// <summary> /// Give meta-data for an event, passed as a EventPipeEventMetaDataHeader and readerForParameters /// which is a StreamReader that points at serialized parameter information, decode the meta-data /// and register the meta-data with the TraceEventParser infrastruture. The readerForParameters /// is advanced beyond the event parameters information. /// </summary> internal void OnNewEventPipeEventDefinition(EventPipeEventMetaDataHeader eventMetaDataHeader, PinnedStreamReader readerForParameters) { // Convert the EventPipe data into a DynamicTraceEventData, which is how TraceEvent does dynamic event parsing. DynamicTraceEventData template = ReadEventParametersAndBuildTemplate(eventMetaDataHeader, readerForParameters); OnNewEventDefintion(template, mayHaveExistedBefore: true); }
internal TraceEventNativeMethods.EVENT_RECORD *ReadEvent(PinnedStreamReader reader) { EventPipeEventHeader *eventData = (EventPipeEventHeader *)reader.GetPointer(EventPipeEventHeader.HeaderSize); eventData = (EventPipeEventHeader *)reader.GetPointer(eventData->TotalEventSize); // now we now the real size and get read entire event // Basic sanity checks. Are the timestamps and sizes sane. Debug.Assert(sessionEndTimeQPC <= eventData->TimeStamp); Debug.Assert(sessionEndTimeQPC == 0 || eventData->TimeStamp - sessionEndTimeQPC < _QPCFreq * 24 * 3600); Debug.Assert(0 <= eventData->PayloadSize && eventData->PayloadSize <= eventData->TotalEventSize); Debug.Assert(0 < eventData->TotalEventSize && eventData->TotalEventSize < 0x20000); // TODO really should be 64K but BulkSurvivingObjectRanges needs fixing. Debug.Assert(_fileFormatVersionNumber < 3 || ((int)EventPipeEventHeader.PayloadBytes(eventData) % 4 == 0 && eventData->TotalEventSize % 4 == 0)); // ensure 4 byte alignment StreamLabel eventDataEnd = reader.Current.Add(eventData->TotalEventSize); Debug.Assert(0 <= EventPipeEventHeader.StackBytesSize(eventData) && EventPipeEventHeader.StackBytesSize(eventData) <= eventData->TotalEventSize); TraceEventNativeMethods.EVENT_RECORD *ret = null; if (eventData->IsMetadata()) { int totalEventSize = eventData->TotalEventSize; int payloadSize = eventData->PayloadSize; // Note that this skip invalidates the eventData pointer, so it is important to pull any fields out we need first. reader.Skip(EventPipeEventHeader.HeaderSize); StreamLabel metaDataEnd = reader.Current.Add(payloadSize); // Read in the header (The header does not include payload parameter information) var metaDataHeader = new EventPipeEventMetaDataHeader(reader, payloadSize, _fileFormatVersionNumber, PointerSize, _processId); _eventMetadataDictionary.Add(metaDataHeader.MetaDataId, metaDataHeader); // Tell the parser about this new event _eventParser.OnNewEventPipeEventDefinition(metaDataHeader, reader); Debug.Assert(reader.Current == metaDataEnd); // We should have read all the meta-data. int stackBytes = reader.ReadInt32(); Debug.Assert(stackBytes == 0, "Meta-data events should always have a empty stack"); } else { if (_eventMetadataDictionary.TryGetValue(eventData->MetaDataId, out var metaData)) { ret = metaData.GetEventRecordForEventData(eventData); } else { Debug.Assert(false, "Warning can't find metaData for ID " + eventData->MetaDataId.ToString("x")); } } reader.Goto(eventDataEnd); return(ret); }
/// <summary> /// Given the EventPipe metaData header and a stream pointing at the serialized meta-data for the parameters for the /// event, create a new DynamicTraceEventData that knows how to parse that event. /// ReaderForParameters.Current is advanced past the parameter information. /// </summary> private DynamicTraceEventData ReadEventParametersAndBuildTemplate(EventPipeEventMetaDataHeader eventMetaDataHeader, PinnedStreamReader readerForParameters) { int opcode; string opcodeName; GetOpcodeFromEventName(eventMetaDataHeader.EventName, out opcode, out opcodeName); DynamicTraceEventData.PayloadFetchClassInfo classInfo = null; DynamicTraceEventData template = new DynamicTraceEventData(null, eventMetaDataHeader.EventId, 0, eventMetaDataHeader.EventName, Guid.Empty, opcode, opcodeName, eventMetaDataHeader.ProviderId, eventMetaDataHeader.ProviderName); // If the metadata contains no parameter metadata, don't attempt to read it. if (!eventMetaDataHeader.ContainsParameterMetadata) { template.payloadNames = new string[0]; template.payloadFetches = new DynamicTraceEventData.PayloadFetch[0]; return(template); } // Read the count of event payload fields. int fieldCount = readerForParameters.ReadInt32(); Debug.Assert(0 <= fieldCount && fieldCount < 0x4000); if (fieldCount > 0) { // Recursively parse the metadata, building up a list of payload names and payload field fetch objects. classInfo = ParseFields(readerForParameters, fieldCount); } else { classInfo = new DynamicTraceEventData.PayloadFetchClassInfo() { FieldNames = new string[0], FieldFetches = new DynamicTraceEventData.PayloadFetch[0] }; } template.payloadNames = classInfo.FieldNames; template.payloadFetches = classInfo.FieldFetches; return(template); }