Beispiel #1
0
        /// <summary>
        /// Froms the etw event.
        /// </summary>
        /// <param name="etwMetricData">The etw metric data.</param>
        /// <returns>The diagnostic heartbeat.</returns>
        public static unsafe IDiagnosticHeartbeat FromEtwEvent(NativeMethods.EventRecord *etwMetricData)
        {
            var heartbeat = new DiagnosticHeartbeat();

            var pointerInPayload = etwMetricData->UserData;

            heartbeat.InstanceName = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);

            var uptimeSec = *((int *)pointerInPayload);

            pointerInPayload      = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(int));
            heartbeat.UptimeInSec = uptimeSec;

            var etwEventsDropped = *((int *)pointerInPayload);

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(int));
            heartbeat.EtwEventsDroppedCount = etwEventsDropped;

            var etwEventsLost = *((int *)pointerInPayload);

            pointerInPayload             = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(int));
            heartbeat.EtwEventsLostCount = etwEventsLost;

            var aggregatedMetricsDropped = *((int *)pointerInPayload);

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(int));
            heartbeat.AggregatedMetricsDroppedCount = aggregatedMetricsDropped;

            var isNearingEtwLimit = *((byte *)pointerInPayload);

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(byte));
            heartbeat.IsNearingEtwQueueLimit = isNearingEtwLimit != 0;

            var isNearingAggregationLimit = *((byte *)pointerInPayload);

            heartbeat.IsNearingAggregationQueueLimit = isNearingAggregationLimit != 0;

            return(heartbeat);
        }
        /// <summary>
        /// Converts content of the ETW event to <see cref="LocalRawMetric"/>.
        /// </summary>
        /// <param name="etwMetricData">Object containing information about metric data sample.</param>
        /// <returns>A <see cref="LocalRawMetric"/> object representing metric sample data.</returns>
        /// <exception cref="ArgumentException">Throw when information contained in metricDataRecord is in incorrect format.</exception>
        internal static unsafe LocalRawMetric ConvertToMetricData(NativeMethods.EventRecord *etwMetricData)
        {
            try
            {
                // Read ETW event time and use as metric time
                var etwTimeUtc = DateTime.FromFileTimeUtc(etwMetricData->EventHeader.TimeStamp);

                IntPtr pointerInPayload = etwMetricData->UserData;

                // Get number of dimensions
                ushort dimensionsCount = *((ushort *)pointerInPayload);
                pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(ushort));

                // Shift 6 bytes as this space is reserved for alignment
                pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(ushort) + sizeof(uint));

                // If time was reported with metric, use it
                long timestamp = *((long *)pointerInPayload);
                pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(long));

                var metricTimeUtc = timestamp == 0 ? etwTimeUtc : DateTime.FromFileTimeUtc(timestamp);

                // Metric sample value which is either value or delta
                double doubleMetricSampleValue = 0;
                long   metricSampleValue       = 0;
                if (etwMetricData->EventHeader.Id == PlatformMetricEtwOperationCode)
                {
                    doubleMetricSampleValue = *((double *)pointerInPayload);
                }
                else
                {
                    metricSampleValue = *((long *)pointerInPayload);
                }

                pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(long));

                // Read monitoring account, metric namespace and name
                var monitoringAccount = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);
                var metricNameSpace   = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);
                var metricName        = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);

                var dimensionNames = new List <string>();
                for (int i = 0; i < dimensionsCount; ++i)
                {
                    dimensionNames.Add(EtwPayloadManipulationUtils.ReadString(ref pointerInPayload));
                }

                var dimensionValues = new List <string>();
                for (int i = 0; i < dimensionsCount; ++i)
                {
                    dimensionValues.Add(EtwPayloadManipulationUtils.ReadString(ref pointerInPayload));
                }

                var dimensions = new Dictionary <string, string>();
                for (int i = 0; i < dimensionsCount; ++i)
                {
                    dimensions[dimensionNames[i]] = dimensionValues[i];
                }

                return(new LocalRawMetric
                {
                    IsPlatformMetric =
                        etwMetricData->EventHeader.Id == PlatformMetricEtwOperationCode,
                    MetricTimeUtc = metricTimeUtc,
                    MetricLongValue = (ulong)metricSampleValue,
                    MetricDoubleValue = doubleMetricSampleValue,
                    MonitoringAccount = monitoringAccount,
                    MetricNamespace = metricNameSpace,
                    MetricName = metricName,
                    Dimensions = dimensions
                });
            }
            catch (Exception e)
            {
                Logger.Log(
                    LoggerLevel.Error,
                    LogId,
                    "ConvertToMetricData",
                    "Failed to read raw metric daat from the ETW event payload.",
                    e);

                throw;
            }
        }
        /// <summary>
        /// Converts content of the ETW event published by ME to a <see cref="LocalAggregatedMetric"/>
        /// </summary>
        /// <param name="etwMetricData">Object containing information about metric data sample.</param>
        /// <returns>A MetricData object representing a locally aggregated metric.</returns>
        internal static unsafe LocalAggregatedMetric ConvertToMetricData(NativeMethods.EventRecord *etwMetricData)
        {
            var metricData = new LocalAggregatedMetric();

            IntPtr pointerInPayload = etwMetricData->UserData;

            metricData.MonitoringAccount = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);
            metricData.MetricNamespace   = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);
            metricData.MetricName        = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);

            long timestamp = *((long *)pointerInPayload);

            metricData.MetricTimeUtc = DateTime.FromFileTimeUtc(timestamp);
            pointerInPayload         = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(long));

            // Read the dimension name and values and split them out.
            var dimensionNames  = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);
            var dimensionValues = EtwPayloadManipulationUtils.ReadString(ref pointerInPayload);

            if (!string.IsNullOrWhiteSpace(dimensionNames) && !string.IsNullOrWhiteSpace(dimensionValues))
            {
                var splitDimensionNames  = dimensionNames.Split(EtwListSeparatorChar, StringSplitOptions.None);
                var splitDimensionValues = dimensionValues.Split(EtwListSeparatorChar, StringSplitOptions.None);

                // Expected that both lengths be the same since they are written this way.
                for (var x = 0; x < splitDimensionNames.Length && x < splitDimensionValues.Length; ++x)
                {
                    metricData.dimensions[splitDimensionNames[x]] = splitDimensionValues[x];
                }
            }

            var scalingFactor = *((float *)pointerInPayload);

            pointerInPayload         = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(float));
            metricData.ScalingFactor = scalingFactor;

            var samplingTypes = (SamplingTypes)(*((int *)pointerInPayload));

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(int));

            if ((samplingTypes & SamplingTypes.Min) != 0)
            {
                metricData.Min       = *((ulong *)pointerInPayload);
                metricData.ScaledMin = metricData.Min / scalingFactor;
            }

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(ulong));

            if ((samplingTypes & SamplingTypes.Max) != 0)
            {
                metricData.Max       = *((ulong *)pointerInPayload);
                metricData.ScaledMax = metricData.Max / scalingFactor;
            }

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(ulong));

            if ((samplingTypes & SamplingTypes.Sum) != 0)
            {
                metricData.Sum       = *((ulong *)pointerInPayload);
                metricData.ScaledSum = metricData.Sum / scalingFactor;
            }

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(ulong));

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(float));

            if ((samplingTypes & SamplingTypes.Count) != 0)
            {
                metricData.Count = *((uint *)pointerInPayload);
            }

            pointerInPayload = EtwPayloadManipulationUtils.Shift(pointerInPayload, sizeof(uint));

            return(metricData);
        }