Skip to content

Instantly share code, notes, and snippets.

@joshrobb
Created September 8, 2014 03:10
Show Gist options
  • Save joshrobb/eb7cad888b7ae10bb989 to your computer and use it in GitHub Desktop.
Save joshrobb/eb7cad888b7ae10bb989 to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using Pushpay.Core;
using StatsdClient;
namespace Pushpay.Base
{
public static class Stats
{
static readonly string Prefix = GetPrefix();
static string GetPrefix()
{
return Settings.IsDevelopment
? "dev."
: Settings.IsProduction
? "prod."
: "qa.";
}
//TODO settings for StatsD host
static Statsd _client = new Statsd(Settings.StatsDHost, 8125, ConnectionType.Udp, Prefix);
public static void Incr(string name, int count = 1)
{
_client.LogCount(name, count);
}
public static void Timing(string name, long millis)
{
_client.LogTiming(name, millis);
}
public static IDisposable Time(string name)
{
var timer = Stopwatch.StartNew();
return new DisposingAction(() => _client.LogTiming(name, timer.ElapsedMilliseconds));
}
public static void Time(string name, Action action)
{
var timer = Stopwatch.StartNew();
action();
_client.LogTiming(name, timer.ElapsedMilliseconds);
}
public static void Gauge(string name, long value)
{
_client.LogGauge(name, Convert.ToInt32(value));
}
}
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using Mindscape.LightSpeed.Logging;
using Pushpay.Base;
namespace Pushpay.Core.Infrastructure
{
public class StatsDLogger : ILogger
{
const int SlowQueryLimit = 250;
public void LogSql(object sql)
{
var cmdLog = sql as CommandLog;
if (cmdLog != null) {
Stats.Timing("app.database.queries", Convert.ToInt64(cmdLog.TimeTaken.TotalMilliseconds));
Stats.Incr("app.database.queries");
TrackQueryForRequest();
if (cmdLog.TimeTaken.TotalMilliseconds > SlowQueryLimit)
{
Raygun.Error("Slow Query alert: " + GetTypeOfCommand(cmdLog.CommandText), new {
cmdLog.CommandText,
CommandParameters = FormatParametersForLogging(cmdLog.CommandParameters),
DurationInMilliseconds = cmdLog.TimeTaken.TotalMilliseconds,
SlowQueryLiminItMilliseconds = SlowQueryLimit
});
}
}
}
public static string GetTypeOfCommand(string commandText)
{
if (commandText.StartsWith("INSERT",StringComparison.OrdinalIgnoreCase)) return "INSERT";
if (commandText.StartsWith("UPDATE", StringComparison.OrdinalIgnoreCase)) return "UPDATE";
if (commandText.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase)) return "DELETE";
if (commandText.IndexOf("SELECT ", StringComparison.OrdinalIgnoreCase)>=0 || commandText.IndexOf("SELECT\r", StringComparison.OrdinalIgnoreCase)>=0) return "SELECT";
return "PROC";
}
public static Dictionary<string,object> FormatParametersForLogging(IEnumerable<IDataParameter> commandParameters)
{
return commandParameters.ToDictionary(x => x.ParameterName, x => x.Value);
}
static void TrackQueryForRequest()
{
IncrementRequestCounter("lightspeed_querycount");
}
public static void TrackRowsForRequest(int rows)
{
IncrementRequestCounter("lightspeed_rowcount");
}
static void IncrementRequestCounter(string key, int counterValue = 1)
{
if (HttpContext.Current == null) return;
var count = HttpContext.Current.Items[key];
if (count != null)
{
var i = (int)count;
counterValue += i;
}
HttpContext.Current.Items["key"] = counterValue;
}
static int GetRequestCounter(string key)
{
if (HttpContext.Current == null) return 1;
var count = HttpContext.Current.Items[key];
if (count == null) return 1;
return (int)count;
}
public static void EndRequest()
{
Stats.Incr("app.database.request.queries", GetRequestCounter("lightspeed_querycount"));
var rows = GetRequestCounter("lightspeed_rowcount");
Stats.Incr("app.database.request.rows",rows);
}
public void LogDebug(object text) {} //no-op
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment