{"action":"created","comment":{"url":"https://api.github.com/repos/opentable/sous/pulls/comments/168342831","pull_request_review_id":96694475,"id":168342831,"diff_hunk":"@@ -0,0 +1,259 @@\n+package messages\n+\n+import (\n+\t\"encoding/json\"\n+\t\"fmt\"\n+\t\"io\"\n+\t\"reflect\"\n+\t\"strings\"\n+\n+\t\"github.com/Jeffail/gabs\"\n+\t\"github.com/fatih/structs\"\n+\t\"github.com/opentable/sous/util/logging\"\n+)\n+\n+//InnerLogger interface is used if struct wants to provide it's own way of returns fields, types, and json string\n+type InnerLogger interface {\n+\tInnerLogInfo() (fields []string, types []string, jsonStruct string)\n+}\n+\n+func removeDuplicates(elements []string) []string {\n+\t// Use map to record duplicates as we find them.\n+\tencountered := map[string]bool{}\n+\tresult := []string{}\n+\n+\tfor v := range elements {\n+\t\t//don't include empty\n+\t\tif elements[v] == \"\" {\n+\t\t\tcontinue\n+\t\t}\n+\t\tif encountered[elements[v]] {\n+\t\t\t// Do not add duplicate.\n+\t\t} else {\n+\t\t\t// Record this element as an encountered element.\n+\t\t\tencountered[elements[v]] = true\n+\t\t\t// Append to result slice.\n+\t\t\tresult = append(result, elements[v])\n+\t\t}\n+\t}\n+\t// Return the new slice.\n+\treturn result\n+}\n+\n+func getType(myvar interface{}) string {\n+\tif myvar != nil {\n+\t\tvar t reflect.Type\n+\t\tif t = reflect.TypeOf(myvar); t.Kind() == reflect.Ptr {\n+\t\t\treturn \"*\" + t.Elem().Name()\n+\t\t}\n+\t\treturn t.Name()\n+\t}\n+\treturn \"\"\n+}\n+\n+func failedToParseJSON(name string) string {\n+\tjsonStruct := fmt.Sprintf(\"{\\\"%s\\\": \\\"Fail to create json\\\"}\", name)\n+\treturn jsonStruct\n+\n+}\n+\n+//DefaultStructInfo is the default implementation for structs to use to return fields, types, and jsonStruct\n+//It checks if the interface passed in implements InnerLogger and will use that instead\n+func defaultStructInfo(o interface{}) (fields []string, types []string, jsonStruct string) {\n+\n+\tif innerLog, ok := o.(InnerLogger); ok {\n+\t\tfields, types, jsonStruct = innerLog.InnerLogInfo()\n+\t\treturn\n+\t}\n+\tv := reflect.ValueOf(o)\n+\n+\t// if pointer get the underlying element≤\n+\tfor v.Kind() == reflect.Ptr {\n+\t\tv = v.Elem()\n+\t}\n+\n+\t//handle when it's not a struct\n+\tif v.Kind() != reflect.Struct {\n+\t\tfields = []string{}\n+\t\ttypes = []string{}\n+\t\toType := getType(o)\n+\t\ttypes = append(types, oType)\n+\t\tjsonObj := gabs.New()\n+\t\tif _, err := jsonObj.Set(o, oType, oType); err != nil {\n+\t\t\tjsonStruct = failedToParseJSON(oType)\n+\t\t} else {\n+\t\t\tjsonStruct = jsonObj.String()\n+\t\t}\n+\t\treturn\n+\t}\n+\n+\t//handle error interface explicitly to extract error msg\n+\tif anErr, ok := o.(error); ok {\n+\t\tfields = []string{}\n+\t\ttypes = []string{\"error\"}\n+\n+\t\tjsonObj := gabs.New()\n+\t\tif _, err := jsonObj.Set(anErr.Error(), \"error\", \"error\"); err != nil {\n+\t\t\tjsonStruct = failedToParseJSON(\"error\")\n+\t\t\treturn\n+\t\t}\n+\t\tjsonStruct = jsonObj.String()\n+\t\treturn\n+\t}\n+\ts := structs.New(o)\n+\n+\tfields = s.Names()\n+\tfields = append(fields, s.Name())\n+\ttypes = []string{}\n+\n+\ttypes = append(types, getType(o))\n+\n+\tfor _, f := range s.Fields() {\n+\t\tif f.IsExported() {\n+\t\t\ttypes = append(types, getType(f.Value()))\n+\t\t\tif f.Kind() == reflect.Struct {\n+\t\t\t\tinnerNames, innerTypes, _ := defaultStructInfo(f.Value())\n+\t\t\t\tfields = append(fields, innerNames...)\n+\t\t\t\ttypes = append(types, innerTypes...)\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tmapParent := structs.Map(o)\n+\tif mapB, err := json.Marshal(mapParent); err == nil {\n+\t\tjsonStruct = string(mapB)\n+\t} else {\n+\n+\t\tjsonObj := gabs.New()\n+\t\tif _, err := jsonObj.Set(fmt.Sprintf(\"%v\", mapParent), s.Name()); err != nil {\n+\t\t\tjsonStruct = failedToParseJSON(s.Name())\n+\t\t\treturn\n+\t\t}\n+\t\tjsonStruct = jsonObj.String()\n+\t}\n+\n+\treturn fields, types, jsonStruct\n+}\n+\n+type logFieldsMessage struct {\n+\tlogging.CallerInfo\n+\tlogging.Level\n+\tFields             []string\n+\tTypes              []string\n+\tJSONRepresentation string\n+\tjsonObj            *gabs.Container\n+\tmsg                string\n+\tconsole            bool\n+}\n+\n+func (l logFieldsMessage) WriteToConsole(console io.Writer) {\n+\tif l.console {\n+\t\tfmt.Fprintf(console, \"%s\\n\", l.composeMsg())\n+\t\tif l.jsonObj != nil {","path":"util/logging/messages/generalmsg.go","position":152,"original_position":152,"commit_id":"ba3518ee9289e726a748148ac3aeb04872d845a1","original_commit_id":"ba3518ee9289e726a748148ac3aeb04872d845a1","user":{"login":"lachlanh","id":1088601,"avatar_url":"https://avatars0.githubusercontent.com/u/1088601?v=4","gravatar_id":"","url":"https://api.github.com/users/lachlanh","html_url":"https://github.com/lachlanh","followers_url":"https://api.github.com/users/lachlanh/followers","following_url":"https://api.github.com/users/lachlanh/following{/other_user}","gists_url":"https://api.github.com/users/lachlanh/gists{/gist_id}","starred_url":"https://api.github.com/users/lachlanh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lachlanh/subscriptions","organizations_url":"https://api.github.com/users/lachlanh/orgs","repos_url":"https://api.github.com/users/lachlanh/repos","events_url":"https://api.github.com/users/lachlanh/events{/privacy}","received_events_url":"https://api.github.com/users/lachlanh/received_events","type":"User","site_admin":false},"body":"msg may be sufficient here, rest if for loglov3 purposes.","created_at":"2018-02-14T23:22:55Z","updated_at":"2018-02-14T23:22:55Z","html_url":"https://github.com/opentable/sous/pull/586#discussion_r168342831","pull_request_url":"https://api.github.com/repos/opentable/sous/pulls/586","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/opentable/sous/pulls/comments/168342831"},"html":{"href":"https://github.com/opentable/sous/pull/586#discussion_r168342831"},"pull_request":{"href":"https://api.github.com/repos/opentable/sous/pulls/586"}}},"pull_request":{"url":"https://api.github.com/repos/opentable/sous/pulls/586","id":168353705,"html_url":"https://github.com/opentable/sous/pull/586","diff_url":"https://github.com/opentable/sous/pull/586.diff","patch_url":"https://github.com/opentable/sous/pull/586.patch","issue_url":"https://api.github.com/repos/opentable/sous/issues/586","number":586,"state":"open","locked":false,"title":"sous-871 General Logger and example usage in image-mapping.go","user":{"login":"JC1738","id":3421783,"avatar_url":"https://avatars3.githubusercontent.com/u/3421783?v=4","gravatar_id":"","url":"https://api.github.com/users/JC1738","html_url":"https://github.com/JC1738","followers_url":"https://api.github.com/users/JC1738/followers","following_url":"https://api.github.com/users/JC1738/following{/other_user}","gists_url":"https://api.github.com/users/JC1738/gists{/gist_id}","starred_url":"https://api.github.com/users/JC1738/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JC1738/subscriptions","organizations_url":"https://api.github.com/users/JC1738/orgs","repos_url":"https://api.github.com/users/JC1738/repos","events_url":"https://api.github.com/users/JC1738/events{/privacy}","received_events_url":"https://api.github.com/users/JC1738/received_events","type":"User","site_admin":false},"body":"Implementing a semi-structured message","created_at":"2018-02-09T22:06:59Z","updated_at":"2018-02-14T23:22:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1b0a3994b4494698fe76e33f9021ce91e3cf0bc3","assignee":null,"assignees":[],"requested_reviewers":[{"login":"samsalisbury","id":111437,"avatar_url":"https://avatars1.githubusercontent.com/u/111437?v=4","gravatar_id":"","url":"https://api.github.com/users/samsalisbury","html_url":"https://github.com/samsalisbury","followers_url":"https://api.github.com/users/samsalisbury/followers","following_url":"https://api.github.com/users/samsalisbury/following{/other_user}","gists_url":"https://api.github.com/users/samsalisbury/gists{/gist_id}","starred_url":"https://api.github.com/users/samsalisbury/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samsalisbury/subscriptions","organizations_url":"https://api.github.com/users/samsalisbury/orgs","repos_url":"https://api.github.com/users/samsalisbury/repos","events_url":"https://api.github.com/users/samsalisbury/events{/privacy}","received_events_url":"https://api.github.com/users/samsalisbury/received_events","type":"User","site_admin":false},{"login":"nyarly","id":127548,"avatar_url":"https://avatars2.githubusercontent.com/u/127548?v=4","gravatar_id":"","url":"https://api.github.com/users/nyarly","html_url":"https://github.com/nyarly","followers_url":"https://api.github.com/users/nyarly/followers","following_url":"https://api.github.com/users/nyarly/following{/other_user}","gists_url":"https://api.github.com/users/nyarly/gists{/gist_id}","starred_url":"https://api.github.com/users/nyarly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nyarly/subscriptions","organizations_url":"https://api.github.com/users/nyarly/orgs","repos_url":"https://api.github.com/users/nyarly/repos","events_url":"https://api.github.com/users/nyarly/events{/privacy}","received_events_url":"https://api.github.com/users/nyarly/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/opentable/sous/pulls/586/commits","review_comments_url":"https://api.github.com/repos/opentable/sous/pulls/586/comments","review_comment_url":"https://api.github.com/repos/opentable/sous/pulls/comments{/number}","comments_url":"https://api.github.com/repos/opentable/sous/issues/586/comments","statuses_url":"https://api.github.com/repos/opentable/sous/statuses/ba3518ee9289e726a748148ac3aeb04872d845a1","head":{"label":"JC1738:SOUS-871","ref":"SOUS-871","sha":"ba3518ee9289e726a748148ac3aeb04872d845a1","user":{"login":"JC1738","id":3421783,"avatar_url":"https://avatars3.githubusercontent.com/u/3421783?v=4","gravatar_id":"","url":"https://api.github.com/users/JC1738","html_url":"https://github.com/JC1738","followers_url":"https://api.github.com/users/JC1738/followers","following_url":"https://api.github.com/users/JC1738/following{/other_user}","gists_url":"https://api.github.com/users/JC1738/gists{/gist_id}","starred_url":"https://api.github.com/users/JC1738/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JC1738/subscriptions","organizations_url":"https://api.github.com/users/JC1738/orgs","repos_url":"https://api.github.com/users/JC1738/repos","events_url":"https://api.github.com/users/JC1738/events{/privacy}","received_events_url":"https://api.github.com/users/JC1738/received_events","type":"User","site_admin":false},"repo":{"id":112507178,"name":"sous","full_name":"JC1738/sous","owner":{"login":"JC1738","id":3421783,"avatar_url":"https://avatars3.githubusercontent.com/u/3421783?v=4","gravatar_id":"","url":"https://api.github.com/users/JC1738","html_url":"https://github.com/JC1738","followers_url":"https://api.github.com/users/JC1738/followers","following_url":"https://api.github.com/users/JC1738/following{/other_user}","gists_url":"https://api.github.com/users/JC1738/gists{/gist_id}","starred_url":"https://api.github.com/users/JC1738/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JC1738/subscriptions","organizations_url":"https://api.github.com/users/JC1738/orgs","repos_url":"https://api.github.com/users/JC1738/repos","events_url":"https://api.github.com/users/JC1738/events{/privacy}","received_events_url":"https://api.github.com/users/JC1738/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/JC1738/sous","description":"Tools for building, testing, deploying Docker containers","fork":true,"url":"https://api.github.com/repos/JC1738/sous","forks_url":"https://api.github.com/repos/JC1738/sous/forks","keys_url":"https://api.github.com/repos/JC1738/sous/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JC1738/sous/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JC1738/sous/teams","hooks_url":"https://api.github.com/repos/JC1738/sous/hooks","issue_events_url":"https://api.github.com/repos/JC1738/sous/issues/events{/number}","events_url":"https://api.github.com/repos/JC1738/sous/events","assignees_url":"https://api.github.com/repos/JC1738/sous/assignees{/user}","branches_url":"https://api.github.com/repos/JC1738/sous/branches{/branch}","tags_url":"https://api.github.com/repos/JC1738/sous/tags","blobs_url":"https://api.github.com/repos/JC1738/sous/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JC1738/sous/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JC1738/sous/git/refs{/sha}","trees_url":"https://api.github.com/repos/JC1738/sous/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JC1738/sous/statuses/{sha}","languages_url":"https://api.github.com/repos/JC1738/sous/languages","stargazers_url":"https://api.github.com/repos/JC1738/sous/stargazers","contributors_url":"https://api.github.com/repos/JC1738/sous/contributors","subscribers_url":"https://api.github.com/repos/JC1738/sous/subscribers","subscription_url":"https://api.github.com/repos/JC1738/sous/subscription","commits_url":"https://api.github.com/repos/JC1738/sous/commits{/sha}","git_commits_url":"https://api.github.com/repos/JC1738/sous/git/commits{/sha}","comments_url":"https://api.github.com/repos/JC1738/sous/comments{/number}","issue_comment_url":"https://api.github.com/repos/JC1738/sous/issues/comments{/number}","contents_url":"https://api.github.com/repos/JC1738/sous/contents/{+path}","compare_url":"https://api.github.com/repos/JC1738/sous/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JC1738/sous/merges","archive_url":"https://api.github.com/repos/JC1738/sous/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JC1738/sous/downloads","issues_url":"https://api.github.com/repos/JC1738/sous/issues{/number}","pulls_url":"https://api.github.com/repos/JC1738/sous/pulls{/number}","milestones_url":"https://api.github.com/repos/JC1738/sous/milestones{/number}","notifications_url":"https://api.github.com/repos/JC1738/sous/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JC1738/sous/labels{/name}","releases_url":"https://api.github.com/repos/JC1738/sous/releases{/id}","deployments_url":"https://api.github.com/repos/JC1738/sous/deployments","created_at":"2017-11-29T17:36:12Z","updated_at":"2017-11-29T17:36:15Z","pushed_at":"2018-02-14T01:01:18Z","git_url":"git://github.com/JC1738/sous.git","ssh_url":"git@github.com:JC1738/sous.git","clone_url":"https://github.com/JC1738/sous.git","svn_url":"https://github.com/JC1738/sous","homepage":"","size":15535,"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,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"opentable:master","ref":"master","sha":"7093b67601677413ae5921908ea0c2368229f259","user":{"login":"opentable","id":2653541,"avatar_url":"https://avatars0.githubusercontent.com/u/2653541?v=4","gravatar_id":"","url":"https://api.github.com/users/opentable","html_url":"https://github.com/opentable","followers_url":"https://api.github.com/users/opentable/followers","following_url":"https://api.github.com/users/opentable/following{/other_user}","gists_url":"https://api.github.com/users/opentable/gists{/gist_id}","starred_url":"https://api.github.com/users/opentable/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opentable/subscriptions","organizations_url":"https://api.github.com/users/opentable/orgs","repos_url":"https://api.github.com/users/opentable/repos","events_url":"https://api.github.com/users/opentable/events{/privacy}","received_events_url":"https://api.github.com/users/opentable/received_events","type":"Organization","site_admin":false},"repo":{"id":43084873,"name":"sous","full_name":"opentable/sous","owner":{"login":"opentable","id":2653541,"avatar_url":"https://avatars0.githubusercontent.com/u/2653541?v=4","gravatar_id":"","url":"https://api.github.com/users/opentable","html_url":"https://github.com/opentable","followers_url":"https://api.github.com/users/opentable/followers","following_url":"https://api.github.com/users/opentable/following{/other_user}","gists_url":"https://api.github.com/users/opentable/gists{/gist_id}","starred_url":"https://api.github.com/users/opentable/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opentable/subscriptions","organizations_url":"https://api.github.com/users/opentable/orgs","repos_url":"https://api.github.com/users/opentable/repos","events_url":"https://api.github.com/users/opentable/events{/privacy}","received_events_url":"https://api.github.com/users/opentable/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/opentable/sous","description":"Tools for building, testing, deploying Docker containers","fork":false,"url":"https://api.github.com/repos/opentable/sous","forks_url":"https://api.github.com/repos/opentable/sous/forks","keys_url":"https://api.github.com/repos/opentable/sous/keys{/key_id}","collaborators_url":"https://api.github.com/repos/opentable/sous/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/opentable/sous/teams","hooks_url":"https://api.github.com/repos/opentable/sous/hooks","issue_events_url":"https://api.github.com/repos/opentable/sous/issues/events{/number}","events_url":"https://api.github.com/repos/opentable/sous/events","assignees_url":"https://api.github.com/repos/opentable/sous/assignees{/user}","branches_url":"https://api.github.com/repos/opentable/sous/branches{/branch}","tags_url":"https://api.github.com/repos/opentable/sous/tags","blobs_url":"https://api.github.com/repos/opentable/sous/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/opentable/sous/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/opentable/sous/git/refs{/sha}","trees_url":"https://api.github.com/repos/opentable/sous/git/trees{/sha}","statuses_url":"https://api.github.com/repos/opentable/sous/statuses/{sha}","languages_url":"https://api.github.com/repos/opentable/sous/languages","stargazers_url":"https://api.github.com/repos/opentable/sous/stargazers","contributors_url":"https://api.github.com/repos/opentable/sous/contributors","subscribers_url":"https://api.github.com/repos/opentable/sous/subscribers","subscription_url":"https://api.github.com/repos/opentable/sous/subscription","commits_url":"https://api.github.com/repos/opentable/sous/commits{/sha}","git_commits_url":"https://api.github.com/repos/opentable/sous/git/commits{/sha}","comments_url":"https://api.github.com/repos/opentable/sous/comments{/number}","issue_comment_url":"https://api.github.com/repos/opentable/sous/issues/comments{/number}","contents_url":"https://api.github.com/repos/opentable/sous/contents/{+path}","compare_url":"https://api.github.com/repos/opentable/sous/compare/{base}...{head}","merges_url":"https://api.github.com/repos/opentable/sous/merges","archive_url":"https://api.github.com/repos/opentable/sous/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/opentable/sous/downloads","issues_url":"https://api.github.com/repos/opentable/sous/issues{/number}","pulls_url":"https://api.github.com/repos/opentable/sous/pulls{/number}","milestones_url":"https://api.github.com/repos/opentable/sous/milestones{/number}","notifications_url":"https://api.github.com/repos/opentable/sous/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/opentable/sous/labels{/name}","releases_url":"https://api.github.com/repos/opentable/sous/releases{/id}","deployments_url":"https://api.github.com/repos/opentable/sous/deployments","created_at":"2015-09-24T18:22:46Z","updated_at":"2018-01-11T20:03:41Z","pushed_at":"2018-02-14T23:15:37Z","git_url":"git://github.com/opentable/sous.git","ssh_url":"git@github.com:opentable/sous.git","clone_url":"https://github.com/opentable/sous.git","svn_url":"https://github.com/opentable/sous","homepage":"","size":15036,"stargazers_count":43,"watchers_count":43,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":18,"mirror_url":null,"archived":false,"open_issues_count":4,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":18,"open_issues":4,"watchers":43,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/opentable/sous/pulls/586"},"html":{"href":"https://github.com/opentable/sous/pull/586"},"issue":{"href":"https://api.github.com/repos/opentable/sous/issues/586"},"comments":{"href":"https://api.github.com/repos/opentable/sous/issues/586/comments"},"review_comments":{"href":"https://api.github.com/repos/opentable/sous/pulls/586/comments"},"review_comment":{"href":"https://api.github.com/repos/opentable/sous/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/opentable/sous/pulls/586/commits"},"statuses":{"href":"https://api.github.com/repos/opentable/sous/statuses/ba3518ee9289e726a748148ac3aeb04872d845a1"}},"author_association":"OWNER"}}
{"actor":{"display_login":"lachlanh"}}