Permalink
Browse files

Support for WPT detailed metrics (i.e. size and time taken per host)

Example config file
Major refactoring
  • Loading branch information...
1 parent d279320 commit eb9aebe4d91bff9ed037d32d0554a514d9dd1159 @salerth committed Feb 28, 2012
View
@@ -1,4 +1,3 @@
-
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
bin
obj
@@ -86,4 +85,6 @@ ngit/
packages/*
*.testsettings
TestResult.xml
-*.VisualState.xml
+*.VisualState.xml
+
+metrics/App.config
View
@@ -7,6 +7,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Parsers", "parsers\Parsers.
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{33FE5D39-2B57-498F-8C2E-65CD70C16A85}"
ProjectSection(SolutionItems) = preProject
+ .gitignore = .gitignore
README.md = README.md
EndProjectSection
EndProject
View
@@ -23,6 +23,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
@@ -61,6 +62,9 @@
<None Include="App.config">
<SubType>Designer</SubType>
</None>
+ <None Include="example.App.config">
+ <SubType>Designer</SubType>
+ </None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
View
@@ -10,23 +10,23 @@ class Program
{
static void Main()
{
+
//Configuration based. Config file lists logs, sizes, regex, etc
var logParser = new LogTailParser();
- SendMetricsToGraphite(logParser.GetMetrics());
+ logParser.GetMetrics(SendMetricsToGraphite);
//WPT parsers
var wptParser = new WebPagetestParser();
- SendMetricsToGraphite(wptParser.GetMetrics());
+ wptParser.GetMetrics(SendMetricsToGraphite);
}
/// <summary>
/// Sends the gathered stats to Graphite
- /// TODO : Switch to statsd if frequent interval to stop spamming
- /// TODO : - Graphite used for historical adds to support intervals > finest whisper resolution
/// </summary>
private static void SendMetricsToGraphite(IEnumerable<Metric> metrics)
{
- using (var graphiteClient = new GraphiteTcpClient(ConfigurationManager.AppSettings["GraphiteHost"], Int32.Parse(ConfigurationManager.AppSettings["GraphitePort"]), ConfigurationManager.AppSettings["GraphiteKeyPrefix"]))
+ using (var graphiteClient = new GraphiteTcpClient(ConfigurationManager.AppSettings["GraphiteHost"],
+ Int32.Parse(ConfigurationManager.AppSettings["GraphitePort"]), ConfigurationManager.AppSettings["GraphiteKeyPrefix"]))
{
foreach (var metric in metrics)
{
View
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <configSections>
+ <section name="WebPagetest" type="Metrics.Parsers.WebPagetest.SiteConfigurationSection, Metrics.Parsers"/>
+ <section name="LogTail" type="Metrics.Parsers.LogTail.LogConfigurationSection, Metrics.Parsers"/>
+ </configSections>
+ <WebPagetest wptHost="http://mywebpagetest.private.instance">
+ <Sites>
+ <Site graphiteKey="wpt.home" url="http://www.example.com/" enableDetailedMetrics="true"/>
+ <Site graphiteKey="wpt.newsHome" url="http://www.example.com/news/" enableDetailedMetrics="true"/>
+ </Sites>
+ </WebPagetest>
+ <LogTail>
+ <!--Standard IIS log with timetaken enabled -->
+ <Patterns>
+ <add key="iis" value="^(?&lt;datetime&gt;\S+\s\S+)\s\S+\s\S+\s\S+\s/(?&lt;url&gt;[^+/]*)\S*\s\S+\s\S+\s\S+\s\S+\s\S+\s(?&lt;code&gt;\S+)\s\S+\s\S+\s(?&lt;timetaken&gt;\S+)$"/>
+ </Patterns>
+ <Logs>
+ <Log pattern="*.log" maxTailMB="0" regexKey="iis" name="myWebSite">
+ <Locations>
+ <add key="server1" value="\\server1\logs\w3svc1"/>
+ <add key="server2" value="\\server2\logs\w3svc1"/>
+ </Locations>
+ <Stats>
+ <Stat graphiteKey="timers.iis.{locationKey}.myWebSite.avg" value="timetaken" type="avg" interval="datetime" dateFormat="yyyy-MM-dd HH:mm:ss" includeZeros="false"/>
+ <Stat graphiteKey="stats.iis.{locationKey}.myWebSite.{0}" type="count" interval="datetime" dateFormat="yyyy-MM-dd HH:mm:ss" />
+ </Stats>
+ <Mapping>
+ <add key="0" value="?code"/>
+ </Mapping>
+ </Log>
+ </Logs>
+ </LogTail>
+ <appSettings>
+ <add key="GraphiteKeyPrefix" value="mySite"/>
+ <add key="GraphiteHost" value="www.example.com"/>
+ <add key="GraphitePort" value="1234"/>
+ </appSettings>
+</configuration>
View
@@ -1,9 +1,10 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
namespace Metrics.Parsers
{
public interface IMetricParser
{
- IEnumerable<Metric> GetMetrics();
+ void GetMetrics(Action<IEnumerable<Metric>> sendMetrics);
}
}
@@ -1,10 +1,11 @@
-using System.Configuration;
+using System.Collections.Generic;
+using System.Configuration;
namespace Metrics.Parsers.LogTail
{
[ConfigurationCollection(typeof(LogConfigurationCollection), AddItemName = "Log",
CollectionType = ConfigurationElementCollectionType.BasicMap)]
- public class LogConfigurationCollection : ConfigurationElementCollection
+ public class LogConfigurationCollection : ConfigurationElementCollection, IEnumerable<LogConfigurationElement>
{
protected override ConfigurationElement CreateNewElement()
@@ -14,12 +15,20 @@ protected override ConfigurationElement CreateNewElement()
protected override object GetElementKey(ConfigurationElement element)
{
- return ((LogConfigurationElement)element).Location + ((LogConfigurationElement)element).Pattern;
+ return ((LogConfigurationElement)element).Name + ((LogConfigurationElement)element).Pattern;
}
new public LogConfigurationElement this[string name]
{
get { return (LogConfigurationElement)BaseGet(name); }
}
+
+ public new IEnumerator<LogConfigurationElement> GetEnumerator()
+ {
+ foreach (var key in base.BaseGetAllKeys())
+ {
+ yield return BaseGet(key) as LogConfigurationElement;
+ }
+ }
}
}
@@ -15,8 +15,12 @@ internal Regex CompiledRegex
{
if (regex == null)
{
- var compiled = new Regex(Expression, RegexOptions.Compiled);
- Interlocked.CompareExchange(ref regex, compiled, null);
+ var section = ConfigurationManager.GetSection("LogTail") as LogConfigurationSection;
+ if (section != null)
+ {
+ var compiled = new Regex(section.Patterns[ExpressionKey].Value, RegexOptions.Compiled);
+ Interlocked.CompareExchange(ref regex, compiled, null);
+ }
}
return regex;
@@ -36,29 +40,29 @@ public bool Enabled
}
}
- [ConfigurationProperty("location", IsRequired = false)]
- public string Location
+ [ConfigurationProperty("pattern", IsRequired = false, DefaultValue = "*")]
+ public string Pattern
{
get
{
- return (String)this["location"];
+ return (String)this["pattern"];
}
set
{
- this["location"] = value;
+ this["pattern"] = value;
}
}
- [ConfigurationProperty("pattern", IsRequired = false, DefaultValue = "*")]
- public string Pattern
+ [ConfigurationProperty("name", IsRequired = true)]
+ public string Name
{
get
{
- return (String)this["pattern"];
+ return (String)this["name"];
}
set
{
- this["pattern"] = value;
+ this["name"] = value;
}
}
@@ -75,16 +79,29 @@ public int MaxTailMB
}
}
- [ConfigurationProperty("regex", IsRequired = true)]
- public string Expression
+ [ConfigurationProperty("onlyToday", IsRequired = false, DefaultValue = true)]
+ public bool OnlyToday
+ {
+ get
+ {
+ return (bool)this["onlyToday"];
+ }
+ set
+ {
+ this["onlyToday"] = value;
+ }
+ }
+
+ [ConfigurationProperty("regexKey", IsRequired = true)]
+ public string ExpressionKey
{
get
{
- return (String)this["regex"];
+ return (String)this["regexKey"];
}
set
{
- this["regex"] = value;
+ this["regexKey"] = value;
}
}
@@ -94,6 +111,12 @@ public KeyValueConfigurationCollection Mapping
get { return (KeyValueConfigurationCollection)this["Mapping"]; }
}
+ [ConfigurationProperty("Locations", IsRequired = true)]
+ public KeyValueConfigurationCollection Locations
+ {
+ get { return (KeyValueConfigurationCollection)this["Locations"]; }
+ }
+
[ConfigurationProperty("Stats", IsRequired = true)]
public LogStatConfigurationCollection Stats
{
@@ -4,11 +4,16 @@ namespace Metrics.Parsers.LogTail
{
public class LogConfigurationSection : ConfigurationSection
{
+ [ConfigurationProperty("Patterns", IsRequired = true)]
+ public KeyValueConfigurationCollection Patterns
+ {
+ get { return (KeyValueConfigurationCollection)this["Patterns"]; }
+ }
+
[ConfigurationProperty("Logs", IsRequired = true)]
public LogConfigurationCollection Logs
{
get { return (LogConfigurationCollection)this["Logs"]; }
}
-
}
}
Oops, something went wrong.

0 comments on commit eb9aebe

Please sign in to comment.