Beispiel #1
0
        private unsafe void WriteToAllListeners(string eventName, ref EventDescriptor eventDescriptor, EventTags tags, Guid *pActivityId, EventPayload payload)
        {
            EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);

            eventCallbackArgs.EventName  = eventName;
            eventCallbackArgs.m_level    = (EventLevel)eventDescriptor.Level;
            eventCallbackArgs.m_keywords = (EventKeywords)eventDescriptor.Keywords;
            eventCallbackArgs.m_opcode   = (EventOpcode)eventDescriptor.Opcode;
            eventCallbackArgs.m_tags     = tags;

            // Self described events do not have an id attached. We mark it internally with -1.
            eventCallbackArgs.EventId = -1;
            if (pActivityId != null)
            {
                eventCallbackArgs.RelatedActivityId = *pActivityId;
            }

            if (payload != null)
            {
                eventCallbackArgs.Payload      = new ReadOnlyCollection <object>((IList <object>)payload.Values);
                eventCallbackArgs.PayloadNames = new ReadOnlyCollection <string>((IList <string>)payload.Keys);
            }

            DispatchToAllListeners(-1, pActivityId, eventCallbackArgs);
        }
        private NameInfo UpdateDescriptor(
            string name,
            TraceLoggingEventTypes eventInfo,
            ref EventSourceOptions options,
            out EventDescriptor descriptor)
        {
            NameInfo nameInfo = null;
            int      identity = 0;
            byte     level    = (options.valuesSet & EventSourceOptions.levelSet) != 0
                ? options.level
                : eventInfo.level;
            byte opcode = (options.valuesSet & EventSourceOptions.opcodeSet) != 0
                ? options.opcode
                : eventInfo.opcode;
            EventTags tags = (options.valuesSet & EventSourceOptions.tagsSet) != 0
                ? options.tags
                : eventInfo.Tags;
            EventKeywords keywords = (options.valuesSet & EventSourceOptions.keywordsSet) != 0
                ? options.keywords
                : eventInfo.keywords;

            if (this.IsEnabled((EventLevel)level, keywords))
            {
                nameInfo = eventInfo.GetNameInfo(name ?? eventInfo.Name, tags);
                identity = nameInfo.identity;
            }

            descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);
            return(nameInfo);
        }
        /// <summary>
        /// Writes an extended event, where the values of the event are the
        /// combined properties of any number of values. This method is
        /// intended for use in advanced logging scenarios that support a
        /// dynamic set of event context providers.
        /// Attention: This API does not check whether the event is enabled or not.
        /// Please use WriteMultiMerge to avoid spending CPU cycles for events that are
        /// not enabled.
        /// </summary>
        /// <param name="eventName">
        /// The name for the event. If null, the name from eventTypes is used.
        /// (Note that providing the event name via the name parameter is slightly
        /// less efficient than using the name from eventTypes.)
        /// </param>
        /// <param name="options">
        /// Optional overrides for the event, such as the level, keyword, opcode,
        /// activityId, and relatedActivityId. Any settings not specified by options
        /// are obtained from eventTypes.
        /// </param>
        /// <param name="eventTypes">
        /// Information about the event and the types of the values in the event.
        /// Must not be null. Note that the eventTypes object should be created once and
        /// saved. It should not be recreated for each event.
        /// </param>
        /// <param name="activityID">
        /// A pointer to the activity ID GUID to log
        /// </param>
        /// <param name="childActivityID">
        /// A pointer to the child activity ID to log (can be null)
        /// </param>
        /// <param name="values">
        /// The values to include in the event. Must not be null. The number and types of
        /// the values must match the number and types of the fields described by the
        /// eventTypes parameter.
        /// </param>
        private unsafe void WriteMultiMergeInner(
            string eventName,
            ref EventSourceOptions options,
            TraceLoggingEventTypes eventTypes,
            Guid *activityID,
            Guid *childActivityID,
            params object[] values)
        {
#if FEATURE_MANAGED_ETW
            int  identity = 0;
            byte level    = (options.valuesSet & EventSourceOptions.levelSet) != 0
                ? options.level
                : eventTypes.level;
            byte opcode = (options.valuesSet & EventSourceOptions.opcodeSet) != 0
                ? options.opcode
                : eventTypes.opcode;
            EventTags tags = (options.valuesSet & EventSourceOptions.tagsSet) != 0
                ? options.tags
                : eventTypes.Tags;
            EventKeywords keywords = (options.valuesSet & EventSourceOptions.keywordsSet) != 0
                ? options.keywords
                : eventTypes.keywords;

            var nameInfo = eventTypes.GetNameInfo(eventName ?? eventTypes.Name, tags);
            if (nameInfo == null)
            {
                return;
            }
            identity = nameInfo.identity;
            EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);

#if FEATURE_PERFTRACING
            IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleMap, descriptor, eventTypes);
            Debug.Assert(eventHandle != IntPtr.Zero);
#else
            IntPtr eventHandle = IntPtr.Zero;
#endif

            var pinCount    = eventTypes.pinCount;
            var scratch     = stackalloc byte[eventTypes.scratchSize];
            var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
            for (int i = 0; i < eventTypes.dataCount + 3; i++)
            {
                descriptors[i] = default;
            }

            var pins = stackalloc GCHandle[pinCount];
            for (int i = 0; i < pinCount; i++)
                pins[i] = default;

            fixed(byte *
                  pMetadata0 = this.providerMetadata,
                  pMetadata1 = nameInfo.nameMetadata,
                  pMetadata2 = eventTypes.typeMetadata)
            {
                descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2);
                descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1);
                descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1);

#if (!ES_BUILD_PCL && !ES_BUILD_PN)
                System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
#endif
                try
                {
                    DataCollector.ThreadInstance.Enable(
                        scratch,
                        eventTypes.scratchSize,
                        descriptors + 3,
                        eventTypes.dataCount,
                        pins,
                        pinCount);

                    for (int i = 0; i < eventTypes.typeInfos.Length; i++)
                    {
                        var info = eventTypes.typeInfos[i];
                        info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(values[i]));
                    }

                    this.WriteEventRaw(
                        eventName,
                        ref descriptor,
                        eventHandle,
                        activityID,
                        childActivityID,
                        (int)(DataCollector.ThreadInstance.Finish() - descriptors),
                        (IntPtr)descriptors);
                }
                finally
                {
                    this.WriteCleanup(pins, pinCount);
                }
            }
#endif // FEATURE_MANAGED_ETW
        }
Beispiel #4
0
        internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
        {
            int status = 0;

            if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
            {
                int argCount = 0;
                unsafe
                {
                    argCount = eventPayload.Length;

                    if (argCount > s_etwMaxNumberArguments)
                    {
                        s_returnCode = WriteEventErrorCode.TooManyArgs;
                        return false;
                    }

                    uint totalEventSize = 0;
                    int index;
                    int refObjIndex = 0;
                    List<int> refObjPosition = new List<int>(s_etwAPIMaxRefObjCount);
                    List<object> dataRefObj = new List<object>(s_etwAPIMaxRefObjCount);
                    EventData* userData = stackalloc EventData[2 * argCount];
                    EventData* userDataPtr = (EventData*)userData;
                    byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * 2 * argCount]; // Assume 16 chars for non-string argument
                    byte* currentBuffer = dataBuffer;

                    //
                    // The loop below goes through all the arguments and fills in the data 
                    // descriptors. For strings save the location in the dataString array.
                    // Calculates the total size of the event by adding the data descriptor
                    // size value set in EncodeObject method.
                    //
                    bool hasNonStringRefArgs = false;
                    for (index = 0; index < eventPayload.Length; index++)
                    {
                        if (eventPayload[index] != null)
                        {
                            object supportedRefObj;
                            supportedRefObj = EncodeObject(ref eventPayload[index], ref userDataPtr, ref currentBuffer, ref totalEventSize);

                            if (supportedRefObj != null)
                            {
                                // EncodeObject advanced userDataPtr to the next empty slot
                                int idx = (int)(userDataPtr - userData - 1);
                                if (!(supportedRefObj is string))
                                {
                                    if (eventPayload.Length + idx + 1 - index > s_etwMaxNumberArguments)
                                    {
                                        s_returnCode = WriteEventErrorCode.TooManyArgs;
                                        return false;
                                    }
                                    hasNonStringRefArgs = true;
                                }
                                dataRefObj.Add(supportedRefObj);
                                refObjPosition.Add(idx);
                                refObjIndex++;
                            }
                        }
                        else
                        {
                            s_returnCode = WriteEventErrorCode.NullInput;
                            return false;
                        }
                    }

                    // update argCount based on actual number of arguments written to 'userData'
                    argCount = (int)(userDataPtr - userData);

                    if (totalEventSize > s_traceEventMaximumSize)
                    {
                        s_returnCode = WriteEventErrorCode.EventTooBig;
                        return false;
                    }

                    // the optimized path (using "fixed" instead of allocating pinned GCHandles
                    if (!hasNonStringRefArgs && (refObjIndex < s_etwAPIMaxRefObjCount))
                    {
                        // Fast path: at most 8 string arguments

                        // ensure we have at least s_etwAPIMaxStringCount in dataString, so that
                        // the "fixed" statement below works
                        while (refObjIndex < s_etwAPIMaxRefObjCount)
                        {
                            dataRefObj.Add(null);
                            ++refObjIndex;
                        }

                        //
                        // now fix any string arguments and set the pointer on the data descriptor 
                        //
                        fixed (char* v0 = (string)dataRefObj[0], v1 = (string)dataRefObj[1], v2 = (string)dataRefObj[2], v3 = (string)dataRefObj[3],
                                v4 = (string)dataRefObj[4], v5 = (string)dataRefObj[5], v6 = (string)dataRefObj[6], v7 = (string)dataRefObj[7])
                        {
                            userDataPtr = (EventData*)userData;
                            if (dataRefObj[0] != null)
                            {
                                userDataPtr[refObjPosition[0]].Ptr = (ulong)v0;
                            }
                            if (dataRefObj[1] != null)
                            {
                                userDataPtr[refObjPosition[1]].Ptr = (ulong)v1;
                            }
                            if (dataRefObj[2] != null)
                            {
                                userDataPtr[refObjPosition[2]].Ptr = (ulong)v2;
                            }
                            if (dataRefObj[3] != null)
                            {
                                userDataPtr[refObjPosition[3]].Ptr = (ulong)v3;
                            }
                            if (dataRefObj[4] != null)
                            {
                                userDataPtr[refObjPosition[4]].Ptr = (ulong)v4;
                            }
                            if (dataRefObj[5] != null)
                            {
                                userDataPtr[refObjPosition[5]].Ptr = (ulong)v5;
                            }
                            if (dataRefObj[6] != null)
                            {
                                userDataPtr[refObjPosition[6]].Ptr = (ulong)v6;
                            }
                            if (dataRefObj[7] != null)
                            {
                                userDataPtr[refObjPosition[7]].Ptr = (ulong)v7;
                            }

                            status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
                        }
                    }
                    else
                    {
                        // Slow path: use pinned handles
                        userDataPtr = (EventData*)userData;

                        GCHandle[] rgGCHandle = new GCHandle[refObjIndex];
                        for (int i = 0; i < refObjIndex; ++i)
                        {
                            // below we still use "fixed" to avoid taking dependency on the offset of the first field
                            // in the object (the way we would need to if we used GCHandle.AddrOfPinnedObject)
                            rgGCHandle[i] = GCHandle.Alloc(dataRefObj[i], GCHandleType.Pinned);
                            if (dataRefObj[i] is string)
                            {
                                fixed (char* p = (string)dataRefObj[i])
                                    userDataPtr[refObjPosition[i]].Ptr = (ulong)p;
                            }
                            else
                            {
                                fixed (byte* p = (byte[])dataRefObj[i])
                                    userDataPtr[refObjPosition[i]].Ptr = (ulong)p;
                            }
                        }

                        status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);

                        for (int i = 0; i < refObjIndex; ++i)
                        {
                            rgGCHandle[i].Free();
                        }
                    }
                }
            }

            if (status != 0)
            {
                SetLastError((int)status);
                return false;
            }

            return true;
        }
Beispiel #5
0
        internal unsafe bool WriteEventRaw(
            ref EventDescriptor eventDescriptor,
            Guid* activityID,
            Guid* relatedActivityID,
            int dataCount,
            IntPtr data)
        {
            int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
                m_regHandle,
                ref eventDescriptor,
                activityID,
                relatedActivityID,
                dataCount,
                (EventData*)data);

            if (status != 0)
            {
                SetLastError(status);
                return false;
            }
            return true;
        }
Beispiel #6
0
        internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
        {
            if (childActivityID != null)
            {
                // activity transfers are supported only for events that specify the Send or Receive opcode
                Contract.Assert((EventOpcode)eventDescriptor.Opcode == EventOpcode.Send ||
                                (EventOpcode)eventDescriptor.Opcode == EventOpcode.Receive ||
                                (EventOpcode)eventDescriptor.Opcode == EventOpcode.Start ||
                                (EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
            }
            
            int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);

            if (status != 0)
            {
                SetLastError(status);
                return false;
            }
            return true;
        }