{"action":"created","comment":{"url":"https://api.github.com/repos/uber-go/zap/pulls/comments/73208407","id":73208407,"diff_hunk":"@@ -0,0 +1,226 @@\n+// Copyright (c) 2016 Uber Technologies, Inc.\n+//\n+// Permission is hereby granted, free of charge, to any person obtaining a copy\n+// of this software and associated documentation files (the \"Software\"), to deal\n+// in the Software without restriction, including without limitation the rights\n+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+// copies of the Software, and to permit persons to whom the Software is\n+// furnished to do so, subject to the following conditions:\n+//\n+// The above copyright notice and this permission notice shall be included in\n+// all copies or substantial portions of the Software.\n+//\n+// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+// THE SOFTWARE.\n+\n+package zap\n+\n+import (\n+\t\"fmt\"\n+\t\"io\"\n+\t\"math\"\n+\t\"strconv\"\n+\t\"sync\"\n+\t\"time\"\n+)\n+\n+var textPool = sync.Pool{New: func() interface{} {\n+\treturn &textEncoder{\n+\t\tbytes: make([]byte, 0, _initialBufSize),\n+\t}\n+}}\n+\n+type textEncoder struct {\n+\tbytes   []byte\n+\ttimeFmt string\n+}\n+\n+// NewTextEncoder creates a line-oriented text encoder whose output is optimized\n+// for human, rather than machine, consumption. By default, the encoder uses\n+// RFC3339-formatted timestamps.\n+func NewTextEncoder(options ...TextOption) Encoder {\n+\tenc := textPool.Get().(*textEncoder)\n+\tenc.truncate()\n+\tenc.timeFmt = time.RFC3339\n+\tfor _, opt := range options {\n+\t\topt.apply(enc)\n+\t}\n+\treturn enc\n+}\n+\n+func (enc *textEncoder) Free() {\n+\ttextPool.Put(enc)\n+}\n+\n+func (enc *textEncoder) AddString(key, val string) {\n+\tenc.addKey(key)\n+\tenc.bytes = append(enc.bytes, val...)\n+}\n+\n+func (enc *textEncoder) AddBool(key string, val bool) {\n+\tenc.addKey(key)\n+\tif val {\n+\t\tenc.bytes = append(enc.bytes, \"true\"...)\n+\t\treturn\n+\t}\n+\tenc.bytes = append(enc.bytes, \"false\"...)\n+}\n+\n+func (enc *textEncoder) AddInt(key string, val int) {\n+\tenc.AddInt64(key, int64(val))\n+}\n+\n+func (enc *textEncoder) AddInt64(key string, val int64) {\n+\tenc.addKey(key)\n+\tenc.bytes = strconv.AppendInt(enc.bytes, val, 10)\n+}\n+\n+// TODO: uncomment once #116 lands.\n+// func (enc *textEncoder) AddUint(key string, val uint) {\n+// \tenc.AddUint64(key, uint64(val))\n+// }\n+\n+// func (enc *textEncoder) AddUint64(key string, val uint64) {\n+// \tenc.addKey(key)\n+// \tenc.bytes = strconv.AppendUint(enc.bytes, val, 10)\n+// }\n+\n+func (enc *textEncoder) AddFloat64(key string, val float64) {\n+\tenc.addKey(key)\n+\tswitch {\n+\tcase math.IsNaN(val):\n+\t\tenc.bytes = append(enc.bytes, \"NaN\"...)\n+\tcase math.IsInf(val, 1):\n+\t\tenc.bytes = append(enc.bytes, \"+Inf\"...)\n+\tcase math.IsInf(val, -1):\n+\t\tenc.bytes = append(enc.bytes, \"-Inf\"...)\n+\tdefault:\n+\t\tenc.bytes = strconv.AppendFloat(enc.bytes, val, 'f', -1, 64)\n+\t}\n+}\n+\n+func (enc *textEncoder) AddMarshaler(key string, obj LogMarshaler) error {\n+\tenc.addKey(key)\n+\tenc.bytes = append(enc.bytes, '{')\n+\terr := obj.MarshalLog(enc)\n+\tenc.bytes = append(enc.bytes, '}')\n+\treturn err\n+}\n+\n+func (enc *textEncoder) AddObject(key string, obj interface{}) error {\n+\tenc.AddString(key, fmt.Sprintf(\"%+v\", obj))\n+\treturn nil\n+}\n+\n+func (enc *textEncoder) Clone() Encoder {\n+\tclone := textPool.Get().(*textEncoder)\n+\tclone.truncate()\n+\tclone.bytes = append(clone.bytes, enc.bytes...)\n+\tclone.timeFmt = enc.timeFmt\n+\treturn clone\n+}\n+\n+func (enc *textEncoder) WriteEntry(sink io.Writer, msg string, lvl Level, t time.Time) error {\n+\tif sink == nil {\n+\t\treturn errNilSink\n+\t}\n+\n+\tfinal := textPool.Get().(*textEncoder)\n+\tfinal.truncate()\n+\tenc.addLevel(final, lvl)\n+\tenc.addTime(final, t)\n+\tenc.addMessage(final, msg)\n+\n+\tif len(enc.bytes) > 0 {\n+\t\tfinal.bytes = append(final.bytes, ' ')\n+\t\tfinal.bytes = append(final.bytes, enc.bytes...)\n+\t}\n+\tfinal.bytes = append(final.bytes, '\\n')\n+\n+\texpectedBytes := len(final.bytes)\n+\tn, err := sink.Write(final.bytes)\n+\tfinal.Free()\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tif n != expectedBytes {\n+\t\treturn fmt.Errorf(\"incomplete write: only wrote %v of %v bytes\", n, expectedBytes)\n+\t}\n+\treturn nil\n+}\n+\n+func (enc *textEncoder) truncate() {\n+\tenc.bytes = enc.bytes[:0]\n+}\n+\n+func (enc *textEncoder) addKey(key string) {\n+\tlastIdx := len(enc.bytes) - 1\n+\tif lastIdx >= 0 && enc.bytes[lastIdx] != '{' {","path":"text_encoder.go","position":163,"original_position":163,"commit_id":"719472635c09ba3181377f2c1ca0b014cc532372","original_commit_id":"719472635c09ba3181377f2c1ca0b014cc532372","user":{"login":"prashantv","id":140159,"avatar_url":"https://avatars.githubusercontent.com/u/140159?v=3","gravatar_id":"","url":"https://api.github.com/users/prashantv","html_url":"https://github.com/prashantv","followers_url":"https://api.github.com/users/prashantv/followers","following_url":"https://api.github.com/users/prashantv/following{/other_user}","gists_url":"https://api.github.com/users/prashantv/gists{/gist_id}","starred_url":"https://api.github.com/users/prashantv/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prashantv/subscriptions","organizations_url":"https://api.github.com/users/prashantv/orgs","repos_url":"https://api.github.com/users/prashantv/repos","events_url":"https://api.github.com/users/prashantv/events{/privacy}","received_events_url":"https://api.github.com/users/prashantv/received_events","type":"User","site_admin":false},"body":"This seems hacky and incorrect.\r\n\r\nE.g., if I do `addString(\"key\", \"{\")` then the value in `bytes` is `key={` and this will check the last byte, see that it's `{`, and drop the space.\r\n\r\nUse a separate bool to track state, and suggest adding failing tests as well.","created_at":"2016-08-02T18:17:54Z","updated_at":"2016-08-02T18:17:54Z","html_url":"https://github.com/uber-go/zap/pull/123#discussion_r73208407","pull_request_url":"https://api.github.com/repos/uber-go/zap/pulls/123","_links":{"self":{"href":"https://api.github.com/repos/uber-go/zap/pulls/comments/73208407"},"html":{"href":"https://github.com/uber-go/zap/pull/123#discussion_r73208407"},"pull_request":{"href":"https://api.github.com/repos/uber-go/zap/pulls/123"}}},"pull_request":{"url":"https://api.github.com/repos/uber-go/zap/pulls/123","id":79774880,"html_url":"https://github.com/uber-go/zap/pull/123","diff_url":"https://github.com/uber-go/zap/pull/123.diff","patch_url":"https://github.com/uber-go/zap/pull/123.patch","issue_url":"https://api.github.com/repos/uber-go/zap/issues/123","number":123,"state":"open","locked":false,"title":"Add a human-optimized text encoder","user":{"login":"akshayjshah","id":972790,"avatar_url":"https://avatars.githubusercontent.com/u/972790?v=3","gravatar_id":"","url":"https://api.github.com/users/akshayjshah","html_url":"https://github.com/akshayjshah","followers_url":"https://api.github.com/users/akshayjshah/followers","following_url":"https://api.github.com/users/akshayjshah/following{/other_user}","gists_url":"https://api.github.com/users/akshayjshah/gists{/gist_id}","starred_url":"https://api.github.com/users/akshayjshah/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akshayjshah/subscriptions","organizations_url":"https://api.github.com/users/akshayjshah/orgs","repos_url":"https://api.github.com/users/akshayjshah/repos","events_url":"https://api.github.com/users/akshayjshah/events{/privacy}","received_events_url":"https://api.github.com/users/akshayjshah/received_events","type":"User","site_admin":false},"body":"Add a text encoder that's friendlier for human consumption. By default, the `TextEncoder` output looks like this:\r\n\r\n```\r\n[I] 1970-01-01T00:00:00Z Something happened. foo=bar baz=bing\r\n```\r\n\r\nThe timestamp format is configurable via functional options, and the encoder includes support for unsigned ints (in advance of #116).\r\n\r\nResolves #59.","created_at":"2016-08-02T17:24:19Z","updated_at":"2016-08-02T18:17:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"81737f8fc2c41199edbd67437fa5cca57e14724c","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/uber-go/zap/pulls/123/commits","review_comments_url":"https://api.github.com/repos/uber-go/zap/pulls/123/comments","review_comment_url":"https://api.github.com/repos/uber-go/zap/pulls/comments{/number}","comments_url":"https://api.github.com/repos/uber-go/zap/issues/123/comments","statuses_url":"https://api.github.com/repos/uber-go/zap/statuses/719472635c09ba3181377f2c1ca0b014cc532372","head":{"label":"uber-go:ajs-text","ref":"ajs-text","sha":"719472635c09ba3181377f2c1ca0b014cc532372","user":{"login":"uber-go","id":19262598,"avatar_url":"https://avatars.githubusercontent.com/u/19262598?v=3","gravatar_id":"","url":"https://api.github.com/users/uber-go","html_url":"https://github.com/uber-go","followers_url":"https://api.github.com/users/uber-go/followers","following_url":"https://api.github.com/users/uber-go/following{/other_user}","gists_url":"https://api.github.com/users/uber-go/gists{/gist_id}","starred_url":"https://api.github.com/users/uber-go/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber-go/subscriptions","organizations_url":"https://api.github.com/users/uber-go/orgs","repos_url":"https://api.github.com/users/uber-go/repos","events_url":"https://api.github.com/users/uber-go/events{/privacy}","received_events_url":"https://api.github.com/users/uber-go/received_events","type":"Organization","site_admin":false},"repo":{"id":52034309,"name":"zap","full_name":"uber-go/zap","owner":{"login":"uber-go","id":19262598,"avatar_url":"https://avatars.githubusercontent.com/u/19262598?v=3","gravatar_id":"","url":"https://api.github.com/users/uber-go","html_url":"https://github.com/uber-go","followers_url":"https://api.github.com/users/uber-go/followers","following_url":"https://api.github.com/users/uber-go/following{/other_user}","gists_url":"https://api.github.com/users/uber-go/gists{/gist_id}","starred_url":"https://api.github.com/users/uber-go/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber-go/subscriptions","organizations_url":"https://api.github.com/users/uber-go/orgs","repos_url":"https://api.github.com/users/uber-go/repos","events_url":"https://api.github.com/users/uber-go/events{/privacy}","received_events_url":"https://api.github.com/users/uber-go/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/uber-go/zap","description":"Fast, structured, leveled logging in Go","fork":false,"url":"https://api.github.com/repos/uber-go/zap","forks_url":"https://api.github.com/repos/uber-go/zap/forks","keys_url":"https://api.github.com/repos/uber-go/zap/keys{/key_id}","collaborators_url":"https://api.github.com/repos/uber-go/zap/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/uber-go/zap/teams","hooks_url":"https://api.github.com/repos/uber-go/zap/hooks","issue_events_url":"https://api.github.com/repos/uber-go/zap/issues/events{/number}","events_url":"https://api.github.com/repos/uber-go/zap/events","assignees_url":"https://api.github.com/repos/uber-go/zap/assignees{/user}","branches_url":"https://api.github.com/repos/uber-go/zap/branches{/branch}","tags_url":"https://api.github.com/repos/uber-go/zap/tags","blobs_url":"https://api.github.com/repos/uber-go/zap/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/uber-go/zap/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/uber-go/zap/git/refs{/sha}","trees_url":"https://api.github.com/repos/uber-go/zap/git/trees{/sha}","statuses_url":"https://api.github.com/repos/uber-go/zap/statuses/{sha}","languages_url":"https://api.github.com/repos/uber-go/zap/languages","stargazers_url":"https://api.github.com/repos/uber-go/zap/stargazers","contributors_url":"https://api.github.com/repos/uber-go/zap/contributors","subscribers_url":"https://api.github.com/repos/uber-go/zap/subscribers","subscription_url":"https://api.github.com/repos/uber-go/zap/subscription","commits_url":"https://api.github.com/repos/uber-go/zap/commits{/sha}","git_commits_url":"https://api.github.com/repos/uber-go/zap/git/commits{/sha}","comments_url":"https://api.github.com/repos/uber-go/zap/comments{/number}","issue_comment_url":"https://api.github.com/repos/uber-go/zap/issues/comments{/number}","contents_url":"https://api.github.com/repos/uber-go/zap/contents/{+path}","compare_url":"https://api.github.com/repos/uber-go/zap/compare/{base}...{head}","merges_url":"https://api.github.com/repos/uber-go/zap/merges","archive_url":"https://api.github.com/repos/uber-go/zap/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/uber-go/zap/downloads","issues_url":"https://api.github.com/repos/uber-go/zap/issues{/number}","pulls_url":"https://api.github.com/repos/uber-go/zap/pulls{/number}","milestones_url":"https://api.github.com/repos/uber-go/zap/milestones{/number}","notifications_url":"https://api.github.com/repos/uber-go/zap/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/uber-go/zap/labels{/name}","releases_url":"https://api.github.com/repos/uber-go/zap/releases{/id}","deployments_url":"https://api.github.com/repos/uber-go/zap/deployments","created_at":"2016-02-18T19:52:56Z","updated_at":"2016-08-02T09:00:42Z","pushed_at":"2016-08-02T17:44:58Z","git_url":"git://github.com/uber-go/zap.git","ssh_url":"git@github.com:uber-go/zap.git","clone_url":"https://github.com/uber-go/zap.git","svn_url":"https://github.com/uber-go/zap","homepage":"https://godoc.org/github.com/uber-go/zap","size":377,"stargazers_count":1068,"watchers_count":1068,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":48,"mirror_url":null,"open_issues_count":13,"forks":48,"open_issues":13,"watchers":1068,"default_branch":"master"}},"base":{"label":"uber-go:master","ref":"master","sha":"855f968676a7e1b788f7d85113e27a26e351d0e9","user":{"login":"uber-go","id":19262598,"avatar_url":"https://avatars.githubusercontent.com/u/19262598?v=3","gravatar_id":"","url":"https://api.github.com/users/uber-go","html_url":"https://github.com/uber-go","followers_url":"https://api.github.com/users/uber-go/followers","following_url":"https://api.github.com/users/uber-go/following{/other_user}","gists_url":"https://api.github.com/users/uber-go/gists{/gist_id}","starred_url":"https://api.github.com/users/uber-go/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber-go/subscriptions","organizations_url":"https://api.github.com/users/uber-go/orgs","repos_url":"https://api.github.com/users/uber-go/repos","events_url":"https://api.github.com/users/uber-go/events{/privacy}","received_events_url":"https://api.github.com/users/uber-go/received_events","type":"Organization","site_admin":false},"repo":{"id":52034309,"name":"zap","full_name":"uber-go/zap","owner":{"login":"uber-go","id":19262598,"avatar_url":"https://avatars.githubusercontent.com/u/19262598?v=3","gravatar_id":"","url":"https://api.github.com/users/uber-go","html_url":"https://github.com/uber-go","followers_url":"https://api.github.com/users/uber-go/followers","following_url":"https://api.github.com/users/uber-go/following{/other_user}","gists_url":"https://api.github.com/users/uber-go/gists{/gist_id}","starred_url":"https://api.github.com/users/uber-go/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber-go/subscriptions","organizations_url":"https://api.github.com/users/uber-go/orgs","repos_url":"https://api.github.com/users/uber-go/repos","events_url":"https://api.github.com/users/uber-go/events{/privacy}","received_events_url":"https://api.github.com/users/uber-go/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/uber-go/zap","description":"Fast, structured, leveled logging in Go","fork":false,"url":"https://api.github.com/repos/uber-go/zap","forks_url":"https://api.github.com/repos/uber-go/zap/forks","keys_url":"https://api.github.com/repos/uber-go/zap/keys{/key_id}","collaborators_url":"https://api.github.com/repos/uber-go/zap/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/uber-go/zap/teams","hooks_url":"https://api.github.com/repos/uber-go/zap/hooks","issue_events_url":"https://api.github.com/repos/uber-go/zap/issues/events{/number}","events_url":"https://api.github.com/repos/uber-go/zap/events","assignees_url":"https://api.github.com/repos/uber-go/zap/assignees{/user}","branches_url":"https://api.github.com/repos/uber-go/zap/branches{/branch}","tags_url":"https://api.github.com/repos/uber-go/zap/tags","blobs_url":"https://api.github.com/repos/uber-go/zap/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/uber-go/zap/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/uber-go/zap/git/refs{/sha}","trees_url":"https://api.github.com/repos/uber-go/zap/git/trees{/sha}","statuses_url":"https://api.github.com/repos/uber-go/zap/statuses/{sha}","languages_url":"https://api.github.com/repos/uber-go/zap/languages","stargazers_url":"https://api.github.com/repos/uber-go/zap/stargazers","contributors_url":"https://api.github.com/repos/uber-go/zap/contributors","subscribers_url":"https://api.github.com/repos/uber-go/zap/subscribers","subscription_url":"https://api.github.com/repos/uber-go/zap/subscription","commits_url":"https://api.github.com/repos/uber-go/zap/commits{/sha}","git_commits_url":"https://api.github.com/repos/uber-go/zap/git/commits{/sha}","comments_url":"https://api.github.com/repos/uber-go/zap/comments{/number}","issue_comment_url":"https://api.github.com/repos/uber-go/zap/issues/comments{/number}","contents_url":"https://api.github.com/repos/uber-go/zap/contents/{+path}","compare_url":"https://api.github.com/repos/uber-go/zap/compare/{base}...{head}","merges_url":"https://api.github.com/repos/uber-go/zap/merges","archive_url":"https://api.github.com/repos/uber-go/zap/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/uber-go/zap/downloads","issues_url":"https://api.github.com/repos/uber-go/zap/issues{/number}","pulls_url":"https://api.github.com/repos/uber-go/zap/pulls{/number}","milestones_url":"https://api.github.com/repos/uber-go/zap/milestones{/number}","notifications_url":"https://api.github.com/repos/uber-go/zap/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/uber-go/zap/labels{/name}","releases_url":"https://api.github.com/repos/uber-go/zap/releases{/id}","deployments_url":"https://api.github.com/repos/uber-go/zap/deployments","created_at":"2016-02-18T19:52:56Z","updated_at":"2016-08-02T09:00:42Z","pushed_at":"2016-08-02T17:44:58Z","git_url":"git://github.com/uber-go/zap.git","ssh_url":"git@github.com:uber-go/zap.git","clone_url":"https://github.com/uber-go/zap.git","svn_url":"https://github.com/uber-go/zap","homepage":"https://godoc.org/github.com/uber-go/zap","size":377,"stargazers_count":1068,"watchers_count":1068,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":48,"mirror_url":null,"open_issues_count":13,"forks":48,"open_issues":13,"watchers":1068,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/uber-go/zap/pulls/123"},"html":{"href":"https://github.com/uber-go/zap/pull/123"},"issue":{"href":"https://api.github.com/repos/uber-go/zap/issues/123"},"comments":{"href":"https://api.github.com/repos/uber-go/zap/issues/123/comments"},"review_comments":{"href":"https://api.github.com/repos/uber-go/zap/pulls/123/comments"},"review_comment":{"href":"https://api.github.com/repos/uber-go/zap/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/uber-go/zap/pulls/123/commits"},"statuses":{"href":"https://api.github.com/repos/uber-go/zap/statuses/719472635c09ba3181377f2c1ca0b014cc532372"}}}}
{"actor":{"display_login":"prashantv"}}