Esempio n. 1
0
        internal override void WritePayload(float intervalSec)
        {
            lock (MyLock)
            {
                float value = 0;
                try
                {
                    value = _getMetricFunction();
                }
                catch (Exception ex)
                {
                    ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message);
                }

                CounterPayload payload = new CounterPayload();
                payload.Name              = _name;
                payload.DisplayName       = (DisplayName == null) ? "" : DisplayName;
                payload.Count             = 1; // NOTE: These dumb-looking statistics is intentional
                payload.IntervalSec       = intervalSec;
                payload.Mean              = value;
                payload.Max               = value;
                payload.Min               = value;
                payload.StandardDeviation = 0;
                _lastVal = value;
                _eventSource.Write("EventCounters", new EventSourceOptions()
                {
                    Level = EventLevel.LogAlways
                }, new PollingPayloadType(payload));
            }
        }
 public static ICounterPayload GenerateCounterPayload(
     bool isIncrementingCounter,
     string counterName,
     double counterValue,
     int displayRateTimeScaleSeconds = 0,
     string displayName  = "",
     string displayUnits = "")
 {
     if (isIncrementingCounter)
     {
         Dictionary <string, object> payloadFields = new Dictionary <string, object>()
         {
             { "Name", counterName },
             { "Increment", counterValue },
             { "DisplayName", displayName },
             { "DisplayRateTimeScale", displayRateTimeScaleSeconds == 0 ? "" : TimeSpan.FromSeconds(displayRateTimeScaleSeconds).ToString() },
             { "DisplayUnits", displayUnits },
         };
         ICounterPayload payload = new IncrementingCounterPayload(payloadFields, 1);
         return(payload);
     }
     else
     {
         Dictionary <string, object> payloadFields = new Dictionary <string, object>()
         {
             { "Name", counterName },
             { "Mean", counterValue },
             { "DisplayName", displayName },
             { "DisplayUnits", displayUnits },
         };
         ICounterPayload payload = new CounterPayload(payloadFields);
         return(payload);
     }
 }
Esempio n. 3
0
        internal override void WritePayload(float intervalSec)
        {
            lock (MyLock)
            {
                Flush();
                CounterPayload payload = new CounterPayload();
                payload.Count       = _count;
                payload.IntervalSec = intervalSec;
                if (0 < _count)
                {
                    payload.Mean = _sum / _count;
                    payload.StandardDeviation = Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
                }
                else
                {
                    payload.Mean = 0;
                    payload.StandardDeviation = 0;
                }
                payload.Min = _min;
                payload.Max = _max;

                payload.Metadata    = GetMetadataString();
                payload.DisplayName = DisplayName;
                payload.Name        = Name;
                ResetStatistics();
                EventSource.Write("EventCounters", new EventSourceOptions()
                {
                    Level = EventLevel.LogAlways
                }, new CounterPayloadType(payload));
            }
        }
Esempio n. 4
0
        public IDisposable Attach(EventPipeEventSource source, ReplicaInfo replicaInfo)
        {
            var store = replicaInfo.Metrics;

            source.Dynamic.All += traceEvent =>
            {
                try
                {
                    // Metrics
                    if (traceEvent.EventName.Equals("EventCounters"))
                    {
                        var value        = (IDictionary <string, object>)traceEvent.PayloadValue(0);
                        var eventPayload = (IDictionary <string, object>)value["Payload"];

                        var payload = CounterPayload.FromPayload(eventPayload);

                        store[traceEvent.ProviderName + "/" + payload.Name] = payload.Value;
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error processing counter for {ProviderName}:{EventName}", traceEvent.ProviderName, traceEvent.EventName);
                }
            };

            return(new NullDisposable());
        }
        internal override void WritePayload(float intervalSec, int pollingIntervalMillisec)
        {
            lock (this)
            {
                double value = 0;
                try
                {
                    value = _metricProvider();
                }
                catch (Exception ex)
                {
                    ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} metricProvider callback: " + ex.Message);
                }

                CounterPayload payload = new CounterPayload();
                payload.Name              = Name;
                payload.DisplayName       = DisplayName ?? "";
                payload.Count             = 1;                                     // NOTE: These dumb-looking statistics is intentional
                payload.IntervalSec       = intervalSec;
                payload.Series            = $"Interval={pollingIntervalMillisec}"; // TODO: This may need to change when we support multi-session
                payload.CounterType       = "Mean";
                payload.Mean              = value;
                payload.Max               = value;
                payload.Min               = value;
                payload.Metadata          = GetMetadataString();
                payload.StandardDeviation = 0;
                payload.DisplayUnits      = DisplayUnits ?? "";
                _lastVal = value;
                EventSource.Write("EventCounters", new EventSourceOptions()
                {
                    Level = EventLevel.LogAlways
                }, new PollingPayloadType(payload));
            }
        }
Esempio n. 6
0
        private void ProcessEvents(TraceEvent eventData)
        {
            if (eventData.EventName.Equals("EventCounters"))
            {
                try
                {
                    IDictionary <string, object> payloadVal    = (IDictionary <string, object>)eventData.PayloadValue(0);
                    IDictionary <string, object> payloadFields = (IDictionary <string, object>)payloadVal["Payload"];

                    var payload = CounterPayload.GetFromKvPairs(payloadFields);

                    OnNewCounterData(payload);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.ToString());
                }
            }
            else
            {
                try
                {
                    OnNewEventData(eventData);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.ToString());
                }
            }
        }
Esempio n. 7
0
 internal override void WritePayload(float intervalSec, int pollingIntervalMillisec)
 {
     lock (this)
     {
         Flush();
         CounterPayload payload = new CounterPayload();
         payload.Count       = _count;
         payload.IntervalSec = intervalSec;
         if (0 < _count)
         {
             payload.Mean = _sum / _count;
             payload.StandardDeviation = Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
         }
         else
         {
             payload.Mean = 0;
             payload.StandardDeviation = 0;
         }
         payload.Min          = _min;
         payload.Max          = _max;
         payload.Series       = $"Interval={pollingIntervalMillisec}"; // TODO: This may need to change when we support multi-session
         payload.CounterType  = "Mean";
         payload.Metadata     = GetMetadataString();
         payload.DisplayName  = DisplayName ?? "";
         payload.DisplayUnits = DisplayUnits ?? "";
         payload.Name         = Name;
         ResetStatistics();
         EventSource.Write("EventCounters", new EventSourceOptions()
         {
             Level = EventLevel.LogAlways
         }, new CounterPayloadType(payload));
     }
 }
Esempio n. 8
0
        internal override void WritePayload(float intervalSec)
        {
            lock (MyLock)
            {
                double value = 0;
                try
                {
                    value = _metricProvider();
                }
                catch (Exception ex)
                {
                    ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} metricProvider callback: " + ex.Message);
                }

                CounterPayload payload = new CounterPayload();
                payload.Name              = Name;
                payload.DisplayName       = DisplayName ?? "";
                payload.Count             = 1; // NOTE: These dumb-looking statistics is intentional
                payload.IntervalSec       = intervalSec;
                payload.Mean              = value;
                payload.Max               = value;
                payload.Min               = value;
                payload.Metadata          = GetMetadataString();
                payload.StandardDeviation = 0;
                _lastVal = value;
                EventSource.Write("EventCounters", new EventSourceOptions()
                {
                    Level = EventLevel.LogAlways
                }, new PollingPayloadType(payload));
            }
        }
Esempio n. 9
0
        private bool TryMapCounterPayload(BaseParseResult result, CounterPayload payload, out CounterData counterData)
        {
            counterData = null;

            if (payload.Value == ulong.MaxValue)
            {
                _logger.LogWarning("TryMapCounterPayload failed for '{SerialNumber}'. The payload value equals maximum ulong", _context.Mini.SerialNumber);
                return(false);
            }

            if ((payload is R21CounterPayload) && !(payload as R21CounterPayload).IsValid)
            {
                _logger.LogWarning("TryMapCounterPayload failed for '{SerialNumber}'. The payload is of type R21CounterPayload but not valid for counter '{InternalNr}'", _context.Mini.SerialNumber, payload.InternalNr);
                return(false);
            }

            if (ClientNotConnected())
            {
                // No connection with client, payload is last measured value and not the real value. First real value will be spread out over missing values
                _logger.LogWarning("TryMapCounterPayload failed for '{SerialNumber}'. There is no connection with client, data not saved", _context.Mini.SerialNumber);
                return(false);
            }

            if (!MapCounterId(payload, _context.Mini))
            {
                _logger.LogWarning("TryMapCounterPayload failed for '{SerialNumber}'. Mapping the counter {InternalNr} failed", _context.Mini.SerialNumber, payload.InternalNr);
                return(false);
            }

            // store the data in the payload into the corresponding counter
            var counter = FindCounter(payload);

            if (counter == null)
            {
                _logger.LogWarning("TryMapCounterPayload failed for '{SerialNumber}'. Received value for unknown counter: {InternalNr}", _context.Mini.SerialNumber, payload.InternalNr);
                return(false);
            }

            if (!(result is MiniParseResult parseResult))
            {
                _logger.LogWarning("TryMapCounterPayload failed for '{SerialNumber}'. The _result is not of type MiniParseResult", _context.Mini.SerialNumber);
                return(false);
            }

            // Counter is valid, set the LastDataReceived
            _context.Mini.QboxStatus.LastDataReceived = _dateTimeService.UtcNow;

            // Counter is valid, define a valid CounterData object
            counterData = new CounterData
            {
                SerialNumber = _context.Mini.SerialNumber,
                MeasureTime  = parseResult.Model.MeasurementTime.ToUniversalTime(), // .ToAmsterdam(), // Change to Dutch Timezone
                CounterId    = payload.InternalNr,
                PulseValue   = Convert.ToInt32(payload.Value)
            };

            return(true);
        }
Esempio n. 10
0
        private void OnNewCounterData(CounterPayload data)
        {
            var subscribers = NewCounterData;

            if (subscribers != null)
            {
                subscribers(this, data);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Process the payload
        /// </summary>
        /// <param name="ioPayload">Payload, InternalNr will be mapped to the actual internal number used to store the data.</param>
        public void Accept(CounterPayload ioPayload)
        {
            try
            {
                if (ioPayload.Value == ulong.MaxValue)
                {
                    return;
                }

                if ((ioPayload is R21CounterPayload) && !(ioPayload as R21CounterPayload).IsValid)
                {
                    Log.Debug("Invalid value for counter {0} / {1}", ioPayload.InternalNr, _context.Mini.SerialNumber);
                    return;
                }

                if (ClientNotConnected())
                {
                    // No connection with client, payload is last measured value and not the real value. First real value will be spread out over missing values
                    Log.Debug("No connection with client, data not saved");
                    return;
                }

                if (!MapCounterId(ioPayload, _context.Mini))
                {
                    return;
                }

                // store the data in the payload into the corresponding counter
                var counter = FindCounter(ioPayload);
                if (counter == null)
                {
                    Log.Warn(string.Format("Recieved value for unknown counter: {0} / {1}", ioPayload.InternalNr, _context.Mini.SerialNumber));
                    return;                     //todo: investigate if exception would be better
                }

                var parseResult = _result as MiniParseResult;
                if (parseResult == null)
                {
                    return;
                }

                counter.SetValue(parseResult.Model.MeasurementTime, ioPayload.Value, _context.Mini.QboxStatus);
                _context.Mini.QboxStatus.LastDataReceived = DateTime.UtcNow;
            }
            catch (Exception e)
            {
                Log.Error(e, e.Message);
            }
        }
Esempio n. 12
0
 public void CounterPayloadReceived(CounterPayload payload, bool _)
 {
     lock (_lock)
     {
         if (builder.Length > flushLength)
         {
             File.AppendAllText(_output, builder.ToString());
             builder.Clear();
         }
         builder
         .Append("{ \"timestamp\": \"").Append(DateTime.Now.ToString("u")).Append("\", ")
         .Append(" \"provider\": \"").Append(JsonEscape(payload.ProviderName)).Append("\", ")
         .Append(" \"name\": \"").Append(JsonEscape(payload.DisplayName)).Append("\", ")
         .Append(" \"tags\": \"").Append(JsonEscape(payload.Tags)).Append("\", ")
         .Append(" \"counterType\": \"").Append(JsonEscape(payload.CounterType)).Append("\", ")
         .Append(" \"value\": ").Append(payload.Value.ToString(CultureInfo.InvariantCulture)).Append(" },");
     }
 }
Esempio n. 13
0
        private CounterPoco FindCounter(CounterPayload payload)
        {
            if (payload is CounterWithSourcePayload)
            {
                var pl      = payload as CounterWithSourcePayload;
                var counter = _context.Mini.Counters.SingleOrDefault(s => s.CounterId == payload.InternalNr && s.Secondary != pl.PrimaryMeter && s.GroupId == pl.Source);

                if (counter != null)
                {
                    return(counter);
                }

                // No specific counter found, try to find counter with only internalNr
            }

            // Down grading firmware could lead to find multiple counters. InternalId is not unique from firmware revision 39
            return(_context.Mini.Counters.SingleOrDefault(s => s.CounterId == payload.InternalNr));
        }
Esempio n. 14
0
        /// <summary>
        /// Change the InternalId (CounterId) of the payload to the value that will be used to store and retrieve the measurements.
        /// </summary>
        /// <returns>false if the mapping could not be done (for example when the secondary meter type of a duo is not an S0 meter).</returns>
        private bool MapCounterId(CounterPayload ioPayload, Mini inMini)
        {
            Dictionary <int, int> mapping = null;

            var counterWithSourcePayload = ioPayload as CounterWithSourcePayload;

            if (counterWithSourcePayload == null || counterWithSourcePayload.PrimaryMeter)
            {
                // Firmware A34, Smart Meter and soladin measured on client reports counters instead of specific message:
                if (inMini.Clients.Any(d =>
                                       d.MeterType == DeviceMeterType.Smart_Meter_E || d.MeterType == DeviceMeterType.Smart_Meter_EG))
                {
                    mapping = SmartMeterIdMapping;
                }
                else if (inMini.Clients.Any(d => d.MeterType == DeviceMeterType.Soladin_600))
                {
                    mapping = SoladinIdMapping;
                }
            }

            if (counterWithSourcePayload != null && !counterWithSourcePayload.PrimaryMeter)
            {
                // At the moment we only support S0 as secondary meter type, so log an error when we find a different meter type.
                var clientsWithUnsupportedSecondaryMeterTypes = inMini.Clients.Where(c => c.SecondaryMeterType != DeviceMeterType.None &&
                                                                                     c.SecondaryMeterType != DeviceMeterType.SO_Pulse).ToList();
                if (clientsWithUnsupportedSecondaryMeterTypes.Count > 0)
                {
                    _logger.LogError("Qbox {SerialNumber} has counter for unsupported secondary meter type {SecondaryMeterType}", inMini.SerialNumber,
                                     clientsWithUnsupportedSecondaryMeterTypes[0].SecondaryMeterType);
                    return(false);
                }

                // S0 as secondary meter type does not need to be mapped.
            }

            if (mapping != null && mapping.ContainsKey(ioPayload.InternalNr))
            {
                ioPayload.InternalNr = mapping[ioPayload.InternalNr];
            }

            return(true);
        }
Esempio n. 15
0
        public void CounterPayloadReceived(CounterPayload payload, bool _)
        {
            lock (_lock)
            {
                if (builder.Length > flushLength)
                {
                    File.AppendAllText(_output, builder.ToString());
                    builder.Clear();
                }

                builder
                .Append(payload.Timestamp.ToString()).Append(',')
                .Append(payload.ProviderName).Append(',')
                .Append(payload.DisplayName);
                if (!string.IsNullOrEmpty(payload.Tags))
                {
                    builder.Append('[').Append(payload.Tags.Replace(',', ';')).Append(']');
                }
                builder.Append(',')
                .Append(payload.CounterType).Append(',')
                .Append(payload.Value.ToString(CultureInfo.InvariantCulture)).Append('\n');
            }
        }
 public PollingPayloadType(CounterPayload payload)
 {
     Payload = payload;
 }
Esempio n. 17
0
 public void Accept(CounterPayload payload)
 {
     throw new NotSupportedException();
 }
        public void ProcessEvents(string applicationName,
                                  string serviceName,
                                  int processId,
                                  string replicaName,
                                  ReplicaStatus replica,
                                  CancellationToken cancellationToken)
        {
            var hasEventPipe = false;

            for (int i = 0; i < 10; ++i)
            {
                if (DiagnosticsClient.GetPublishedProcesses().Contains(processId))
                {
                    hasEventPipe = true;
                    break;
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                Thread.Sleep(500);
            }

            if (!hasEventPipe)
            {
                _logger.LogInformation("Process id {PID}, does not support event pipe", processId);
                return;
            }

            _logger.LogInformation("Listening for event pipe events for {ServiceName} on process id {PID}", replicaName, processId);

            // Create the logger factory for this replica
            using var loggerFactory = LoggerFactory.Create(builder => ConfigureLogging(serviceName, replicaName, builder));

            var processor = new SimpleSpanProcessor(CreateSpanExporter(serviceName, replicaName));

            var providers = new List <EventPipeProvider>()
            {
                // Runtime Metrics
                new EventPipeProvider(
                    SystemRuntimeEventSourceName,
                    EventLevel.Informational,
                    (long)ClrTraceEventParser.Keywords.None,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),
                new EventPipeProvider(
                    MicrosoftAspNetCoreHostingEventSourceName,
                    EventLevel.Informational,
                    (long)ClrTraceEventParser.Keywords.None,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),
                new EventPipeProvider(
                    GrpcAspNetCoreServer,
                    EventLevel.Informational,
                    (long)ClrTraceEventParser.Keywords.None,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),

                // Application Metrics
                new EventPipeProvider(
                    applicationName,
                    EventLevel.Informational,
                    (long)ClrTraceEventParser.Keywords.None,
                    new Dictionary <string, string>()
                {
                    { "EventCounterIntervalSec", "1" }
                }
                    ),

                // Logging
                new EventPipeProvider(
                    MicrosoftExtensionsLoggingProviderName,
                    EventLevel.LogAlways,
                    (long)(LoggingEventSource.Keywords.JsonMessage | LoggingEventSource.Keywords.FormattedMessage)
                    ),

                // Distributed Tracing

                // Activity correlation
                new EventPipeProvider(TplEventSource,
                                      keywords: 0x80,
                                      eventLevel: EventLevel.LogAlways),

                // Diagnostic source events
                new EventPipeProvider(DiagnosticSourceEventSource,
                                      keywords: 0x1 | 0x2,
                                      eventLevel: EventLevel.Verbose,
                                      arguments: new Dictionary <string, string>
                {
                    { "FilterAndPayloadSpecs", DiagnosticFilterString }
                })
            };

            while (!cancellationToken.IsCancellationRequested)
            {
                EventPipeSession session = null;
                var client = new DiagnosticsClient(processId);

                try
                {
                    session = client.StartEventPipeSession(providers);
                }
                catch (EndOfStreamException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    if (!cancellationToken.IsCancellationRequested)
                    {
                        _logger.LogDebug(0, ex, "Failed to start the event pipe session");
                    }

                    // We can't even start the session, wait until the process boots up again to start another metrics thread
                    break;
                }

                void StopSession()
                {
                    try
                    {
                        session.Stop();
                    }
                    catch (EndOfStreamException)
                    {
                        // If the app we're monitoring exits abruptly, this may throw in which case we just swallow the exception and exit gracefully.
                    }
                    // We may time out if the process ended before we sent StopTracing command. We can just exit in that case.
                    catch (TimeoutException)
                    {
                    }
                    // On Unix platforms, we may actually get a PNSE since the pipe is gone with the process, and Runtime Client Library
                    // does not know how to distinguish a situation where there is no pipe to begin with, or where the process has exited
                    // before dotnet-counters and got rid of a pipe that once existed.
                    // Since we are catching this in StopMonitor() we know that the pipe once existed (otherwise the exception would've
                    // been thrown in StartMonitor directly)
                    catch (PlatformNotSupportedException)
                    {
                    }
                }

                using var _ = cancellationToken.Register(() => StopSession());

                try
                {
                    var source     = new EventPipeEventSource(session.EventStream);
                    var activities = new Dictionary <string, ActivityItem>();

                    source.Dynamic.All += traceEvent =>
                    {
                        try
                        {
                            // Uncomment to debug the diagnostics source event source
                            //if (traceEvent.EventName == "Message")
                            //{
                            //    _logger.LogTrace("[" + replicaName + "]:" + traceEvent.PayloadValue(0));
                            //}
                            //// Distributed tracing
                            // else
                            if (traceEvent.EventName == "Activity1Start/Start")
                            {
                                var listenerEventName = (string)traceEvent.PayloadByName("EventName");

                                if (traceEvent.PayloadByName("Arguments") is IDictionary <string, object>[] arguments)
                                {
                                    string           activityId    = null;
                                    string           parentId      = null;
                                    string           operationName = null;
                                    string           httpMethod    = null;
                                    string           path          = null;
                                    string           spanId        = null;
                                    string           parentSpanId  = null;
                                    string           traceId       = null;
                                    DateTime         startTime     = default;
                                    ActivityIdFormat idFormat      = default;

                                    foreach (var arg in arguments)
                                    {
                                        var key   = (string)arg["Key"];
                                        var value = (string)arg["Value"];

                                        if (key == "ActivityId")
                                        {
                                            activityId = value;
                                        }
                                        else if (key == "ActivityParentId")
                                        {
                                            parentId = value;
                                        }
                                        else if (key == "ActivityOperationName")
                                        {
                                            operationName = value;
                                        }
                                        else if (key == "ActivitySpanId")
                                        {
                                            spanId = value;
                                        }
                                        else if (key == "ActivityTraceId")
                                        {
                                            traceId = value;
                                        }
                                        else if (key == "ActivityParentSpanId")
                                        {
                                            parentSpanId = value;
                                        }
                                        else if (key == "Method")
                                        {
                                            httpMethod = value;
                                        }
                                        else if (key == "Path")
                                        {
                                            path = value;
                                        }
                                        else if (key == "ActivityStartTime")
                                        {
                                            startTime = new DateTime(long.Parse(value), DateTimeKind.Utc);
                                        }
                                        else if (key == "ActivityIdFormat")
                                        {
                                            idFormat = Enum.Parse <ActivityIdFormat>(value);
                                        }
                                    }

                                    if (string.IsNullOrEmpty(activityId))
                                    {
                                        // Not a 3.1 application (we can detect this earlier)
                                        return;
                                    }

                                    if (idFormat == ActivityIdFormat.Hierarchical)
                                    {
                                        // We need W3C to make it work
                                        return;
                                    }

                                    // This is what open telemetry currently does
                                    // https://github.com/open-telemetry/opentelemetry-dotnet/blob/4ba732af062ddc2759c02aebbc91335aaa3f7173/src/OpenTelemetry.Collector.AspNetCore/Implementation/HttpInListener.cs#L65-L92

                                    var item = new ActivityItem()
                                    {
                                        Name                                 = path,
                                        SpanId                               = ActivitySpanId.CreateFromString(spanId),
                                        TraceId                              = ActivityTraceId.CreateFromString(traceId),
                                        ParentSpanId                         = parentSpanId == "0000000000000000" ? default : ActivitySpanId.CreateFromString(parentSpanId),
                                                                   StartTime = startTime,
                                    };

                                    item.Attributes[SpanAttributeConstants.HttpMethodKey] = httpMethod;
                                    item.Attributes[SpanAttributeConstants.HttpPathKey]   = path;

                                    activities[activityId] = item;
                                }
                            }
                            else if (traceEvent.EventName == "Activity1Stop/Stop")
                            {
                                var listenerEventName = (string)traceEvent.PayloadByName("EventName");

                                if (traceEvent.PayloadByName("Arguments") is IDictionary <string, object>[] arguments)
                                {
                                    string   activityId = null;
                                    TimeSpan duration   = default;
                                    int      statusCode = 0;

                                    foreach (var arg in arguments)
                                    {
                                        var key   = (string)arg["Key"];
                                        var value = (string)arg["Value"];

                                        if (key == "ActivityId")
                                        {
                                            activityId = value;
                                        }
                                        else if (key == "StatusCode")
                                        {
                                            statusCode = int.Parse(value);
                                        }
                                        else if (key == "ActivityDuration")
                                        {
                                            duration = new TimeSpan(long.Parse(value));
                                        }
                                    }

                                    if (string.IsNullOrEmpty(activityId))
                                    {
                                        // Not a 3.1 application (we can detect this earlier)
                                        return;
                                    }

                                    if (activities.TryGetValue(activityId, out var item))
                                    {
                                        item.Attributes[SpanAttributeConstants.HttpStatusCodeKey] = statusCode;

                                        item.EndTime = item.StartTime + duration;

                                        var spanData = new SpanData(item.Name,
                                                                    new SpanContext(item.TraceId, item.SpanId, ActivityTraceFlags.Recorded),
                                                                    item.ParentSpanId,
                                                                    SpanKind.Server,
                                                                    item.StartTime,
                                                                    item.Attributes,
                                                                    Enumerable.Empty <Event>(),
                                                                    Enumerable.Empty <Link>(),
                                                                    null,
                                                                    Status.Ok,
                                                                    item.EndTime);

                                        processor.OnEnd(spanData);

                                        activities.Remove(activityId);
                                    }
                                }
                            }
                            else if (traceEvent.EventName == "Activity2Start/Start")
                            {
                                var listenerEventName = (string)traceEvent.PayloadByName("EventName");

                                _logger.LogDebug("[" + replicaName + "]: " + listenerEventName + " fired");
                            }
                            else if (traceEvent.EventName == "Activity2Stop/Stop")
                            {
                                var listenerEventName = (string)traceEvent.PayloadByName("EventName");

                                _logger.LogDebug("[" + replicaName + "]: " + listenerEventName + " fired");
                            }

                            // Metrics
                            else if (traceEvent.EventName.Equals("EventCounters"))
                            {
                                var payloadVal   = (IDictionary <string, object>)traceEvent.PayloadValue(0);
                                var eventPayload = (IDictionary <string, object>)payloadVal["Payload"];

                                ICounterPayload payload = CounterPayload.FromPayload(eventPayload);

                                replica.Metrics[traceEvent.ProviderName + "/" + payload.Name] = payload.Value;
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "Error processing counter for {ProviderName}:{EventName}", traceEvent.ProviderName, traceEvent.EventName);
                        }
                    };

                    // Logging
                    string lastFormattedMessage = "";

                    var logActivities = new Dictionary <Guid, LogActivityItem>();
                    var stack         = new Stack <Guid>();

                    source.Dynamic.AddCallbackForProviderEvent(MicrosoftExtensionsLoggingProviderName, "ActivityJsonStart/Start", (traceEvent) =>
                    {
                        var factoryId    = (int)traceEvent.PayloadByName("FactoryID");
                        var categoryName = (string)traceEvent.PayloadByName("LoggerName");
                        var argsJson     = (string)traceEvent.PayloadByName("ArgumentsJson");

                        // TODO: Store this information by logger factory id
                        var item = new LogActivityItem
                        {
                            ActivityID   = traceEvent.ActivityID,
                            ScopedObject = new LogObject(JsonDocument.Parse(argsJson).RootElement),
                        };

                        if (stack.TryPeek(out var parentId) && logActivities.TryGetValue(parentId, out var parentItem))
                        {
                            item.Parent = parentItem;
                        }

                        stack.Push(traceEvent.ActivityID);
                        logActivities[traceEvent.ActivityID] = item;
                    });

                    source.Dynamic.AddCallbackForProviderEvent(MicrosoftExtensionsLoggingProviderName, "ActivityJsonStop/Stop", (traceEvent) =>
                    {
                        var factoryId    = (int)traceEvent.PayloadByName("FactoryID");
                        var categoryName = (string)traceEvent.PayloadByName("LoggerName");

                        stack.Pop();
                        logActivities.Remove(traceEvent.ActivityID);
                    });

                    source.Dynamic.AddCallbackForProviderEvent(MicrosoftExtensionsLoggingProviderName, "MessageJson", (traceEvent) =>
                    {
                        // Level, FactoryID, LoggerName, EventID, EventName, ExceptionJson, ArgumentsJson
                        var logLevel      = (LogLevel)traceEvent.PayloadByName("Level");
                        var factoryId     = (int)traceEvent.PayloadByName("FactoryID");
                        var categoryName  = (string)traceEvent.PayloadByName("LoggerName");
                        var eventId       = (int)traceEvent.PayloadByName("EventId");
                        var eventName     = (string)traceEvent.PayloadByName("EventName");
                        var exceptionJson = (string)traceEvent.PayloadByName("ExceptionJson");
                        var argsJson      = (string)traceEvent.PayloadByName("ArgumentsJson");

                        // There's a bug that causes some of the columns to get mixed up
                        if (eventName.StartsWith("{"))
                        {
                            argsJson      = exceptionJson;
                            exceptionJson = eventName;
                            eventName     = null;
                        }

                        if (string.IsNullOrEmpty(argsJson))
                        {
                            return;
                        }

                        Exception exception = null;

                        var logger = loggerFactory.CreateLogger(categoryName);

                        var scopes = new List <IDisposable>();

                        if (logActivities.TryGetValue(traceEvent.ActivityID, out var logActivityItem))
                        {
                            // REVIEW: Does order matter here? We're combining everything anyways.
                            while (logActivityItem != null)
                            {
                                scopes.Add(logger.BeginScope(logActivityItem.ScopedObject));

                                logActivityItem = logActivityItem.Parent;
                            }
                        }

                        try
                        {
                            if (exceptionJson != "{}")
                            {
                                var exceptionMessage = JsonSerializer.Deserialize <JsonElement>(exceptionJson);
                                exception            = new LoggerException(exceptionMessage);
                            }

                            var message = JsonSerializer.Deserialize <JsonElement>(argsJson);
                            if (message.TryGetProperty("{OriginalFormat}", out var formatElement))
                            {
                                var formatString = formatElement.GetString();
                                var formatter    = new LogValuesFormatter(formatString);
                                object[] args    = new object[formatter.ValueNames.Count];
                                for (int i = 0; i < args.Length; i++)
                                {
                                    args[i] = message.GetProperty(formatter.ValueNames[i]).GetString();
                                }

                                logger.Log(logLevel, new EventId(eventId, eventName), exception, formatString, args);
                            }
                            else
                            {
                                var obj = new LogObject(message, lastFormattedMessage);
                                logger.Log(logLevel, new EventId(eventId, eventName), obj, exception, LogObject.Callback);
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.LogDebug(ex, "Error processing log entry for {ServiceName}", replicaName);
                        }
                        finally
                        {
                            scopes.ForEach(d => d.Dispose());
                        }
                    });

                    source.Dynamic.AddCallbackForProviderEvent(MicrosoftExtensionsLoggingProviderName, "FormattedMessage", (traceEvent) =>
                    {
                        // Level, FactoryID, LoggerName, EventID, EventName, FormattedMessage
                        var logLevel         = (LogLevel)traceEvent.PayloadByName("Level");
                        var factoryId        = (int)traceEvent.PayloadByName("FactoryID");
                        var categoryName     = (string)traceEvent.PayloadByName("LoggerName");
                        var eventId          = (int)traceEvent.PayloadByName("EventId");
                        var eventName        = (string)traceEvent.PayloadByName("EventName");
                        var formattedMessage = (string)traceEvent.PayloadByName("FormattedMessage");

                        if (string.IsNullOrEmpty(formattedMessage))
                        {
                            formattedMessage = eventName;
                            eventName        = "";
                        }

                        lastFormattedMessage = formattedMessage;
                    });

                    source.Process();
                }
Esempio n. 19
0
 /// <summary>
 /// Обработчик собьытия, выводит данные на конссоль
 /// </summary>
 /// <param name="sender">Кем сгенерировано событие</param>
 /// <param name="data">Данные счётчика</param>
 public void OnNewCounterData(object sender, CounterPayload data)
 {
     Console.WriteLine($"{data.DisplayName}: {data.Value} {data.DisplayUnits}");
 }
Esempio n. 20
0
 public CounterPayloadType(CounterPayload payload)
 {
     Payload = payload;
 }