Created
January 18, 2018 07:39
-
-
Save tonesandtones/8f45ab89e90d4474b108a35898a0d636 to your computer and use it in GitHub Desktop.
Hangfire stats collector Azure Function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Configuration; | |
using System.Globalization; | |
using System.Net.Http; | |
using System.Text; | |
using System.Threading.Tasks; | |
using Microsoft.Azure.WebJobs; | |
using Microsoft.Azure.WebJobs.Host; | |
using Flurl.Http; | |
using Microsoft.ApplicationInsights; | |
using Microsoft.ApplicationInsights.Extensibility; | |
using Newtonsoft.Json; | |
namespace HangfireStatsCollector | |
{ | |
public static class HangfireStatsCollector | |
{ | |
private static readonly string key; | |
private static readonly TelemetryClient telemetry; | |
static HangfireStatsCollector() | |
{ | |
key = ConfigurationManager.AppSettings["HangfireMetricsAppInsightsSinkKey"]; | |
if (!string.IsNullOrEmpty(key)) | |
{ | |
TelemetryConfiguration.Active.InstrumentationKey = key; | |
telemetry = new TelemetryClient() { InstrumentationKey = key }; | |
} | |
} | |
[FunctionName("HangfireStatsCollector")] | |
public static async Task Run( | |
[TimerTrigger("0 */1 * * * *", RunOnStartup = true)] TimerInfo myTimer, | |
TraceWriter log) | |
{ | |
log.Info($"C# Timer trigger function executed at: {DateTime.Now}"); | |
if (telemetry == null) | |
{ | |
log.Error("No App Insights instrumentation key available. Cannot publish metrics."); | |
return; | |
} | |
IList<string> paramsToFetch = new List<string> | |
{ | |
"enqueued:count-or-null", | |
"retries:count", | |
"recurring:count", | |
"servers:count", | |
"succeeded:count", | |
"failed:count" | |
}; | |
string ps = "metrics[]=" + string.Join("&metrics[]=", paramsToFetch); | |
string statsUrl = ConfigurationManager.AppSettings["HangfireStatsUrl"]; | |
if (string.IsNullOrEmpty(statsUrl)) | |
{ | |
log.Error("No Hangfire stats target URL specified. Cannot fetch metrics"); | |
return; | |
} | |
HangfireStatsWrapper stats; | |
try | |
{ | |
stats = | |
await statsUrl | |
.PostAsync( | |
new StringContent(ps, Encoding.UTF8, "application/x-www-form-urlencoded")) | |
.ReceiveJson<HangfireStatsWrapper>(); | |
} | |
catch (Exception e) | |
{ | |
log.Error("Unexpected exception", e); | |
telemetry.TrackException(e); | |
throw; | |
} | |
log.Info($"Got Hangfire stats: Succeeded = {stats.Succeeded.Value}, Retries = {stats.Retries.Value}, Failed = {stats.Failed.Value}"); | |
if (stats.Retries.ValueInt.HasValue) telemetry.TrackMetric("Hangfire-Retries", stats.Retries.ValueInt.Value); | |
if (stats.Succeeded.ValueInt.HasValue) telemetry.TrackMetric("Hangfire-Succeeded", stats.Succeeded.ValueInt.Value); | |
if (stats.Failed.ValueInt.HasValue) telemetry.TrackMetric("Hangfire-Failed", stats.Failed.ValueInt.Value); | |
if (stats.Servers.ValueInt.HasValue) telemetry.TrackMetric("Hangfire-Servers", stats.Servers.ValueInt.Value); | |
telemetry.Flush(); | |
} | |
} | |
public class HangfireStatsWrapper | |
{ | |
[JsonProperty("enqueued:count-or-null")] | |
public HangfireStat Enqueued { get; set; } | |
[JsonProperty("retries:count")] | |
public HangfireStat Retries { get; set; } | |
[JsonProperty("recurring:count")] | |
public HangfireStat Recurring { get; set; } | |
[JsonProperty("servers:count")] | |
public HangfireStat Servers { get; set; } | |
[JsonProperty("succeeded:count")] | |
public HangfireStat Succeeded { get; set; } | |
[JsonProperty("failed:count")] | |
public HangfireStat Failed { get; set; } | |
} | |
public class HangfireStat | |
{ | |
public string Value { get; set; } | |
[JsonIgnore] | |
public int? ValueInt | |
{ | |
get | |
{ | |
if (int.TryParse(Value, NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var valueResult)) | |
{ | |
return valueResult; | |
} | |
else | |
{ | |
return null; | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment