{"action":"created","comment":{"url":"https://api.github.com/repos/influxdb/telegraf/pulls/comments/39176858","id":39176858,"diff_hunk":"@@ -0,0 +1,255 @@\n+package webservercodes\n+\n+import (\n+\t\"net/http\"\n+\t\"strconv\"\n+\t\"sync\"\n+\t\"time\"\n+\t\"os\"\n+\t\"io\"\n+\t\"regexp\"\n+\t\"errors\"\n+\t\n+\t\"github.com/rogpeppe/rog-go/reverse\"\n+\t\"github.com/influxdb/telegraf/plugins\"\n+)\n+\n+type Vhost struct {\n+    Host string\n+    AccessLog string\n+    RegexParsestring string\n+    Interval string\n+}\n+\n+type Webservercodes struct {\n+\tVhosts []*Vhost\n+}\n+\n+type HttpStats struct {\n+    codes map[int]int\n+}\n+\n+var sampleConfig = `\n+# List of virtualhosts for http codes collecting (each section for one virtualhost, none for disable collecting codes)\n+[[webservercodes.vhosts]]\n+# 'host' field should match hostname in appropriate status url\n+host = \"defaulthost\"\n+\n+# telegraf user must have read permissions to this log file (shell command 'sudo adduser telegraf adm' for apache on Ubuntu)\n+access_log = \"/var/log/apache2/access.log\"\n+\n+# Regular expression for fetching codes from log file strings. You can adjust regex for your custom log format\n+# example for apache \"common\" and \"combined\" log formats, nginx default log format (\"combined\"):\n+#   '\\[(?P<time>[^\\]]+)\\] \".*?\" (?P<code>\\d{3})'\n+regex_parsestring = '\\[(?P<time>[^\\]]+)\\] \".*?\" (?P<code>\\d{3})'\n+\n+# plugin will count http codes in this interval. Interval must be in time.Duration format (see https://golang.org/pkg/time/#ParseDuration)\n+interval = \"10s\"\n+`\n+\n+func (n *Webservercodes) SampleConfig() string {\n+\treturn sampleConfig\n+}\n+\n+func (n *Webservercodes) Description() string {\n+\treturn \"Read webserver access log files and collects http return codes stats\"\n+}\n+\n+func (n *Webservercodes) Gather(acc plugins.Accumulator) error {\n+\tvar wg sync.WaitGroup\n+\t\n+    hostStats := map[string]HttpStats{}\n+    errChan := make(chan error)\n+    successChan := make(chan bool)\n+    remainingItems := len(n.Vhosts)\n+    \n+    for _, vhost := range n.Vhosts {\n+        if duration, err := time.ParseDuration(vhost.Interval); err == nil {\n+            wg.Add(1)\n+            go func(host string, logfile string, regex string, duration time.Duration, successChan chan bool, errChan chan error) {\n+                defer wg.Done()\n+                if stats, err := n.ParseHttpCodes(logfile, regex, duration); err == nil {\n+                    hostStats[host] = *stats\n+                    successChan <- true\n+                } else {\n+                    errChan <- err\n+                }\n+            }(vhost.Host, vhost.AccessLog, vhost.RegexParsestring, duration, successChan, errChan)\n+        } else {\n+            return err\n+        }\n+    }\n+    for {\n+        select {\n+            case _ = <-successChan:\n+                remainingItems--\n+            case err := <-errChan:\n+                return err\n+        }\n+        if remainingItems == 0 {\n+            break;\n+        }\n+    }\n+    \n+    wg.Wait()\n+\t\n+    for vhost, stats := range hostStats {\n+        n.gatherCodes(vhost, stats, acc)\n+    }\n+\t\n+\treturn nil\n+}\n+\n+func SearchStringInSlice(a string, list []string) bool {\n+    for _, b := range list {\n+        if b == a {\n+            return true\n+        }\n+    }\n+    return false\n+}\n+\n+func (n Webservercodes) ParseRegex(regex string, f io.ReadSeeker) (*regexp.Regexp, error) {\n+    \n+    if rx, err := regexp.Compile(regex); err == nil {\n+        \n+        keys := rx.SubexpNames();\n+        if SearchStringInSlice(\"time\", keys) && SearchStringInSlice(\"code\", keys) {\n+            \n+            reader := reverse.NewScanner(f)","path":"plugins/webservercodes/webserver_codes.go","position":119,"original_position":119,"commit_id":"07c4f51157a5c3cc4be84fd72b084256e07a0166","original_commit_id":"07c4f51157a5c3cc4be84fd72b084256e07a0166","user":{"login":"sparrc","id":7155926,"avatar_url":"https://avatars.githubusercontent.com/u/7155926?v=3","gravatar_id":"","url":"https://api.github.com/users/sparrc","html_url":"https://github.com/sparrc","followers_url":"https://api.github.com/users/sparrc/followers","following_url":"https://api.github.com/users/sparrc/following{/other_user}","gists_url":"https://api.github.com/users/sparrc/gists{/gist_id}","starred_url":"https://api.github.com/users/sparrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sparrc/subscriptions","organizations_url":"https://api.github.com/users/sparrc/orgs","repos_url":"https://api.github.com/users/sparrc/repos","events_url":"https://api.github.com/users/sparrc/events{/privacy}","received_events_url":"https://api.github.com/users/sparrc/received_events","type":"User","site_admin":false},"body":"fair enough","created_at":"2015-09-10T15:53:30Z","updated_at":"2015-09-10T15:53:30Z","html_url":"https://github.com/influxdb/telegraf/pull/176#discussion_r39176858","pull_request_url":"https://api.github.com/repos/influxdb/telegraf/pulls/176","_links":{"self":{"href":"https://api.github.com/repos/influxdb/telegraf/pulls/comments/39176858"},"html":{"href":"https://github.com/influxdb/telegraf/pull/176#discussion_r39176858"},"pull_request":{"href":"https://api.github.com/repos/influxdb/telegraf/pulls/176"}}},"pull_request":{"url":"https://api.github.com/repos/influxdb/telegraf/pulls/176","id":44603524,"html_url":"https://github.com/influxdb/telegraf/pull/176","diff_url":"https://github.com/influxdb/telegraf/pull/176.diff","patch_url":"https://github.com/influxdb/telegraf/pull/176.patch","issue_url":"https://api.github.com/repos/influxdb/telegraf/issues/176","number":176,"state":"open","locked":false,"title":"added webservercodes plugin","user":{"login":"KPACHbIuLLIAnO4","id":9525495,"avatar_url":"https://avatars.githubusercontent.com/u/9525495?v=3","gravatar_id":"","url":"https://api.github.com/users/KPACHbIuLLIAnO4","html_url":"https://github.com/KPACHbIuLLIAnO4","followers_url":"https://api.github.com/users/KPACHbIuLLIAnO4/followers","following_url":"https://api.github.com/users/KPACHbIuLLIAnO4/following{/other_user}","gists_url":"https://api.github.com/users/KPACHbIuLLIAnO4/gists{/gist_id}","starred_url":"https://api.github.com/users/KPACHbIuLLIAnO4/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KPACHbIuLLIAnO4/subscriptions","organizations_url":"https://api.github.com/users/KPACHbIuLLIAnO4/orgs","repos_url":"https://api.github.com/users/KPACHbIuLLIAnO4/repos","events_url":"https://api.github.com/users/KPACHbIuLLIAnO4/events{/privacy}","received_events_url":"https://api.github.com/users/KPACHbIuLLIAnO4/received_events","type":"User","site_admin":false},"body":"This is plugin for collecting http codes returned to clients by parsing web server logs (all codes from rfc 2616). Plugin allows to set one access log per virtualhost, unlimited virtualhosts. Different log formats allowed, examples for apache and nginx.","created_at":"2015-09-09T21:35:39Z","updated_at":"2015-09-10T15:53:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b18d265b77dec0f9b8525d11dc0b51e7c64fcaab","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/influxdb/telegraf/pulls/176/commits","review_comments_url":"https://api.github.com/repos/influxdb/telegraf/pulls/176/comments","review_comment_url":"https://api.github.com/repos/influxdb/telegraf/pulls/comments{/number}","comments_url":"https://api.github.com/repos/influxdb/telegraf/issues/176/comments","statuses_url":"https://api.github.com/repos/influxdb/telegraf/statuses/07c4f51157a5c3cc4be84fd72b084256e07a0166","head":{"label":"KPACHbIuLLIAnO4:webservercodes","ref":"webservercodes","sha":"07c4f51157a5c3cc4be84fd72b084256e07a0166","user":{"login":"KPACHbIuLLIAnO4","id":9525495,"avatar_url":"https://avatars.githubusercontent.com/u/9525495?v=3","gravatar_id":"","url":"https://api.github.com/users/KPACHbIuLLIAnO4","html_url":"https://github.com/KPACHbIuLLIAnO4","followers_url":"https://api.github.com/users/KPACHbIuLLIAnO4/followers","following_url":"https://api.github.com/users/KPACHbIuLLIAnO4/following{/other_user}","gists_url":"https://api.github.com/users/KPACHbIuLLIAnO4/gists{/gist_id}","starred_url":"https://api.github.com/users/KPACHbIuLLIAnO4/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KPACHbIuLLIAnO4/subscriptions","organizations_url":"https://api.github.com/users/KPACHbIuLLIAnO4/orgs","repos_url":"https://api.github.com/users/KPACHbIuLLIAnO4/repos","events_url":"https://api.github.com/users/KPACHbIuLLIAnO4/events{/privacy}","received_events_url":"https://api.github.com/users/KPACHbIuLLIAnO4/received_events","type":"User","site_admin":false},"repo":{"id":42203071,"name":"telegraf","full_name":"KPACHbIuLLIAnO4/telegraf","owner":{"login":"KPACHbIuLLIAnO4","id":9525495,"avatar_url":"https://avatars.githubusercontent.com/u/9525495?v=3","gravatar_id":"","url":"https://api.github.com/users/KPACHbIuLLIAnO4","html_url":"https://github.com/KPACHbIuLLIAnO4","followers_url":"https://api.github.com/users/KPACHbIuLLIAnO4/followers","following_url":"https://api.github.com/users/KPACHbIuLLIAnO4/following{/other_user}","gists_url":"https://api.github.com/users/KPACHbIuLLIAnO4/gists{/gist_id}","starred_url":"https://api.github.com/users/KPACHbIuLLIAnO4/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KPACHbIuLLIAnO4/subscriptions","organizations_url":"https://api.github.com/users/KPACHbIuLLIAnO4/orgs","repos_url":"https://api.github.com/users/KPACHbIuLLIAnO4/repos","events_url":"https://api.github.com/users/KPACHbIuLLIAnO4/events{/privacy}","received_events_url":"https://api.github.com/users/KPACHbIuLLIAnO4/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/KPACHbIuLLIAnO4/telegraf","description":"The plugin-driven server agent for reporting metrics into InfluxDB.","fork":true,"url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf","forks_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/forks","keys_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/teams","hooks_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/hooks","issue_events_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/issues/events{/number}","events_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/events","assignees_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/assignees{/user}","branches_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/branches{/branch}","tags_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/tags","blobs_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/git/refs{/sha}","trees_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/statuses/{sha}","languages_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/languages","stargazers_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/stargazers","contributors_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/contributors","subscribers_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/subscribers","subscription_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/subscription","commits_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/commits{/sha}","git_commits_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/git/commits{/sha}","comments_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/comments{/number}","issue_comment_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/issues/comments{/number}","contents_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/contents/{+path}","compare_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/merges","archive_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/downloads","issues_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/issues{/number}","pulls_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/pulls{/number}","milestones_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/milestones{/number}","notifications_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/labels{/name}","releases_url":"https://api.github.com/repos/KPACHbIuLLIAnO4/telegraf/releases{/id}","created_at":"2015-09-09T20:33:18Z","updated_at":"2015-09-09T20:33:19Z","pushed_at":"2015-09-09T21:29:00Z","git_url":"git://github.com/KPACHbIuLLIAnO4/telegraf.git","ssh_url":"git@github.com:KPACHbIuLLIAnO4/telegraf.git","clone_url":"https://github.com/KPACHbIuLLIAnO4/telegraf.git","svn_url":"https://github.com/KPACHbIuLLIAnO4/telegraf","homepage":"","size":7468,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"influxdb:master","ref":"master","sha":"a7ed46160ad68937a3c1385d28d736352e1fe883","user":{"login":"influxdb","id":5713248,"avatar_url":"https://avatars.githubusercontent.com/u/5713248?v=3","gravatar_id":"","url":"https://api.github.com/users/influxdb","html_url":"https://github.com/influxdb","followers_url":"https://api.github.com/users/influxdb/followers","following_url":"https://api.github.com/users/influxdb/following{/other_user}","gists_url":"https://api.github.com/users/influxdb/gists{/gist_id}","starred_url":"https://api.github.com/users/influxdb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/influxdb/subscriptions","organizations_url":"https://api.github.com/users/influxdb/orgs","repos_url":"https://api.github.com/users/influxdb/repos","events_url":"https://api.github.com/users/influxdb/events{/privacy}","received_events_url":"https://api.github.com/users/influxdb/received_events","type":"Organization","site_admin":false},"repo":{"id":33258973,"name":"telegraf","full_name":"influxdb/telegraf","owner":{"login":"influxdb","id":5713248,"avatar_url":"https://avatars.githubusercontent.com/u/5713248?v=3","gravatar_id":"","url":"https://api.github.com/users/influxdb","html_url":"https://github.com/influxdb","followers_url":"https://api.github.com/users/influxdb/followers","following_url":"https://api.github.com/users/influxdb/following{/other_user}","gists_url":"https://api.github.com/users/influxdb/gists{/gist_id}","starred_url":"https://api.github.com/users/influxdb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/influxdb/subscriptions","organizations_url":"https://api.github.com/users/influxdb/orgs","repos_url":"https://api.github.com/users/influxdb/repos","events_url":"https://api.github.com/users/influxdb/events{/privacy}","received_events_url":"https://api.github.com/users/influxdb/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/influxdb/telegraf","description":"The plugin-driven server agent for reporting metrics into InfluxDB.","fork":false,"url":"https://api.github.com/repos/influxdb/telegraf","forks_url":"https://api.github.com/repos/influxdb/telegraf/forks","keys_url":"https://api.github.com/repos/influxdb/telegraf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/influxdb/telegraf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/influxdb/telegraf/teams","hooks_url":"https://api.github.com/repos/influxdb/telegraf/hooks","issue_events_url":"https://api.github.com/repos/influxdb/telegraf/issues/events{/number}","events_url":"https://api.github.com/repos/influxdb/telegraf/events","assignees_url":"https://api.github.com/repos/influxdb/telegraf/assignees{/user}","branches_url":"https://api.github.com/repos/influxdb/telegraf/branches{/branch}","tags_url":"https://api.github.com/repos/influxdb/telegraf/tags","blobs_url":"https://api.github.com/repos/influxdb/telegraf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/influxdb/telegraf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/influxdb/telegraf/git/refs{/sha}","trees_url":"https://api.github.com/repos/influxdb/telegraf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/influxdb/telegraf/statuses/{sha}","languages_url":"https://api.github.com/repos/influxdb/telegraf/languages","stargazers_url":"https://api.github.com/repos/influxdb/telegraf/stargazers","contributors_url":"https://api.github.com/repos/influxdb/telegraf/contributors","subscribers_url":"https://api.github.com/repos/influxdb/telegraf/subscribers","subscription_url":"https://api.github.com/repos/influxdb/telegraf/subscription","commits_url":"https://api.github.com/repos/influxdb/telegraf/commits{/sha}","git_commits_url":"https://api.github.com/repos/influxdb/telegraf/git/commits{/sha}","comments_url":"https://api.github.com/repos/influxdb/telegraf/comments{/number}","issue_comment_url":"https://api.github.com/repos/influxdb/telegraf/issues/comments{/number}","contents_url":"https://api.github.com/repos/influxdb/telegraf/contents/{+path}","compare_url":"https://api.github.com/repos/influxdb/telegraf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/influxdb/telegraf/merges","archive_url":"https://api.github.com/repos/influxdb/telegraf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/influxdb/telegraf/downloads","issues_url":"https://api.github.com/repos/influxdb/telegraf/issues{/number}","pulls_url":"https://api.github.com/repos/influxdb/telegraf/pulls{/number}","milestones_url":"https://api.github.com/repos/influxdb/telegraf/milestones{/number}","notifications_url":"https://api.github.com/repos/influxdb/telegraf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/influxdb/telegraf/labels{/name}","releases_url":"https://api.github.com/repos/influxdb/telegraf/releases{/id}","created_at":"2015-04-01T16:28:44Z","updated_at":"2015-09-10T08:41:33Z","pushed_at":"2015-09-10T11:30:12Z","git_url":"git://github.com/influxdb/telegraf.git","ssh_url":"git@github.com:influxdb/telegraf.git","clone_url":"https://github.com/influxdb/telegraf.git","svn_url":"https://github.com/influxdb/telegraf","homepage":"","size":7468,"stargazers_count":446,"watchers_count":446,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":72,"mirror_url":null,"open_issues_count":25,"forks":72,"open_issues":25,"watchers":446,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/influxdb/telegraf/pulls/176"},"html":{"href":"https://github.com/influxdb/telegraf/pull/176"},"issue":{"href":"https://api.github.com/repos/influxdb/telegraf/issues/176"},"comments":{"href":"https://api.github.com/repos/influxdb/telegraf/issues/176/comments"},"review_comments":{"href":"https://api.github.com/repos/influxdb/telegraf/pulls/176/comments"},"review_comment":{"href":"https://api.github.com/repos/influxdb/telegraf/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/influxdb/telegraf/pulls/176/commits"},"statuses":{"href":"https://api.github.com/repos/influxdb/telegraf/statuses/07c4f51157a5c3cc4be84fd72b084256e07a0166"}}}}