From cc7b50cc77836a11c398d55aa5f9028a6997f21e Mon Sep 17 00:00:00 2001 From: "Jeffrey T. Fritz" Date: Tue, 19 Mar 2024 12:11:48 -0400 Subject: [PATCH] Added TwitchChat metrics (#420) --- ...n => TagzApp Dashboard-1710864444226.json} | 97 ++++++++++++++++--- src/TagzApp.Blazor/OpenTelemetryExtensions.cs | 1 + .../StartTwitchChat.cs | 1 + .../TwitchChatInstrumentation.cs | 20 ++++ .../TwitchChatProvider.cs | 14 ++- 5 files changed, 121 insertions(+), 12 deletions(-) rename observability-config/dashboards/{TagzApp Dashboard-1710808195996.json => TagzApp Dashboard-1710864444226.json} (75%) create mode 100644 src/TagzApp.Providers.TwitchChat/TwitchChatInstrumentation.cs diff --git a/observability-config/dashboards/TagzApp Dashboard-1710808195996.json b/observability-config/dashboards/TagzApp Dashboard-1710864444226.json similarity index 75% rename from observability-config/dashboards/TagzApp Dashboard-1710808195996.json rename to observability-config/dashboards/TagzApp Dashboard-1710864444226.json index 865645c0..5f0cd97b 100644 --- a/observability-config/dashboards/TagzApp Dashboard-1710808195996.json +++ b/observability-config/dashboards/TagzApp Dashboard-1710864444226.json @@ -36,8 +36,8 @@ "description": "", "gridPos": { "h": 11, - "w": 2, - "x": 7, + "w": 3, + "x": 0, "y": 0 }, "id": 3, @@ -53,6 +53,81 @@ "pluginVersion": "10.3.1", "type": "text" }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "Top 5 Twitch Chatters", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 8, + "x": 3, + "y": 0 + }, + "id": 4, + "options": { + "displayMode": "gradient", + "maxVizHeight": 80, + "minVizHeight": 50, + "minVizWidth": 8, + "namePlacement": "top", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": false, + "sizing": "manual", + "valueMode": "color" + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "topk(5, sum by (author) (sort_desc(max_over_time(twitchchat_messages_by_author_message_total[$__range]))))", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "B" + } + ], + "title": "Top 5 Twitch Chatters", + "transformations": [], + "type": "bargauge" + }, { "datasource": { "type": "prometheus", @@ -85,7 +160,7 @@ "gridPos": { "h": 11, "w": 8, - "x": 9, + "x": 11, "y": 0 }, "id": 1, @@ -218,7 +293,7 @@ "gridPos": { "h": 15, "w": 10, - "x": 7, + "x": 0, "y": 11 }, "id": 2, @@ -247,30 +322,30 @@ }, "editorMode": "code", "exemplar": false, - "expr": "round(increase(mastodon_messages_received_message_total[$__rate_interval]))", - "instant": false, + "expr": "round(increase(twitchchat_messages_received_message_total[$__rate_interval]))", + "instant": true, "legendFormat": "__auto", - "range": true, + "range": false, "refId": "A" } ], - "title": "Posts Received", + "title": "TwitchChat Messages Received", "transformations": [], "type": "timeseries" } ], - "refresh": "auto", + "refresh": "5s", "schemaVersion": 39, "tags": [], "templating": { "list": [] }, "time": { - "from": "now-1h", + "from": "now-6h", "to": "now" }, "timepicker": {}, - "timezone": "utc", + "timezone": "", "title": "TagzApp Dashboard", "uid": "fb737849-bd1f-45e3-9b20-3d87d4cc3e20", "version": 1, diff --git a/src/TagzApp.Blazor/OpenTelemetryExtensions.cs b/src/TagzApp.Blazor/OpenTelemetryExtensions.cs index 64117b3f..0874039f 100644 --- a/src/TagzApp.Blazor/OpenTelemetryExtensions.cs +++ b/src/TagzApp.Blazor/OpenTelemetryExtensions.cs @@ -42,6 +42,7 @@ public static IServiceCollection AddOpenTelemetryObservability(this IServiceColl builder .SetResourceBuilder(resourceBuilder) .AddMeter("mastodon-metrics") + .AddMeter("twitchchat-metrics") .AddProcessInstrumentation() .AddRuntimeInstrumentation() .AddHttpClientInstrumentation() diff --git a/src/TagzApp.Providers.TwitchChat/StartTwitchChat.cs b/src/TagzApp.Providers.TwitchChat/StartTwitchChat.cs index bf11f5cf..7828ce8d 100644 --- a/src/TagzApp.Providers.TwitchChat/StartTwitchChat.cs +++ b/src/TagzApp.Providers.TwitchChat/StartTwitchChat.cs @@ -15,6 +15,7 @@ public async Task RegisterServices(IServiceCollection servic _TwitchChatConfiguration = await ConfigureTagzAppFactory.Current.GetConfigurationById(ConfigurationKey); + services.AddSingleton(); services.AddSingleton(_TwitchChatConfiguration ?? TwitchChatConfiguration.Empty); services.AddHttpClient(new()); services.AddSingleton(); diff --git a/src/TagzApp.Providers.TwitchChat/TwitchChatInstrumentation.cs b/src/TagzApp.Providers.TwitchChat/TwitchChatInstrumentation.cs new file mode 100644 index 00000000..8ff44ba2 --- /dev/null +++ b/src/TagzApp.Providers.TwitchChat/TwitchChatInstrumentation.cs @@ -0,0 +1,20 @@ +using System.Diagnostics.Metrics; + +namespace TagzApp.Providers.TwitchChat; + +public class TwitchChatInstrumentation +{ + private Counter MessagesReceivedCounter { get; } + private Counter MessagesByAuthorCounter { get; } + + public TwitchChatInstrumentation(IMeterFactory meterFactory) + { + var meter = meterFactory.Create("twitchchat-metrics"); + + MessagesReceivedCounter = meter.CreateCounter("twitchchat-messages-received", "message", "Counter for TwitchChat Messages Received"); + MessagesByAuthorCounter = meter.CreateCounter("twitchchat-messages-by-author", "message", "Counter for TwitchChat Messages Received by Author"); + } + + public void AddMessages(int count) => MessagesReceivedCounter.Add(count); + public void AddMessages(string author) => MessagesByAuthorCounter.Add(1, new KeyValuePair("author", author)); +} diff --git a/src/TagzApp.Providers.TwitchChat/TwitchChatProvider.cs b/src/TagzApp.Providers.TwitchChat/TwitchChatProvider.cs index cc0e2a43..ede8a483 100644 --- a/src/TagzApp.Providers.TwitchChat/TwitchChatProvider.cs +++ b/src/TagzApp.Providers.TwitchChat/TwitchChatProvider.cs @@ -25,13 +25,15 @@ public class TwitchChatProvider : ISocialMediaProvider, IDisposable private readonly TwitchChatConfiguration _Settings; private readonly ILogger _Logger; private readonly TwitchProfileRepository _ProfileRepository; + private readonly TwitchChatInstrumentation _Instrumentation; - public TwitchChatProvider(ILogger logger, IConfiguration configuration, HttpClient client) + public TwitchChatProvider(ILogger logger, IConfiguration configuration, HttpClient client, TwitchChatInstrumentation instrumentation) { _Settings = ConfigureTagzAppFactory.Current.GetConfigurationById(Id).GetAwaiter().GetResult(); _Logger = logger; _ProfileRepository = new TwitchProfileRepository(configuration, client); Enabled = _Settings.Enabled; + _Instrumentation = instrumentation; if (!string.IsNullOrWhiteSpace(_Settings.Description)) { @@ -152,6 +154,16 @@ public Task> GetContentForHashtag(Hashtag tag, DateTimeOffs _Status = SocialMediaStatus.Healthy; _StatusMessage = "OK"; + _Instrumentation.AddMessages(messages?.Count() ?? 0); + + foreach (var username in messages?.Select(x => x.Author?.UserName)!) + { + if (!string.IsNullOrEmpty(username)) + { + _Instrumentation.AddMessages(username); + } + } + messages.ForEach(m => m.HashtagSought = tag.Text); return Task.FromResult(messages.AsEnumerable());