{"action":"created","comment":{"url":"https://api.github.com/repos/line/armeria/pulls/comments/51692478","id":51692478,"diff_hunk":"@@ -0,0 +1,76 @@\n+/*\n+ * Copyright 2016 LINE Corporation\n+ *\n+ * LINE Corporation licenses this file to you under the Apache License,\n+ * version 2.0 (the \"License\"); you may not use this file except in compliance\n+ * with the License. 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, WITHOUT\n+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n+ * License for the specific language governing permissions and limitations\n+ * under the License.\n+ */\n+\n+package com.linecorp.armeria.common.util;\n+\n+import java.io.IOException;\n+import java.nio.channels.ClosedChannelException;\n+import java.util.regex.Pattern;\n+\n+import org.slf4j.Logger;\n+\n+import com.linecorp.armeria.client.ClosedSessionException;\n+\n+import io.netty.channel.Channel;\n+import io.netty.channel.ChannelException;\n+import io.netty.handler.codec.http2.Http2Exception;\n+\n+public final class Exceptions {\n+\n+    private static final Pattern IGNORABLE_SOCKET_ERROR_MESSAGE = Pattern.compile(\n+            \"(?:connection.*(?:reset|closed|abort|broken)|broken.*pipe)\", Pattern.CASE_INSENSITIVE);\n+\n+    private static final Pattern IGNORABLE_HTTP2_ERROR_MESSAGE = Pattern.compile(\n+            \"(?:stream closed)\", Pattern.CASE_INSENSITIVE);\n+\n+\n+    public static void log(Logger logger, Channel ch, Throwable cause) {\n+        if (!logger.isWarnEnabled()) {\n+            return;\n+        }\n+\n+        if (needsAttention(cause)) {\n+            logger.warn(\"{} Unexpected exception:\", ch, cause);\n+        }\n+    }\n+\n+    public static boolean needsAttention(Throwable cause) {","path":"src/main/java/com/linecorp/armeria/common/util/Exceptions.java","position":50,"original_position":50,"commit_id":"15bea485986ae5657a8888d6e6c73771fa1f4f7b","original_commit_id":"11db90d3de142e349c7081be66a881d371042db0","user":{"login":"trustin","id":173918,"avatar_url":"https://avatars.githubusercontent.com/u/173918?v=3","gravatar_id":"","url":"https://api.github.com/users/trustin","html_url":"https://github.com/trustin","followers_url":"https://api.github.com/users/trustin/followers","following_url":"https://api.github.com/users/trustin/following{/other_user}","gists_url":"https://api.github.com/users/trustin/gists{/gist_id}","starred_url":"https://api.github.com/users/trustin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trustin/subscriptions","organizations_url":"https://api.github.com/users/trustin/orgs","repos_url":"https://api.github.com/users/trustin/repos","events_url":"https://api.github.com/users/trustin/events{/privacy}","received_events_url":"https://api.github.com/users/trustin/received_events","type":"User","site_admin":false},"body":"Will rename as suggested (`isExpected()` and `logIfUnexpected()`) and add Javadoc I forgot.","created_at":"2016-02-03T08:46:05Z","updated_at":"2016-02-03T08:46:05Z","html_url":"https://github.com/line/armeria/pull/105#discussion_r51692478","pull_request_url":"https://api.github.com/repos/line/armeria/pulls/105","_links":{"self":{"href":"https://api.github.com/repos/line/armeria/pulls/comments/51692478"},"html":{"href":"https://github.com/line/armeria/pull/105#discussion_r51692478"},"pull_request":{"href":"https://api.github.com/repos/line/armeria/pulls/105"}}},"pull_request":{"url":"https://api.github.com/repos/line/armeria/pulls/105","id":58104844,"html_url":"https://github.com/line/armeria/pull/105","diff_url":"https://github.com/line/armeria/pull/105.diff","patch_url":"https://github.com/line/armeria/pull/105.patch","issue_url":"https://api.github.com/repos/line/armeria/issues/105","number":105,"state":"open","locked":false,"title":"Reduce the unnecessarily noisy/long exceptions","user":{"login":"trustin","id":173918,"avatar_url":"https://avatars.githubusercontent.com/u/173918?v=3","gravatar_id":"","url":"https://api.github.com/users/trustin","html_url":"https://github.com/trustin","followers_url":"https://api.github.com/users/trustin/followers","following_url":"https://api.github.com/users/trustin/following{/other_user}","gists_url":"https://api.github.com/users/trustin/gists{/gist_id}","starred_url":"https://api.github.com/users/trustin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trustin/subscriptions","organizations_url":"https://api.github.com/users/trustin/orgs","repos_url":"https://api.github.com/users/trustin/repos","events_url":"https://api.github.com/users/trustin/events{/privacy}","received_events_url":"https://api.github.com/users/trustin/received_events","type":"User","site_admin":false},"body":"Motivation:\r\n\r\nWhen Armeria is under heavy load that it cannot keep up with, exceptions\r\nwill be triggered, and some of them do not really need logging.\r\n\r\nHere's the list of the exceptions which are triggered very usually in\r\ncase of socket disconnection due to timeout / connection reset by peer\r\nerrors:\r\n\r\n- IOException: connection reset by peer / broken pipe\r\n- Http2Exception$StreamException: Stream closed\r\n- ClosedChannelException\r\n- ClosedSessionException\r\n\r\nAlso, an attempt to close a HTTP/2 connection with pending writes can\r\ncause unnecessarily long stack trace because of the following steps they\r\ninvolve:\r\n\r\n1. Channel.close() triggers AbstractHttpToHttp2ConnectionHandler.close().\r\n2. AbstractHttpToHttp2ConnectionHandler.close() triggers Http2Stream.close().\r\n3. Http2Stream.close() fails the promise of its pending writes.\r\n4. The failed promise notifies HttpServerHandler.CLOSE_ON_FAILURE.\r\n5. HttpServerHandler.CLOSE_ON_FAILURE calls Channel.close().\r\n6. Repeat from the step 1.\r\n\r\nMore the pending writes, longer the stack trace.\r\n\r\nModifications:\r\n\r\n- Add Exceptions, a utility class that filters out the exceptions\r\n  mentioned above\r\n  - Use Exceptions in ServiceInvocationContext and ChannelHandler\r\n    implementations to reduce the amount of noisy log messages\r\n- Do not call Channel.close() if HttpToHttp2Connection.close() has been\r\n  invoked already or the Channel has been closed already\r\n\r\nResult:\r\n\r\n- Much less noise when Armeria server is overloaded\r\n- The bad call cycle that was cause unnecessarily long stack trace is gone.","created_at":"2016-02-03T08:24:03Z","updated_at":"2016-02-03T08:46:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3a8828daa18786e6c0722fc6a0a8b25d48bb46c4","assignee":{"login":"anuraaga","id":198344,"avatar_url":"https://avatars.githubusercontent.com/u/198344?v=3","gravatar_id":"","url":"https://api.github.com/users/anuraaga","html_url":"https://github.com/anuraaga","followers_url":"https://api.github.com/users/anuraaga/followers","following_url":"https://api.github.com/users/anuraaga/following{/other_user}","gists_url":"https://api.github.com/users/anuraaga/gists{/gist_id}","starred_url":"https://api.github.com/users/anuraaga/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/anuraaga/subscriptions","organizations_url":"https://api.github.com/users/anuraaga/orgs","repos_url":"https://api.github.com/users/anuraaga/repos","events_url":"https://api.github.com/users/anuraaga/events{/privacy}","received_events_url":"https://api.github.com/users/anuraaga/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/line/armeria/milestones/11","html_url":"https://github.com/line/armeria/milestones/0.9.0.Final","labels_url":"https://api.github.com/repos/line/armeria/milestones/11/labels","id":1540902,"number":11,"title":"0.9.0.Final","description":null,"creator":{"login":"trustin","id":173918,"avatar_url":"https://avatars.githubusercontent.com/u/173918?v=3","gravatar_id":"","url":"https://api.github.com/users/trustin","html_url":"https://github.com/trustin","followers_url":"https://api.github.com/users/trustin/followers","following_url":"https://api.github.com/users/trustin/following{/other_user}","gists_url":"https://api.github.com/users/trustin/gists{/gist_id}","starred_url":"https://api.github.com/users/trustin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trustin/subscriptions","organizations_url":"https://api.github.com/users/trustin/orgs","repos_url":"https://api.github.com/users/trustin/repos","events_url":"https://api.github.com/users/trustin/events{/privacy}","received_events_url":"https://api.github.com/users/trustin/received_events","type":"User","site_admin":false},"open_issues":15,"closed_issues":7,"state":"open","created_at":"2016-01-25T09:28:12Z","updated_at":"2016-02-03T08:24:03Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/line/armeria/pulls/105/commits","review_comments_url":"https://api.github.com/repos/line/armeria/pulls/105/comments","review_comment_url":"https://api.github.com/repos/line/armeria/pulls/comments{/number}","comments_url":"https://api.github.com/repos/line/armeria/issues/105/comments","statuses_url":"https://api.github.com/repos/line/armeria/statuses/15bea485986ae5657a8888d6e6c73771fa1f4f7b","head":{"label":"trustin:less_noisy_exceptions","ref":"less_noisy_exceptions","sha":"15bea485986ae5657a8888d6e6c73771fa1f4f7b","user":{"login":"trustin","id":173918,"avatar_url":"https://avatars.githubusercontent.com/u/173918?v=3","gravatar_id":"","url":"https://api.github.com/users/trustin","html_url":"https://github.com/trustin","followers_url":"https://api.github.com/users/trustin/followers","following_url":"https://api.github.com/users/trustin/following{/other_user}","gists_url":"https://api.github.com/users/trustin/gists{/gist_id}","starred_url":"https://api.github.com/users/trustin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trustin/subscriptions","organizations_url":"https://api.github.com/users/trustin/orgs","repos_url":"https://api.github.com/users/trustin/repos","events_url":"https://api.github.com/users/trustin/events{/privacy}","received_events_url":"https://api.github.com/users/trustin/received_events","type":"User","site_admin":false},"repo":{"id":46322160,"name":"armeria","full_name":"trustin/armeria","owner":{"login":"trustin","id":173918,"avatar_url":"https://avatars.githubusercontent.com/u/173918?v=3","gravatar_id":"","url":"https://api.github.com/users/trustin","html_url":"https://github.com/trustin","followers_url":"https://api.github.com/users/trustin/followers","following_url":"https://api.github.com/users/trustin/following{/other_user}","gists_url":"https://api.github.com/users/trustin/gists{/gist_id}","starred_url":"https://api.github.com/users/trustin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trustin/subscriptions","organizations_url":"https://api.github.com/users/trustin/orgs","repos_url":"https://api.github.com/users/trustin/repos","events_url":"https://api.github.com/users/trustin/events{/privacy}","received_events_url":"https://api.github.com/users/trustin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/trustin/armeria","description":"Asynchronous RPC/API client/server library built on top of Java 8, Netty 4.1, HTTP/2, and Thrift","fork":true,"url":"https://api.github.com/repos/trustin/armeria","forks_url":"https://api.github.com/repos/trustin/armeria/forks","keys_url":"https://api.github.com/repos/trustin/armeria/keys{/key_id}","collaborators_url":"https://api.github.com/repos/trustin/armeria/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/trustin/armeria/teams","hooks_url":"https://api.github.com/repos/trustin/armeria/hooks","issue_events_url":"https://api.github.com/repos/trustin/armeria/issues/events{/number}","events_url":"https://api.github.com/repos/trustin/armeria/events","assignees_url":"https://api.github.com/repos/trustin/armeria/assignees{/user}","branches_url":"https://api.github.com/repos/trustin/armeria/branches{/branch}","tags_url":"https://api.github.com/repos/trustin/armeria/tags","blobs_url":"https://api.github.com/repos/trustin/armeria/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/trustin/armeria/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/trustin/armeria/git/refs{/sha}","trees_url":"https://api.github.com/repos/trustin/armeria/git/trees{/sha}","statuses_url":"https://api.github.com/repos/trustin/armeria/statuses/{sha}","languages_url":"https://api.github.com/repos/trustin/armeria/languages","stargazers_url":"https://api.github.com/repos/trustin/armeria/stargazers","contributors_url":"https://api.github.com/repos/trustin/armeria/contributors","subscribers_url":"https://api.github.com/repos/trustin/armeria/subscribers","subscription_url":"https://api.github.com/repos/trustin/armeria/subscription","commits_url":"https://api.github.com/repos/trustin/armeria/commits{/sha}","git_commits_url":"https://api.github.com/repos/trustin/armeria/git/commits{/sha}","comments_url":"https://api.github.com/repos/trustin/armeria/comments{/number}","issue_comment_url":"https://api.github.com/repos/trustin/armeria/issues/comments{/number}","contents_url":"https://api.github.com/repos/trustin/armeria/contents/{+path}","compare_url":"https://api.github.com/repos/trustin/armeria/compare/{base}...{head}","merges_url":"https://api.github.com/repos/trustin/armeria/merges","archive_url":"https://api.github.com/repos/trustin/armeria/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/trustin/armeria/downloads","issues_url":"https://api.github.com/repos/trustin/armeria/issues{/number}","pulls_url":"https://api.github.com/repos/trustin/armeria/pulls{/number}","milestones_url":"https://api.github.com/repos/trustin/armeria/milestones{/number}","notifications_url":"https://api.github.com/repos/trustin/armeria/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/trustin/armeria/labels{/name}","releases_url":"https://api.github.com/repos/trustin/armeria/releases{/id}","deployments_url":"https://api.github.com/repos/trustin/armeria/deployments","created_at":"2015-11-17T03:59:08Z","updated_at":"2016-01-19T06:06:01Z","pushed_at":"2016-02-03T08:40:48Z","git_url":"git://github.com/trustin/armeria.git","ssh_url":"git@github.com:trustin/armeria.git","clone_url":"https://github.com/trustin/armeria.git","svn_url":"https://github.com/trustin/armeria","homepage":"http://line.github.io/armeria/","size":10259,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"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":"line:master","ref":"master","sha":"23b81e83059555196486c6765e563843f612f43c","user":{"login":"line","id":13128444,"avatar_url":"https://avatars.githubusercontent.com/u/13128444?v=3","gravatar_id":"","url":"https://api.github.com/users/line","html_url":"https://github.com/line","followers_url":"https://api.github.com/users/line/followers","following_url":"https://api.github.com/users/line/following{/other_user}","gists_url":"https://api.github.com/users/line/gists{/gist_id}","starred_url":"https://api.github.com/users/line/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/line/subscriptions","organizations_url":"https://api.github.com/users/line/orgs","repos_url":"https://api.github.com/users/line/repos","events_url":"https://api.github.com/users/line/events{/privacy}","received_events_url":"https://api.github.com/users/line/received_events","type":"Organization","site_admin":false},"repo":{"id":46251204,"name":"armeria","full_name":"line/armeria","owner":{"login":"line","id":13128444,"avatar_url":"https://avatars.githubusercontent.com/u/13128444?v=3","gravatar_id":"","url":"https://api.github.com/users/line","html_url":"https://github.com/line","followers_url":"https://api.github.com/users/line/followers","following_url":"https://api.github.com/users/line/following{/other_user}","gists_url":"https://api.github.com/users/line/gists{/gist_id}","starred_url":"https://api.github.com/users/line/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/line/subscriptions","organizations_url":"https://api.github.com/users/line/orgs","repos_url":"https://api.github.com/users/line/repos","events_url":"https://api.github.com/users/line/events{/privacy}","received_events_url":"https://api.github.com/users/line/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/line/armeria","description":"Asynchronous RPC/API client/server library built on top of Java 8, Netty 4.1, HTTP/2, and Thrift","fork":false,"url":"https://api.github.com/repos/line/armeria","forks_url":"https://api.github.com/repos/line/armeria/forks","keys_url":"https://api.github.com/repos/line/armeria/keys{/key_id}","collaborators_url":"https://api.github.com/repos/line/armeria/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/line/armeria/teams","hooks_url":"https://api.github.com/repos/line/armeria/hooks","issue_events_url":"https://api.github.com/repos/line/armeria/issues/events{/number}","events_url":"https://api.github.com/repos/line/armeria/events","assignees_url":"https://api.github.com/repos/line/armeria/assignees{/user}","branches_url":"https://api.github.com/repos/line/armeria/branches{/branch}","tags_url":"https://api.github.com/repos/line/armeria/tags","blobs_url":"https://api.github.com/repos/line/armeria/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/line/armeria/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/line/armeria/git/refs{/sha}","trees_url":"https://api.github.com/repos/line/armeria/git/trees{/sha}","statuses_url":"https://api.github.com/repos/line/armeria/statuses/{sha}","languages_url":"https://api.github.com/repos/line/armeria/languages","stargazers_url":"https://api.github.com/repos/line/armeria/stargazers","contributors_url":"https://api.github.com/repos/line/armeria/contributors","subscribers_url":"https://api.github.com/repos/line/armeria/subscribers","subscription_url":"https://api.github.com/repos/line/armeria/subscription","commits_url":"https://api.github.com/repos/line/armeria/commits{/sha}","git_commits_url":"https://api.github.com/repos/line/armeria/git/commits{/sha}","comments_url":"https://api.github.com/repos/line/armeria/comments{/number}","issue_comment_url":"https://api.github.com/repos/line/armeria/issues/comments{/number}","contents_url":"https://api.github.com/repos/line/armeria/contents/{+path}","compare_url":"https://api.github.com/repos/line/armeria/compare/{base}...{head}","merges_url":"https://api.github.com/repos/line/armeria/merges","archive_url":"https://api.github.com/repos/line/armeria/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/line/armeria/downloads","issues_url":"https://api.github.com/repos/line/armeria/issues{/number}","pulls_url":"https://api.github.com/repos/line/armeria/pulls{/number}","milestones_url":"https://api.github.com/repos/line/armeria/milestones{/number}","notifications_url":"https://api.github.com/repos/line/armeria/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/line/armeria/labels{/name}","releases_url":"https://api.github.com/repos/line/armeria/releases{/id}","deployments_url":"https://api.github.com/repos/line/armeria/deployments","created_at":"2015-11-16T04:04:01Z","updated_at":"2016-02-01T15:38:40Z","pushed_at":"2016-02-03T08:40:49Z","git_url":"git://github.com/line/armeria.git","ssh_url":"git@github.com:line/armeria.git","clone_url":"https://github.com/line/armeria.git","svn_url":"https://github.com/line/armeria","homepage":"http://line.github.io/armeria/","size":10300,"stargazers_count":260,"watchers_count":260,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":56,"mirror_url":null,"open_issues_count":21,"forks":56,"open_issues":21,"watchers":260,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/line/armeria/pulls/105"},"html":{"href":"https://github.com/line/armeria/pull/105"},"issue":{"href":"https://api.github.com/repos/line/armeria/issues/105"},"comments":{"href":"https://api.github.com/repos/line/armeria/issues/105/comments"},"review_comments":{"href":"https://api.github.com/repos/line/armeria/pulls/105/comments"},"review_comment":{"href":"https://api.github.com/repos/line/armeria/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/line/armeria/pulls/105/commits"},"statuses":{"href":"https://api.github.com/repos/line/armeria/statuses/15bea485986ae5657a8888d6e6c73771fa1f4f7b"}}}}