{"action":"created","comment":{"url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/comments/62126513","id":62126513,"diff_hunk":"@@ -0,0 +1,237 @@\n+﻿//  Copyright 2014 Bloomerang\n+//  Copyright 2016 Expected Behavior, LLC\n+//\n+//  Licensed under the Apache License, Version 2.0 (the \"License\");\n+//  you may not use this file except in compliance with the License.\n+//  You may obtain a copy of the License at\n+//\n+//      http://www.apache.org/licenses/LICENSE-2.0\n+//\n+//  Unless required by applicable law or agreed to in writing, software\n+//  distributed under the License is distributed on an \"AS IS\" BASIS,\n+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+//  See the License for the specific language governing permissions and\n+//  limitations under the License.\n+\n+using System;\n+using System.Text.RegularExpressions;\n+using Common.Logging;\n+\n+namespace Instrumental\n+{\n+  /// <summary>\n+  ///   Instrumental Agent used to send performance and other metrics to http://instrumentalapp.com\n+  /// </summary>\n+  public class Agent\n+  {\n+    /// <summary>\n+    ///   The agent version, according to the agent.  See script/check_version for things that must match this\n+    /// </summary>\n+    public static readonly String AgentVersion = \"0.2.0\";\n+\n+    /// <summary>\n+    ///   Enable/disable the agent.  This enables you to block sending of metrics to Instrumental without having to change your code.\n+    /// </summary>\n+    public bool Enabled { get; set; }\n+\n+    private readonly Collector _collector;\n+    private static readonly ILog _log = LogManager.GetCurrentClassLogger();\n+    private readonly Regex _validateMetric;\n+\n+    /// <summary>\n+    ///   The number of messages waiting to be sent to Instrumental\n+    /// </summary>\n+    public int MessageCount\n+    {\n+      get\n+        {\n+          return _collector.MessageCount;\n+        }\n+    }\n+\n+    /// <summary>\n+    ///   Create a new Agent\n+    /// </summary>\n+    /// <param name=\"apiKey\">Your project API key from instrumentalapp.com</param>\n+    public Agent(String apiKey)\n+    {\n+      if(string.IsNullOrEmpty(apiKey))\n+        throw new ArgumentException(\"api key was null or missing\", apiKey);\n+\n+      Enabled = true;\n+      _collector = new Collector(apiKey);\n+\n+      var validationOptions = RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture;\n+      _validateMetric = new Regex(@\"^([\\d\\w\\-_]+\\.)*[\\d\\w\\-_]+$\", validationOptions);\n+    }\n+\n+    /// <summary>\n+    ///   Measure the average value of something in your code, like response time.\n+    /// </summary>\n+    /// <param name=\"metricName\">The name of the metric to send.  Letters, numbers, and dots.</param>\n+    /// <param name=\"value\">The value to record.</param>\n+    /// <param name=\"time\">The exact time at which the event happened.  You probably want the default.</param>\n+    /// <param name=\"count\">The number of events which this represents.  You almost certainly want the default.</param>\n+    /// <returns>The value being passed in via value, or null if something bad happened.</returns>\n+    public float? Gauge(String metricName, float value, DateTime? time = null, int count = 1)\n+    {\n+      try\n+        {\n+          if(!ValidateMetricName(metricName)) return null;\n+          if(!Enabled) return value;\n+          int metricTime = (time ?? DateTime.Now).ToEpoch();\n+          _collector.SendMessage(String.Format(\"gauge {0} {1} {2} {3}\", metricName, value, metricTime, count));\n+          return value;\n+        }\n+      catch (Exception e)\n+        {\n+          ReportException(e);\n+        }\n+      return null;\n+    }\n+\n+    /// <summary>\n+    ///   Measure the duration of an action in seconds.\n+    /// </summary>\n+    /// <param name=\"metricName\">The name of the metric to send.  Letters, numbers, and dots.</param>\n+    /// <param name=\"action\">The action being measured</param>\n+    /// <returns>The result of executing the action.</returns>\n+    public T Time<T>(String metricName, Func<T> action)\n+    {\n+      return ActuallyTime(metricName, action);\n+    }\n+\n+    /// <summary>\n+    ///   Measure the duration of an action in seconds.\n+    /// </summary>\n+    /// <param name=\"metricName\">The name of the metric to send.  Letters, numbers, and dots.</param>\n+    /// <param name=\"action\">The action being measured</param>\n+    public void Time(String metricName, Action action)\n+    {\n+      ActuallyTime(metricName, action);\n+    }\n+\n+    /// <summary>\n+    ///   Measure the duration of an action in milliseconds.\n+    /// </summary>\n+    /// <param name=\"metricName\">The name of the metric to send.  Letters, numbers, and dots.</param>\n+    /// <param name=\"action\">The action being measured</param>\n+    /// <returns>The result of executing the action.</returns>\n+    public T TimeMs<T>(String metricName, Func<T> action)\n+    {\n+      return ActuallyTime(metricName, action, 1000);\n+    }\n+\n+    /// <summary>\n+    ///   Measure the duration of an action in milliseconds.\n+    /// </summary>\n+    /// <param name=\"metricName\">The name of the metric to send.  Letters, numbers, and dots.</param>\n+    /// <param name=\"action\">The action being measured</param>\n+    public void TimeMs(String metricName, Action action)\n+    {\n+      ActuallyTime(metricName, action, 1000);\n+    }\n+\n+    private T ActuallyTime<T>(String metricName, Func<T> action, float durationMultiplier = 1)\n+    {\n+      var start = DateTime.Now;\n+      try\n+        {\n+          return action();\n+        }\n+      finally\n+        {\n+          var end = DateTime.Now;\n+          var duration = end - start;\n+          Gauge(metricName, (float)duration.TotalSeconds * durationMultiplier);","path":"src/Agent.cs","position":146,"original_position":146,"commit_id":"371617271ac754ec1efa9c2d19322bfbb8b54264","original_commit_id":"371617271ac754ec1efa9c2d19322bfbb8b54264","user":{"login":"mediocretes","id":149895,"avatar_url":"https://avatars.githubusercontent.com/u/149895?v=3","gravatar_id":"","url":"https://api.github.com/users/mediocretes","html_url":"https://github.com/mediocretes","followers_url":"https://api.github.com/users/mediocretes/followers","following_url":"https://api.github.com/users/mediocretes/following{/other_user}","gists_url":"https://api.github.com/users/mediocretes/gists{/gist_id}","starred_url":"https://api.github.com/users/mediocretes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mediocretes/subscriptions","organizations_url":"https://api.github.com/users/mediocretes/orgs","repos_url":"https://api.github.com/users/mediocretes/repos","events_url":"https://api.github.com/users/mediocretes/events{/privacy}","received_events_url":"https://api.github.com/users/mediocretes/received_events","type":"User","site_admin":false},"body":"This cast is not necessary.","created_at":"2016-05-04T22:35:29Z","updated_at":"2016-05-04T22:35:29Z","html_url":"https://github.com/Instrumental/instrumental_agent-csharp/pull/13#discussion_r62126513","pull_request_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/13","_links":{"self":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/comments/62126513"},"html":{"href":"https://github.com/Instrumental/instrumental_agent-csharp/pull/13#discussion_r62126513"},"pull_request":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/13"}}},"pull_request":{"url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/13","id":68930211,"html_url":"https://github.com/Instrumental/instrumental_agent-csharp/pull/13","diff_url":"https://github.com/Instrumental/instrumental_agent-csharp/pull/13.diff","patch_url":"https://github.com/Instrumental/instrumental_agent-csharp/pull/13.patch","issue_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues/13","number":13,"state":"open","locked":false,"title":"Temp giant PR for me to review. :)","user":{"login":"jason-o-matic","id":13733,"avatar_url":"https://avatars.githubusercontent.com/u/13733?v=3","gravatar_id":"","url":"https://api.github.com/users/jason-o-matic","html_url":"https://github.com/jason-o-matic","followers_url":"https://api.github.com/users/jason-o-matic/followers","following_url":"https://api.github.com/users/jason-o-matic/following{/other_user}","gists_url":"https://api.github.com/users/jason-o-matic/gists{/gist_id}","starred_url":"https://api.github.com/users/jason-o-matic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jason-o-matic/subscriptions","organizations_url":"https://api.github.com/users/jason-o-matic/orgs","repos_url":"https://api.github.com/users/jason-o-matic/repos","events_url":"https://api.github.com/users/jason-o-matic/events{/privacy}","received_events_url":"https://api.github.com/users/jason-o-matic/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-05-04T20:54:46Z","updated_at":"2016-05-04T22:35:29Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2dcb845f84c6a4c3f774abaa495f9d88969515ef","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/13/commits","review_comments_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/13/comments","review_comment_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues/13/comments","statuses_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/statuses/371617271ac754ec1efa9c2d19322bfbb8b54264","head":{"label":"Instrumental:tmp_review","ref":"tmp_review","sha":"371617271ac754ec1efa9c2d19322bfbb8b54264","user":{"login":"Instrumental","id":17914730,"avatar_url":"https://avatars.githubusercontent.com/u/17914730?v=3","gravatar_id":"","url":"https://api.github.com/users/Instrumental","html_url":"https://github.com/Instrumental","followers_url":"https://api.github.com/users/Instrumental/followers","following_url":"https://api.github.com/users/Instrumental/following{/other_user}","gists_url":"https://api.github.com/users/Instrumental/gists{/gist_id}","starred_url":"https://api.github.com/users/Instrumental/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Instrumental/subscriptions","organizations_url":"https://api.github.com/users/Instrumental/orgs","repos_url":"https://api.github.com/users/Instrumental/repos","events_url":"https://api.github.com/users/Instrumental/events{/privacy}","received_events_url":"https://api.github.com/users/Instrumental/received_events","type":"Organization","site_admin":false},"repo":{"id":20925133,"name":"instrumental_agent-csharp","full_name":"Instrumental/instrumental_agent-csharp","owner":{"login":"Instrumental","id":17914730,"avatar_url":"https://avatars.githubusercontent.com/u/17914730?v=3","gravatar_id":"","url":"https://api.github.com/users/Instrumental","html_url":"https://github.com/Instrumental","followers_url":"https://api.github.com/users/Instrumental/followers","following_url":"https://api.github.com/users/Instrumental/following{/other_user}","gists_url":"https://api.github.com/users/Instrumental/gists{/gist_id}","starred_url":"https://api.github.com/users/Instrumental/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Instrumental/subscriptions","organizations_url":"https://api.github.com/users/Instrumental/orgs","repos_url":"https://api.github.com/users/Instrumental/repos","events_url":"https://api.github.com/users/Instrumental/events{/privacy}","received_events_url":"https://api.github.com/users/Instrumental/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Instrumental/instrumental_agent-csharp","description":"C# Agent for Instrumental Application Monitoring","fork":true,"url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp","forks_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/forks","keys_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/teams","hooks_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/hooks","issue_events_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues/events{/number}","events_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/events","assignees_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/assignees{/user}","branches_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/branches{/branch}","tags_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/tags","blobs_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/refs{/sha}","trees_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/statuses/{sha}","languages_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/languages","stargazers_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/stargazers","contributors_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/contributors","subscribers_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/subscribers","subscription_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/subscription","commits_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/commits{/sha}","git_commits_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/commits{/sha}","comments_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/comments{/number}","issue_comment_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues/comments{/number}","contents_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/contents/{+path}","compare_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/merges","archive_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/downloads","issues_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues{/number}","pulls_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls{/number}","milestones_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/milestones{/number}","notifications_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/labels{/name}","releases_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/releases{/id}","deployments_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/deployments","created_at":"2014-06-17T13:47:58Z","updated_at":"2016-05-04T16:17:00Z","pushed_at":"2016-05-04T22:17:55Z","git_url":"git://github.com/Instrumental/instrumental_agent-csharp.git","ssh_url":"git@github.com:Instrumental/instrumental_agent-csharp.git","clone_url":"https://github.com/Instrumental/instrumental_agent-csharp.git","svn_url":"https://github.com/Instrumental/instrumental_agent-csharp","homepage":"https://instrumentalapp.com","size":1505,"stargazers_count":1,"watchers_count":1,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":3,"forks":0,"open_issues":3,"watchers":1,"default_branch":"master"}},"base":{"label":"Instrumental:tmp_blank","ref":"tmp_blank","sha":"b7ed9eae8614fe901297409c9be732d34c8894ee","user":{"login":"Instrumental","id":17914730,"avatar_url":"https://avatars.githubusercontent.com/u/17914730?v=3","gravatar_id":"","url":"https://api.github.com/users/Instrumental","html_url":"https://github.com/Instrumental","followers_url":"https://api.github.com/users/Instrumental/followers","following_url":"https://api.github.com/users/Instrumental/following{/other_user}","gists_url":"https://api.github.com/users/Instrumental/gists{/gist_id}","starred_url":"https://api.github.com/users/Instrumental/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Instrumental/subscriptions","organizations_url":"https://api.github.com/users/Instrumental/orgs","repos_url":"https://api.github.com/users/Instrumental/repos","events_url":"https://api.github.com/users/Instrumental/events{/privacy}","received_events_url":"https://api.github.com/users/Instrumental/received_events","type":"Organization","site_admin":false},"repo":{"id":20925133,"name":"instrumental_agent-csharp","full_name":"Instrumental/instrumental_agent-csharp","owner":{"login":"Instrumental","id":17914730,"avatar_url":"https://avatars.githubusercontent.com/u/17914730?v=3","gravatar_id":"","url":"https://api.github.com/users/Instrumental","html_url":"https://github.com/Instrumental","followers_url":"https://api.github.com/users/Instrumental/followers","following_url":"https://api.github.com/users/Instrumental/following{/other_user}","gists_url":"https://api.github.com/users/Instrumental/gists{/gist_id}","starred_url":"https://api.github.com/users/Instrumental/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Instrumental/subscriptions","organizations_url":"https://api.github.com/users/Instrumental/orgs","repos_url":"https://api.github.com/users/Instrumental/repos","events_url":"https://api.github.com/users/Instrumental/events{/privacy}","received_events_url":"https://api.github.com/users/Instrumental/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Instrumental/instrumental_agent-csharp","description":"C# Agent for Instrumental Application Monitoring","fork":true,"url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp","forks_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/forks","keys_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/teams","hooks_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/hooks","issue_events_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues/events{/number}","events_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/events","assignees_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/assignees{/user}","branches_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/branches{/branch}","tags_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/tags","blobs_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/refs{/sha}","trees_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/statuses/{sha}","languages_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/languages","stargazers_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/stargazers","contributors_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/contributors","subscribers_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/subscribers","subscription_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/subscription","commits_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/commits{/sha}","git_commits_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/git/commits{/sha}","comments_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/comments{/number}","issue_comment_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues/comments{/number}","contents_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/contents/{+path}","compare_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/merges","archive_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/downloads","issues_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues{/number}","pulls_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls{/number}","milestones_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/milestones{/number}","notifications_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/labels{/name}","releases_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/releases{/id}","deployments_url":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/deployments","created_at":"2014-06-17T13:47:58Z","updated_at":"2016-05-04T16:17:00Z","pushed_at":"2016-05-04T22:17:55Z","git_url":"git://github.com/Instrumental/instrumental_agent-csharp.git","ssh_url":"git@github.com:Instrumental/instrumental_agent-csharp.git","clone_url":"https://github.com/Instrumental/instrumental_agent-csharp.git","svn_url":"https://github.com/Instrumental/instrumental_agent-csharp","homepage":"https://instrumentalapp.com","size":1505,"stargazers_count":1,"watchers_count":1,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":3,"forks":0,"open_issues":3,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/13"},"html":{"href":"https://github.com/Instrumental/instrumental_agent-csharp/pull/13"},"issue":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues/13"},"comments":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/issues/13/comments"},"review_comments":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/13/comments"},"review_comment":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/pulls/13/commits"},"statuses":{"href":"https://api.github.com/repos/Instrumental/instrumental_agent-csharp/statuses/371617271ac754ec1efa9c2d19322bfbb8b54264"}}}}