protected override void OnEventWritten(EventWrittenEventArgs eventData) { SendManifestIfNecessary(eventData.EventSource); var relogger = m_relogger; var newEvent = relogger.m_relogger.CreateEventInstance(relogger.m_traceHandleForFirstStream, 0); // The interop assembly has its own def of EventDescriptor, but they are identical, so we use unsafe casting to // bridge the gap. _EVENT_DESCRIPTOR descr = new _EVENT_DESCRIPTOR(); descr.Id = (ushort)eventData.EventId; descr.Keyword = (ulong)eventData.Keywords; descr.Level = (byte)eventData.Level; descr.Opcode = (byte)eventData.Opcode; descr.Task = (ushort)eventData.Task; descr.Version = eventData.Version; newEvent.SetEventDescriptor(ref descr); // Set the provider to the EventSource Guid providerGuid = eventData.EventSource.Guid; newEvent.SetProviderId(ref providerGuid); // Clone the process ID, thread ID and TimeStamp _EVENT_RECORD *eventRecord = (_EVENT_RECORD *)relogger.m_curITraceEvent.GetEventRecord(); newEvent.SetThreadId(eventRecord->EventHeader.ThreadId); newEvent.SetProcessId(eventRecord->EventHeader.ProcessId); newEvent.SetTimeStamp(ref eventRecord->EventHeader.TimeStamp); // Copy over the payload. relogger.SetPayload(newEvent, eventData.Payload); relogger.m_relogger.Inject(newEvent); }
/// <summary> /// Writes an event that did not exist previously into the data stream, The context data (time, process, thread, activity, comes from 'an existing event') is given explicitly /// </summary> public unsafe void WriteEvent(Guid providerId, ref _EVENT_DESCRIPTOR eventDescriptor, DateTime timeStamp, int processId, int processorIndex, int threadID, Guid activityID, params object[] payload) { // Today we always create 64 bit events on 64 bit OSes. var newEvent = m_relogger.CreateEventInstance(m_traceHandleForFirstStream, (pointerSize == 8) ? TraceEventNativeMethods.EVENT_HEADER_FLAG_64_BIT_HEADER : TraceEventNativeMethods.EVENT_HEADER_FLAG_32_BIT_HEADER); fixed(_EVENT_DESCRIPTOR *fixedEventDescr = &eventDescriptor) { // The interop assembly has its own def of EventDescriptor, but they are identical, so we use unsafe casting to // bridge the gap. _EVENT_DESCRIPTOR *ptrDescr = (_EVENT_DESCRIPTOR *)fixedEventDescr; newEvent.SetEventDescriptor(ref *ptrDescr); newEvent.SetProviderId(ref providerId); _LARGE_INTEGER fileTimeStamp = new _LARGE_INTEGER(); fileTimeStamp.QuadPart = timeStamp.ToFileTimeUtc(); newEvent.SetTimeStamp(ref fileTimeStamp); newEvent.SetProcessId((uint)processId); newEvent.SetProcessorIndex((uint)processorIndex); newEvent.SetThreadId((uint)threadID); newEvent.SetActivityId(ref activityID); SetPayload(newEvent, payload); m_relogger.Inject(newEvent); } }
// ability to modify events you don't own, which may be useful. /// <summary> /// Writes an event that did not exist previously into the data stream, The context data (time, process, thread, activity, comes from 'an existing event') /// </summary> public unsafe void WriteEvent(Guid providerId, ref _EVENT_DESCRIPTOR eventDescriptor, TraceEvent template, params object[] payload) { if (template.eventRecord != m_curTraceEventRecord) { throw new InvalidOperationException("Currently can only write the event being processed by the callback"); } // Make a copy of the template so we can modify it var newEvent = m_curITraceEvent.Clone(); fixed(_EVENT_DESCRIPTOR *fixedEventDescr = &eventDescriptor) { // The interop assembly has its own def of EventDescriptor, but they are identical, so we use unsafe casting to // bridge the gap. _EVENT_DESCRIPTOR *ptrDescr = (_EVENT_DESCRIPTOR *)fixedEventDescr; newEvent.SetEventDescriptor(ref *ptrDescr); newEvent.SetProviderId(ref providerId); SetPayload(newEvent, payload); m_relogger.Inject(newEvent); } }
internal static extern uint EventWrite(ulong RegHandle, ref _EVENT_DESCRIPTOR EventDescriptor, uint UserDataCount, IntPtr UserData);
internal unsafe void SendManifest(byte[] rawManifest, EventSource eventSource) { ManifestEnvelope envelope = new ManifestEnvelope(); envelope.Format = ManifestEnvelope.ManifestFormats.SimpleXmlFormat; envelope.MajorVersion = 1; envelope.MinorVersion = 0; envelope.Magic = 0x5B; // An unusual number that can be checked for consistancy. int dataLeft = rawManifest.Length; envelope.TotalChunks = (ushort)((dataLeft + (ManifestEnvelope.MaxChunkSize - 1)) / ManifestEnvelope.MaxChunkSize); envelope.ChunkNumber = 0; if (m_curITraceEvent == null) { throw new InvalidOperationException("Currently can only write the event being processed by the callback"); } // Make a copy of the template so we can modify it var manifestEvent = m_relogger.CreateEventInstance(m_traceHandleForFirstStream, 0); var manifestDescr = new _EVENT_DESCRIPTOR() { Id = 0xFFFE, Task = 0xFFFE, Opcode = 0xFE, Keyword = ulong.MaxValue }; manifestEvent.SetEventDescriptor(ref manifestDescr); // Set the provider to the EventSoruce Guid providerGuid = eventSource.Guid; manifestEvent.SetProviderId(ref providerGuid); // Clone the process ID, thread ID and TimeStamp _EVENT_RECORD *eventRecord = (_EVENT_RECORD *)m_curITraceEvent.GetEventRecord(); manifestEvent.SetThreadId(eventRecord->EventHeader.ThreadId); manifestEvent.SetProcessId(eventRecord->EventHeader.ProcessId); manifestEvent.SetTimeStamp(ref eventRecord->EventHeader.TimeStamp); int bufferSize = sizeof(ManifestEnvelope) + Math.Min(ManifestEnvelope.MaxChunkSize, rawManifest.Length); byte[] buffer = new byte[bufferSize]; int manifestIdx = 0; // Where we are in the manifest. while (dataLeft > 0) { // Copy envelope into buffer byte *envelopePtr = (byte *)&envelope; int bufferIdx = 0; while (bufferIdx < sizeof(ManifestEnvelope)) { buffer[bufferIdx++] = *envelopePtr++; } // Copy chunk of manifest into buffer while (bufferIdx < buffer.Length && manifestIdx < rawManifest.Length) buffer[bufferIdx++] = rawManifest[manifestIdx++]; // write the envelope + chunk. fixed(byte *bufferPtr = buffer) { manifestEvent.SetPayload(ref *bufferPtr, (uint)bufferIdx); m_relogger.Inject(manifestEvent); } envelope.ChunkNumber++; Debug.Assert(envelope.ChunkNumber <= envelope.TotalChunks); dataLeft -= ManifestEnvelope.MaxChunkSize; } Debug.Assert(envelope.ChunkNumber == envelope.TotalChunks); }