{"action":"created","comment":{"url":"https://api.github.com/repos/trivago/gollum/pulls/comments/126393034","pull_request_review_id":48871506,"id":126393034,"diff_hunk":"@@ -0,0 +1,175 @@\n+// Copyright 2015-2017 trivago GmbH\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+package format\n+\n+import (\n+\t\"encoding/json\"\n+\t\"fmt\"\n+\t\"github.com/trivago/gollum/core\"\n+\t\"github.com/trivago/tgo/tcontainer\"\n+\t\"strconv\"\n+\t\"strings\"\n+\t\"time\"\n+)\n+\n+// JSONToInflux10 formatter plugin\n+// JSONToInflux10 provides a transformation from JSON data to\n+// InfluxDB 0.9.1+ compatible line protocol data.\n+// Configuration example\n+//\n+//  - format.JSONToInflux10\n+//      TimeField: time\n+//      Measurement: measurement\n+//      Ignore:\n+//        - ignore\n+//        - these\n+//        - tags\n+//      Tags:\n+//        - datacenter\n+//        - service\n+//        - host\n+//        - application\n+//\n+// TimeField specifies the JSON field that holds the Unix timestamp of the message.\n+// The precision is seconds.\n+// By default, the field is named `time`. If such a key does not exist in the\n+// message, the current Unix timestamp at the time of parsing the message is used.\n+//\n+// Measurement specifies the JSON field that holds the measurement of the message.\n+// By default, the field is named `measurement`. This field MUST exist in the message.\n+// If it does not exist in the message, an error will be thrown.\n+//\n+// Ignore lists all JSON fields that will be ignored and not sent to InfluxDB.\n+//\n+// Tags lists all names of JSON fields to send to Influxdb as tags.\n+// The Influxdb 0.9 convention is that values that do not change every\n+// request should be considered metadata and given as tags.\n+//\n+// JsonToInfluxFormatter defines the formatter applied before the conversion\n+// from JSON to InfluxDB. By default this is set to format.Forward.\n+type JSONToInflux10 struct {\n+\tcore.SimpleFormatter `gollumdoc:\"embed_type\"`\n+\tmetadataEscape       *strings.Replacer\n+\tmeasurementEscape    *strings.Replacer\n+\tfieldValueEscape     *strings.Replacer\n+\ttimeField            string `config:\"Timefield\" default:\"time\"`\n+\tmeasurement          string `config:\"Measurement\" default:\"measurement\"`\n+\ttags                 map[string]bool\n+\tignore               map[string]bool\n+}\n+\n+func init() {\n+\tcore.TypeRegistry.Register(JSONToInflux10{})\n+}\n+\n+// Configure initializes this formatter with values from a plugin config.\n+func (format *JSONToInflux10) Configure(conf core.PluginConfigReader) {\n+\tformat.SimpleFormatter.Configure(conf)\n+\n+\tformat.metadataEscape = strings.NewReplacer(\",\", \"\\\\,\", \"=\", \"\\\\=\", \" \", \"\\\\ \")\n+\tformat.measurementEscape = strings.NewReplacer(\",\", \"\\\\,\", \" \", \"\\\\ \")\n+\tformat.fieldValueEscape = strings.NewReplacer(\"\\\"\", \"\\\\\\\"\")\n+\n+\t// Create a set from the tags array for O(1) lookup\n+\ttagsArray := conf.GetStringArray(\"Tags\", []string{})\n+\tformat.tags = map[string]bool{}\n+\tfor _, v := range tagsArray {\n+\t\tformat.tags[v] = true\n+\t}\n+\n+\t// Create a set from the ignore array for O(1) lookup\n+\tignoreArray := conf.GetStringArray(\"Ignore\", []string{})\n+\tformat.ignore = map[string]bool{}\n+\tfor _, v := range ignoreArray {\n+\t\tformat.ignore[v] = true\n+\t}\n+}\n+\n+func (format *JSONToInflux10) escapeMeasurment(value string) string {","path":"format/jsontoinflux10.go","position":100,"original_position":100,"commit_id":"f5abe27520906e69b1407be5f3748a198289826a","original_commit_id":"f5abe27520906e69b1407be5f3748a198289826a","user":{"login":"mre","id":175809,"avatar_url":"https://avatars1.githubusercontent.com/u/175809?v=3","gravatar_id":"","url":"https://api.github.com/users/mre","html_url":"https://github.com/mre","followers_url":"https://api.github.com/users/mre/followers","following_url":"https://api.github.com/users/mre/following{/other_user}","gists_url":"https://api.github.com/users/mre/gists{/gist_id}","starred_url":"https://api.github.com/users/mre/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mre/subscriptions","organizations_url":"https://api.github.com/users/mre/orgs","repos_url":"https://api.github.com/users/mre/repos","events_url":"https://api.github.com/users/mre/events{/privacy}","received_events_url":"https://api.github.com/users/mre/received_events","type":"User","site_admin":false},"body":"Clarified offline.\r\n`json.Unmarshal()` returns a `map[string]interface{}`, so I need to add a type assertion when calling `escape*`, for example `format.escapeMetadata(v.(string))`. (Note that `format.escapeMetadata(string(v))` does not work. It would result in an error: [\"cannot convert v (type interface{}) to type string: need type assertion\"](https://stackoverflow.com/a/14289568/270334))","created_at":"2017-07-10T11:14:44Z","updated_at":"2017-07-10T11:14:44Z","html_url":"https://github.com/trivago/gollum/pull/164#discussion_r126393034","pull_request_url":"https://api.github.com/repos/trivago/gollum/pulls/164","_links":{"self":{"href":"https://api.github.com/repos/trivago/gollum/pulls/comments/126393034"},"html":{"href":"https://github.com/trivago/gollum/pull/164#discussion_r126393034"},"pull_request":{"href":"https://api.github.com/repos/trivago/gollum/pulls/164"}}},"pull_request":{"url":"https://api.github.com/repos/trivago/gollum/pulls/164","id":129199922,"html_url":"https://github.com/trivago/gollum/pull/164","diff_url":"https://github.com/trivago/gollum/pull/164.diff","patch_url":"https://github.com/trivago/gollum/pull/164.patch","issue_url":"https://api.github.com/repos/trivago/gollum/issues/164","number":164,"state":"open","locked":false,"title":"JSON to InfluxDB support","user":{"login":"mre","id":175809,"avatar_url":"https://avatars1.githubusercontent.com/u/175809?v=3","gravatar_id":"","url":"https://api.github.com/users/mre","html_url":"https://github.com/mre","followers_url":"https://api.github.com/users/mre/followers","following_url":"https://api.github.com/users/mre/following{/other_user}","gists_url":"https://api.github.com/users/mre/gists{/gist_id}","starred_url":"https://api.github.com/users/mre/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mre/subscriptions","organizations_url":"https://api.github.com/users/mre/orgs","repos_url":"https://api.github.com/users/mre/repos","events_url":"https://api.github.com/users/mre/events{/privacy}","received_events_url":"https://api.github.com/users/mre/received_events","type":"User","site_admin":false},"body":"This PR adds support for convert arbitrary JSON payloads into the InfluxDB Line Protocol format.\r\nIt has similar functionality like the [logstash influxdb plugin](https://www.elastic.co/guide/en/logstash/current/plugins-outputs-influxdb.html). In combination with the grok formatter it makes migration from logstash to gollum much easier.\r\n\r\n#### Implementation details\r\n\r\nI tried using the new gollum config format for the plugin configuration.\r\nNamely, I added two struct tags, `config:\"Timefield\" default:\"time\"` and `config:\"Measurement\" default:\"measurement\"`.\r\nFor the two config options \"tags\" and \"ignore\" I used a custom hashmap which gets initialized inside the Configure method. This way we can do a fast hashmap lookup which significantly speeds up message parsing.","created_at":"2017-07-06T14:29:57Z","updated_at":"2017-07-10T11:14:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9dfab3ade8549ac0f6ffda45970f93d1249513ef","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":{"url":"https://api.github.com/repos/trivago/gollum/milestones/2","html_url":"https://github.com/trivago/gollum/milestone/2","labels_url":"https://api.github.com/repos/trivago/gollum/milestones/2/labels","id":1277204,"number":2,"title":"v0.5.0","description":"Next release containing breaking changes.\r\n\r\nThis release contains a new configuration format to pave the way for live config changes/reloading and eventually zero-downtime restarts. As this will introduce changes to existing plugins the main plugin architecture will be revamped, too.","creator":{"login":"arnecls","id":6131989,"avatar_url":"https://avatars1.githubusercontent.com/u/6131989?v=3","gravatar_id":"","url":"https://api.github.com/users/arnecls","html_url":"https://github.com/arnecls","followers_url":"https://api.github.com/users/arnecls/followers","following_url":"https://api.github.com/users/arnecls/following{/other_user}","gists_url":"https://api.github.com/users/arnecls/gists{/gist_id}","starred_url":"https://api.github.com/users/arnecls/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arnecls/subscriptions","organizations_url":"https://api.github.com/users/arnecls/orgs","repos_url":"https://api.github.com/users/arnecls/repos","events_url":"https://api.github.com/users/arnecls/events{/privacy}","received_events_url":"https://api.github.com/users/arnecls/received_events","type":"User","site_admin":false},"open_issues":5,"closed_issues":43,"state":"open","created_at":"2015-08-28T08:40:28Z","updated_at":"2017-07-10T08:45:32Z","due_on":"2017-07-31T07:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/trivago/gollum/pulls/164/commits","review_comments_url":"https://api.github.com/repos/trivago/gollum/pulls/164/comments","review_comment_url":"https://api.github.com/repos/trivago/gollum/pulls/comments{/number}","comments_url":"https://api.github.com/repos/trivago/gollum/issues/164/comments","statuses_url":"https://api.github.com/repos/trivago/gollum/statuses/f5abe27520906e69b1407be5f3748a198289826a","head":{"label":"mre:feature/json-to-influxdb-support","ref":"feature/json-to-influxdb-support","sha":"f5abe27520906e69b1407be5f3748a198289826a","user":{"login":"mre","id":175809,"avatar_url":"https://avatars1.githubusercontent.com/u/175809?v=3","gravatar_id":"","url":"https://api.github.com/users/mre","html_url":"https://github.com/mre","followers_url":"https://api.github.com/users/mre/followers","following_url":"https://api.github.com/users/mre/following{/other_user}","gists_url":"https://api.github.com/users/mre/gists{/gist_id}","starred_url":"https://api.github.com/users/mre/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mre/subscriptions","organizations_url":"https://api.github.com/users/mre/orgs","repos_url":"https://api.github.com/users/mre/repos","events_url":"https://api.github.com/users/mre/events{/privacy}","received_events_url":"https://api.github.com/users/mre/received_events","type":"User","site_admin":false},"repo":{"id":94088524,"name":"gollum","full_name":"mre/gollum","owner":{"login":"mre","id":175809,"avatar_url":"https://avatars1.githubusercontent.com/u/175809?v=3","gravatar_id":"","url":"https://api.github.com/users/mre","html_url":"https://github.com/mre","followers_url":"https://api.github.com/users/mre/followers","following_url":"https://api.github.com/users/mre/following{/other_user}","gists_url":"https://api.github.com/users/mre/gists{/gist_id}","starred_url":"https://api.github.com/users/mre/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mre/subscriptions","organizations_url":"https://api.github.com/users/mre/orgs","repos_url":"https://api.github.com/users/mre/repos","events_url":"https://api.github.com/users/mre/events{/privacy}","received_events_url":"https://api.github.com/users/mre/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mre/gollum","description":"An n:m message multiplexer written in Go","fork":true,"url":"https://api.github.com/repos/mre/gollum","forks_url":"https://api.github.com/repos/mre/gollum/forks","keys_url":"https://api.github.com/repos/mre/gollum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mre/gollum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mre/gollum/teams","hooks_url":"https://api.github.com/repos/mre/gollum/hooks","issue_events_url":"https://api.github.com/repos/mre/gollum/issues/events{/number}","events_url":"https://api.github.com/repos/mre/gollum/events","assignees_url":"https://api.github.com/repos/mre/gollum/assignees{/user}","branches_url":"https://api.github.com/repos/mre/gollum/branches{/branch}","tags_url":"https://api.github.com/repos/mre/gollum/tags","blobs_url":"https://api.github.com/repos/mre/gollum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mre/gollum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mre/gollum/git/refs{/sha}","trees_url":"https://api.github.com/repos/mre/gollum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mre/gollum/statuses/{sha}","languages_url":"https://api.github.com/repos/mre/gollum/languages","stargazers_url":"https://api.github.com/repos/mre/gollum/stargazers","contributors_url":"https://api.github.com/repos/mre/gollum/contributors","subscribers_url":"https://api.github.com/repos/mre/gollum/subscribers","subscription_url":"https://api.github.com/repos/mre/gollum/subscription","commits_url":"https://api.github.com/repos/mre/gollum/commits{/sha}","git_commits_url":"https://api.github.com/repos/mre/gollum/git/commits{/sha}","comments_url":"https://api.github.com/repos/mre/gollum/comments{/number}","issue_comment_url":"https://api.github.com/repos/mre/gollum/issues/comments{/number}","contents_url":"https://api.github.com/repos/mre/gollum/contents/{+path}","compare_url":"https://api.github.com/repos/mre/gollum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mre/gollum/merges","archive_url":"https://api.github.com/repos/mre/gollum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mre/gollum/downloads","issues_url":"https://api.github.com/repos/mre/gollum/issues{/number}","pulls_url":"https://api.github.com/repos/mre/gollum/pulls{/number}","milestones_url":"https://api.github.com/repos/mre/gollum/milestones{/number}","notifications_url":"https://api.github.com/repos/mre/gollum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mre/gollum/labels{/name}","releases_url":"https://api.github.com/repos/mre/gollum/releases{/id}","deployments_url":"https://api.github.com/repos/mre/gollum/deployments","created_at":"2017-06-12T11:27:41Z","updated_at":"2017-06-12T11:27:43Z","pushed_at":"2017-07-10T10:03:59Z","git_url":"git://github.com/mre/gollum.git","ssh_url":"git@github.com:mre/gollum.git","clone_url":"https://github.com/mre/gollum.git","svn_url":"https://github.com/mre/gollum","homepage":"http://gollum.readthedocs.org/en/latest/","size":20400,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"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":"trivago:master","ref":"master","sha":"40ecad7be7d51791e737f7078121336dc3555497","user":{"login":"trivago","id":1481788,"avatar_url":"https://avatars2.githubusercontent.com/u/1481788?v=3","gravatar_id":"","url":"https://api.github.com/users/trivago","html_url":"https://github.com/trivago","followers_url":"https://api.github.com/users/trivago/followers","following_url":"https://api.github.com/users/trivago/following{/other_user}","gists_url":"https://api.github.com/users/trivago/gists{/gist_id}","starred_url":"https://api.github.com/users/trivago/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trivago/subscriptions","organizations_url":"https://api.github.com/users/trivago/orgs","repos_url":"https://api.github.com/users/trivago/repos","events_url":"https://api.github.com/users/trivago/events{/privacy}","received_events_url":"https://api.github.com/users/trivago/received_events","type":"Organization","site_admin":false},"repo":{"id":37787279,"name":"gollum","full_name":"trivago/gollum","owner":{"login":"trivago","id":1481788,"avatar_url":"https://avatars2.githubusercontent.com/u/1481788?v=3","gravatar_id":"","url":"https://api.github.com/users/trivago","html_url":"https://github.com/trivago","followers_url":"https://api.github.com/users/trivago/followers","following_url":"https://api.github.com/users/trivago/following{/other_user}","gists_url":"https://api.github.com/users/trivago/gists{/gist_id}","starred_url":"https://api.github.com/users/trivago/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trivago/subscriptions","organizations_url":"https://api.github.com/users/trivago/orgs","repos_url":"https://api.github.com/users/trivago/repos","events_url":"https://api.github.com/users/trivago/events{/privacy}","received_events_url":"https://api.github.com/users/trivago/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/trivago/gollum","description":"An n:m message multiplexer written in Go","fork":false,"url":"https://api.github.com/repos/trivago/gollum","forks_url":"https://api.github.com/repos/trivago/gollum/forks","keys_url":"https://api.github.com/repos/trivago/gollum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/trivago/gollum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/trivago/gollum/teams","hooks_url":"https://api.github.com/repos/trivago/gollum/hooks","issue_events_url":"https://api.github.com/repos/trivago/gollum/issues/events{/number}","events_url":"https://api.github.com/repos/trivago/gollum/events","assignees_url":"https://api.github.com/repos/trivago/gollum/assignees{/user}","branches_url":"https://api.github.com/repos/trivago/gollum/branches{/branch}","tags_url":"https://api.github.com/repos/trivago/gollum/tags","blobs_url":"https://api.github.com/repos/trivago/gollum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/trivago/gollum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/trivago/gollum/git/refs{/sha}","trees_url":"https://api.github.com/repos/trivago/gollum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/trivago/gollum/statuses/{sha}","languages_url":"https://api.github.com/repos/trivago/gollum/languages","stargazers_url":"https://api.github.com/repos/trivago/gollum/stargazers","contributors_url":"https://api.github.com/repos/trivago/gollum/contributors","subscribers_url":"https://api.github.com/repos/trivago/gollum/subscribers","subscription_url":"https://api.github.com/repos/trivago/gollum/subscription","commits_url":"https://api.github.com/repos/trivago/gollum/commits{/sha}","git_commits_url":"https://api.github.com/repos/trivago/gollum/git/commits{/sha}","comments_url":"https://api.github.com/repos/trivago/gollum/comments{/number}","issue_comment_url":"https://api.github.com/repos/trivago/gollum/issues/comments{/number}","contents_url":"https://api.github.com/repos/trivago/gollum/contents/{+path}","compare_url":"https://api.github.com/repos/trivago/gollum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/trivago/gollum/merges","archive_url":"https://api.github.com/repos/trivago/gollum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/trivago/gollum/downloads","issues_url":"https://api.github.com/repos/trivago/gollum/issues{/number}","pulls_url":"https://api.github.com/repos/trivago/gollum/pulls{/number}","milestones_url":"https://api.github.com/repos/trivago/gollum/milestones{/number}","notifications_url":"https://api.github.com/repos/trivago/gollum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/trivago/gollum/labels{/name}","releases_url":"https://api.github.com/repos/trivago/gollum/releases{/id}","deployments_url":"https://api.github.com/repos/trivago/gollum/deployments","created_at":"2015-06-20T21:51:20Z","updated_at":"2017-07-05T05:58:35Z","pushed_at":"2017-07-10T10:15:34Z","git_url":"git://github.com/trivago/gollum.git","ssh_url":"git@github.com:trivago/gollum.git","clone_url":"https://github.com/trivago/gollum.git","svn_url":"https://github.com/trivago/gollum","homepage":"http://gollum.readthedocs.org/en/latest/","size":20459,"stargazers_count":543,"watchers_count":543,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":50,"mirror_url":null,"open_issues_count":21,"forks":50,"open_issues":21,"watchers":543,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/trivago/gollum/pulls/164"},"html":{"href":"https://github.com/trivago/gollum/pull/164"},"issue":{"href":"https://api.github.com/repos/trivago/gollum/issues/164"},"comments":{"href":"https://api.github.com/repos/trivago/gollum/issues/164/comments"},"review_comments":{"href":"https://api.github.com/repos/trivago/gollum/pulls/164/comments"},"review_comment":{"href":"https://api.github.com/repos/trivago/gollum/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/trivago/gollum/pulls/164/commits"},"statuses":{"href":"https://api.github.com/repos/trivago/gollum/statuses/f5abe27520906e69b1407be5f3748a198289826a"}}}}
{"actor":{"display_login":"mre"}}