{"action":"created","comment":{"url":"https://api.github.com/repos/jenkinsci/jenkins/pulls/comments/209321705","pull_request_review_id":145319412,"id":209321705,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwOTMyMTcwNQ==","diff_hunk":"@@ -0,0 +1,104 @@\n+/*\n+ * The MIT License\n+ *\n+ * Copyright 2018 CloudBees, 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 jenkins.model.logging.impl;\n+\n+import hudson.console.ConsoleLogFilter;\n+import hudson.model.AbstractBuild;\n+import hudson.model.BuildableItemWithBuildWrappers;\n+import hudson.model.Job;\n+import hudson.model.Run;\n+import hudson.model.StreamBuildListener;\n+import hudson.tasks.BuildWrapper;\n+import jenkins.model.logging.Loggable;\n+import jenkins.model.logging.LogStorage;\n+import org.kohsuke.accmod.Restricted;\n+import org.kohsuke.accmod.restrictions.Beta;\n+\n+import javax.annotation.Nonnull;\n+import java.io.IOException;\n+import java.io.OutputStream;\n+import java.util.logging.Level;\n+import java.util.logging.Logger;\n+\n+/**\n+ * Logging method which takes {@link OutputStream} as a destination.\n+ * This implementation consults with {@link ConsoleLogFilter} extensions in Jenkins.\n+ * @author Oleg Nenashev\n+ * @since TODO\n+ */\n+@Restricted(Beta.class)\n+public abstract class StreamLogStorage extends LogStorage {\n+\n+    private static final Logger LOGGER =\n+            Logger.getLogger(StreamLogStorage.class.getName());\n+\n+    public StreamLogStorage(@Nonnull Loggable loggable) {\n+        super(loggable);\n+    }\n+\n+    public abstract OutputStream createOutputStream() throws IOException, InterruptedException;\n+\n+    /**\n+     * Defines an additional Console Log Filter to be used with the logging method.\n+     * This filter may be also used for log redirection and multi-reporting in very custom cases.\n+     * @return Log filter. {@code null} if no custom implementation\n+     */\n+    public ConsoleLogFilter getExtraConsoleLogFilter() {\n+        return null;\n+    }\n+\n+    //TODO: This decoration logic should be shared with other implementations\n+    @Override\n+    public final StreamBuildListener createBuildListener() throws IOException, InterruptedException {\n+\n+        OutputStream logger = createOutputStream();\n+        if (!(loggable instanceof Run<?,?>)) {\n+            throw new IOException(\"Loggable is not a Run instance: \" + loggable.getClass());\n+        }\n+        Run<?,?> build = (Run<?, ?>)loggable;\n+\n+        // Global log filter\n+        for (ConsoleLogFilter filter : ConsoleLogFilter.all()) {\n+            logger = filter.decorateLogger(build, logger);","path":"core/src/main/java/jenkins/model/logging/impl/StreamLogStorage.java","position":83,"original_position":83,"commit_id":"1113413e89a62defd4e70962e33f0c819d382a0f","original_commit_id":"1113413e89a62defd4e70962e33f0c819d382a0f","user":{"login":"jglick","id":154109,"node_id":"MDQ6VXNlcjE1NDEwOQ==","avatar_url":"https://avatars1.githubusercontent.com/u/154109?v=4","gravatar_id":"","url":"https://api.github.com/users/jglick","html_url":"https://github.com/jglick","followers_url":"https://api.github.com/users/jglick/followers","following_url":"https://api.github.com/users/jglick/following{/other_user}","gists_url":"https://api.github.com/users/jglick/gists{/gist_id}","starred_url":"https://api.github.com/users/jglick/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jglick/subscriptions","organizations_url":"https://api.github.com/users/jglick/orgs","repos_url":"https://api.github.com/users/jglick/repos","events_url":"https://api.github.com/users/jglick/events{/privacy}","received_events_url":"https://api.github.com/users/jglick/received_events","type":"User","site_admin":false},"body":"Suggest moving this to a `protected` method in `RunExecution`…","created_at":"2018-08-10T16:51:34Z","updated_at":"2018-08-10T16:53:43Z","html_url":"https://github.com/jenkinsci/jenkins/pull/3575#discussion_r209321705","pull_request_url":"https://api.github.com/repos/jenkinsci/jenkins/pulls/3575","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/jenkinsci/jenkins/pulls/comments/209321705"},"html":{"href":"https://github.com/jenkinsci/jenkins/pull/3575#discussion_r209321705"},"pull_request":{"href":"https://api.github.com/repos/jenkinsci/jenkins/pulls/3575"}},"in_reply_to_id":209308648},"pull_request":{"url":"https://api.github.com/repos/jenkinsci/jenkins/pulls/3575","id":206016443,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA2MDE2NDQz","html_url":"https://github.com/jenkinsci/jenkins/pull/3575","diff_url":"https://github.com/jenkinsci/jenkins/pull/3575.diff","patch_url":"https://github.com/jenkinsci/jenkins/pull/3575.patch","issue_url":"https://api.github.com/repos/jenkinsci/jenkins/issues/3575","number":3575,"state":"open","locked":false,"title":"[JENKINS-38313] - Introduce LogStorage API in the core","user":{"login":"oleg-nenashev","id":3000480,"node_id":"MDQ6VXNlcjMwMDA0ODA=","avatar_url":"https://avatars0.githubusercontent.com/u/3000480?v=4","gravatar_id":"","url":"https://api.github.com/users/oleg-nenashev","html_url":"https://github.com/oleg-nenashev","followers_url":"https://api.github.com/users/oleg-nenashev/followers","following_url":"https://api.github.com/users/oleg-nenashev/following{/other_user}","gists_url":"https://api.github.com/users/oleg-nenashev/gists{/gist_id}","starred_url":"https://api.github.com/users/oleg-nenashev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleg-nenashev/subscriptions","organizations_url":"https://api.github.com/users/oleg-nenashev/orgs","repos_url":"https://api.github.com/users/oleg-nenashev/repos","events_url":"https://api.github.com/users/oleg-nenashev/events{/privacy}","received_events_url":"https://api.github.com/users/oleg-nenashev/received_events","type":"User","site_admin":false},"body":"Version of https://github.com/jenkinsci/jenkins/pull/3557, but with a single LogStorage as proposed by @jglick . The previous implementation had separate `LoggingMethod` and `LogBrowser` implementation directly in the core, but with this change I will need to move it to External Logging API.\r\n\r\n# Proposed Changelog Entries\r\n\r\n* Major RFE: JENKINS-52692 - Developer: Introduce new LogStorage API and LogStorageFactory extension point \r\n* RFE: JENKINS-52867 - Developer: Introduce new API for deleting Run logs\r\n\r\n### Submitter checklist\r\n\r\n- [x] JIRA issue is well described\r\n- [x] Changelog entry appropriate for the audience affected by the change (users or developer, depending on the change). [Examples](https://github.com/jenkins-infra/jenkins.io/blob/master/content/_data/changelogs/weekly.yml)\r\n      * Use the `Internal: ` prefix if the change has no user-visible impact (API, test frameworks, etc.)\r\n- [x] Appropriate autotests or explanation to why this change has no tests\r\n- [x] For dependency updates: links to external changelogs and, if possible, full diffs\r\n\r\n@carlossg @jenkinsci/code-reviewers I will appreciate feedback about the preferred approach \r\n\r\n","created_at":"2018-08-03T12:31:49Z","updated_at":"2018-08-10T16:53:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c0c97a8155b5ca547b1eb3d98122750bb67066d1","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":271563319,"node_id":"MDU6TGFiZWwyNzE1NjMzMTk=","url":"https://api.github.com/repos/jenkinsci/jenkins/labels/needs-review","name":"needs-review","color":"207de5","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/jenkinsci/jenkins/pulls/3575/commits","review_comments_url":"https://api.github.com/repos/jenkinsci/jenkins/pulls/3575/comments","review_comment_url":"https://api.github.com/repos/jenkinsci/jenkins/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jenkinsci/jenkins/issues/3575/comments","statuses_url":"https://api.github.com/repos/jenkinsci/jenkins/statuses/1113413e89a62defd4e70962e33f0c819d382a0f","head":{"label":"oleg-nenashev:extlogging/LogStorage","ref":"extlogging/LogStorage","sha":"1113413e89a62defd4e70962e33f0c819d382a0f","user":{"login":"oleg-nenashev","id":3000480,"node_id":"MDQ6VXNlcjMwMDA0ODA=","avatar_url":"https://avatars0.githubusercontent.com/u/3000480?v=4","gravatar_id":"","url":"https://api.github.com/users/oleg-nenashev","html_url":"https://github.com/oleg-nenashev","followers_url":"https://api.github.com/users/oleg-nenashev/followers","following_url":"https://api.github.com/users/oleg-nenashev/following{/other_user}","gists_url":"https://api.github.com/users/oleg-nenashev/gists{/gist_id}","starred_url":"https://api.github.com/users/oleg-nenashev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleg-nenashev/subscriptions","organizations_url":"https://api.github.com/users/oleg-nenashev/orgs","repos_url":"https://api.github.com/users/oleg-nenashev/repos","events_url":"https://api.github.com/users/oleg-nenashev/events{/privacy}","received_events_url":"https://api.github.com/users/oleg-nenashev/received_events","type":"User","site_admin":false},"repo":{"id":14375421,"node_id":"MDEwOlJlcG9zaXRvcnkxNDM3NTQyMQ==","name":"jenkins","full_name":"oleg-nenashev/jenkins","owner":{"login":"oleg-nenashev","id":3000480,"node_id":"MDQ6VXNlcjMwMDA0ODA=","avatar_url":"https://avatars0.githubusercontent.com/u/3000480?v=4","gravatar_id":"","url":"https://api.github.com/users/oleg-nenashev","html_url":"https://github.com/oleg-nenashev","followers_url":"https://api.github.com/users/oleg-nenashev/followers","following_url":"https://api.github.com/users/oleg-nenashev/following{/other_user}","gists_url":"https://api.github.com/users/oleg-nenashev/gists{/gist_id}","starred_url":"https://api.github.com/users/oleg-nenashev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oleg-nenashev/subscriptions","organizations_url":"https://api.github.com/users/oleg-nenashev/orgs","repos_url":"https://api.github.com/users/oleg-nenashev/repos","events_url":"https://api.github.com/users/oleg-nenashev/events{/privacy}","received_events_url":"https://api.github.com/users/oleg-nenashev/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/oleg-nenashev/jenkins","description":"Jenkins Continuous Integration Server","fork":true,"url":"https://api.github.com/repos/oleg-nenashev/jenkins","forks_url":"https://api.github.com/repos/oleg-nenashev/jenkins/forks","keys_url":"https://api.github.com/repos/oleg-nenashev/jenkins/keys{/key_id}","collaborators_url":"https://api.github.com/repos/oleg-nenashev/jenkins/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/oleg-nenashev/jenkins/teams","hooks_url":"https://api.github.com/repos/oleg-nenashev/jenkins/hooks","issue_events_url":"https://api.github.com/repos/oleg-nenashev/jenkins/issues/events{/number}","events_url":"https://api.github.com/repos/oleg-nenashev/jenkins/events","assignees_url":"https://api.github.com/repos/oleg-nenashev/jenkins/assignees{/user}","branches_url":"https://api.github.com/repos/oleg-nenashev/jenkins/branches{/branch}","tags_url":"https://api.github.com/repos/oleg-nenashev/jenkins/tags","blobs_url":"https://api.github.com/repos/oleg-nenashev/jenkins/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/oleg-nenashev/jenkins/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/oleg-nenashev/jenkins/git/refs{/sha}","trees_url":"https://api.github.com/repos/oleg-nenashev/jenkins/git/trees{/sha}","statuses_url":"https://api.github.com/repos/oleg-nenashev/jenkins/statuses/{sha}","languages_url":"https://api.github.com/repos/oleg-nenashev/jenkins/languages","stargazers_url":"https://api.github.com/repos/oleg-nenashev/jenkins/stargazers","contributors_url":"https://api.github.com/repos/oleg-nenashev/jenkins/contributors","subscribers_url":"https://api.github.com/repos/oleg-nenashev/jenkins/subscribers","subscription_url":"https://api.github.com/repos/oleg-nenashev/jenkins/subscription","commits_url":"https://api.github.com/repos/oleg-nenashev/jenkins/commits{/sha}","git_commits_url":"https://api.github.com/repos/oleg-nenashev/jenkins/git/commits{/sha}","comments_url":"https://api.github.com/repos/oleg-nenashev/jenkins/comments{/number}","issue_comment_url":"https://api.github.com/repos/oleg-nenashev/jenkins/issues/comments{/number}","contents_url":"https://api.github.com/repos/oleg-nenashev/jenkins/contents/{+path}","compare_url":"https://api.github.com/repos/oleg-nenashev/jenkins/compare/{base}...{head}","merges_url":"https://api.github.com/repos/oleg-nenashev/jenkins/merges","archive_url":"https://api.github.com/repos/oleg-nenashev/jenkins/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/oleg-nenashev/jenkins/downloads","issues_url":"https://api.github.com/repos/oleg-nenashev/jenkins/issues{/number}","pulls_url":"https://api.github.com/repos/oleg-nenashev/jenkins/pulls{/number}","milestones_url":"https://api.github.com/repos/oleg-nenashev/jenkins/milestones{/number}","notifications_url":"https://api.github.com/repos/oleg-nenashev/jenkins/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/oleg-nenashev/jenkins/labels{/name}","releases_url":"https://api.github.com/repos/oleg-nenashev/jenkins/releases{/id}","deployments_url":"https://api.github.com/repos/oleg-nenashev/jenkins/deployments","created_at":"2013-11-13T20:24:23Z","updated_at":"2018-07-09T07:42:12Z","pushed_at":"2018-08-09T16:25:50Z","git_url":"git://github.com/oleg-nenashev/jenkins.git","ssh_url":"git@github.com:oleg-nenashev/jenkins.git","clone_url":"https://github.com/oleg-nenashev/jenkins.git","svn_url":"https://github.com/oleg-nenashev/jenkins","homepage":"http://jenkins-ci.org/","size":114084,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"jenkinsci:master","ref":"master","sha":"7b2698db89183b4d701107485db61eb36442ac25","user":{"login":"jenkinsci","id":107424,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEwNzQyNA==","avatar_url":"https://avatars0.githubusercontent.com/u/107424?v=4","gravatar_id":"","url":"https://api.github.com/users/jenkinsci","html_url":"https://github.com/jenkinsci","followers_url":"https://api.github.com/users/jenkinsci/followers","following_url":"https://api.github.com/users/jenkinsci/following{/other_user}","gists_url":"https://api.github.com/users/jenkinsci/gists{/gist_id}","starred_url":"https://api.github.com/users/jenkinsci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jenkinsci/subscriptions","organizations_url":"https://api.github.com/users/jenkinsci/orgs","repos_url":"https://api.github.com/users/jenkinsci/repos","events_url":"https://api.github.com/users/jenkinsci/events{/privacy}","received_events_url":"https://api.github.com/users/jenkinsci/received_events","type":"Organization","site_admin":false},"repo":{"id":1103607,"node_id":"MDEwOlJlcG9zaXRvcnkxMTAzNjA3","name":"jenkins","full_name":"jenkinsci/jenkins","owner":{"login":"jenkinsci","id":107424,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEwNzQyNA==","avatar_url":"https://avatars0.githubusercontent.com/u/107424?v=4","gravatar_id":"","url":"https://api.github.com/users/jenkinsci","html_url":"https://github.com/jenkinsci","followers_url":"https://api.github.com/users/jenkinsci/followers","following_url":"https://api.github.com/users/jenkinsci/following{/other_user}","gists_url":"https://api.github.com/users/jenkinsci/gists{/gist_id}","starred_url":"https://api.github.com/users/jenkinsci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jenkinsci/subscriptions","organizations_url":"https://api.github.com/users/jenkinsci/orgs","repos_url":"https://api.github.com/users/jenkinsci/repos","events_url":"https://api.github.com/users/jenkinsci/events{/privacy}","received_events_url":"https://api.github.com/users/jenkinsci/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/jenkinsci/jenkins","description":"Jenkins automation server","fork":false,"url":"https://api.github.com/repos/jenkinsci/jenkins","forks_url":"https://api.github.com/repos/jenkinsci/jenkins/forks","keys_url":"https://api.github.com/repos/jenkinsci/jenkins/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jenkinsci/jenkins/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jenkinsci/jenkins/teams","hooks_url":"https://api.github.com/repos/jenkinsci/jenkins/hooks","issue_events_url":"https://api.github.com/repos/jenkinsci/jenkins/issues/events{/number}","events_url":"https://api.github.com/repos/jenkinsci/jenkins/events","assignees_url":"https://api.github.com/repos/jenkinsci/jenkins/assignees{/user}","branches_url":"https://api.github.com/repos/jenkinsci/jenkins/branches{/branch}","tags_url":"https://api.github.com/repos/jenkinsci/jenkins/tags","blobs_url":"https://api.github.com/repos/jenkinsci/jenkins/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jenkinsci/jenkins/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jenkinsci/jenkins/git/refs{/sha}","trees_url":"https://api.github.com/repos/jenkinsci/jenkins/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jenkinsci/jenkins/statuses/{sha}","languages_url":"https://api.github.com/repos/jenkinsci/jenkins/languages","stargazers_url":"https://api.github.com/repos/jenkinsci/jenkins/stargazers","contributors_url":"https://api.github.com/repos/jenkinsci/jenkins/contributors","subscribers_url":"https://api.github.com/repos/jenkinsci/jenkins/subscribers","subscription_url":"https://api.github.com/repos/jenkinsci/jenkins/subscription","commits_url":"https://api.github.com/repos/jenkinsci/jenkins/commits{/sha}","git_commits_url":"https://api.github.com/repos/jenkinsci/jenkins/git/commits{/sha}","comments_url":"https://api.github.com/repos/jenkinsci/jenkins/comments{/number}","issue_comment_url":"https://api.github.com/repos/jenkinsci/jenkins/issues/comments{/number}","contents_url":"https://api.github.com/repos/jenkinsci/jenkins/contents/{+path}","compare_url":"https://api.github.com/repos/jenkinsci/jenkins/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jenkinsci/jenkins/merges","archive_url":"https://api.github.com/repos/jenkinsci/jenkins/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jenkinsci/jenkins/downloads","issues_url":"https://api.github.com/repos/jenkinsci/jenkins/issues{/number}","pulls_url":"https://api.github.com/repos/jenkinsci/jenkins/pulls{/number}","milestones_url":"https://api.github.com/repos/jenkinsci/jenkins/milestones{/number}","notifications_url":"https://api.github.com/repos/jenkinsci/jenkins/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jenkinsci/jenkins/labels{/name}","releases_url":"https://api.github.com/repos/jenkinsci/jenkins/releases{/id}","deployments_url":"https://api.github.com/repos/jenkinsci/jenkins/deployments","created_at":"2010-11-22T21:21:23Z","updated_at":"2018-08-10T15:42:37Z","pushed_at":"2018-08-10T12:39:48Z","git_url":"git://github.com/jenkinsci/jenkins.git","ssh_url":"git@github.com:jenkinsci/jenkins.git","clone_url":"https://github.com/jenkinsci/jenkins.git","svn_url":"https://github.com/jenkinsci/jenkins","homepage":"https://jenkins.io/","size":108550,"stargazers_count":10865,"watchers_count":10865,"language":"Java","has_issues":false,"has_projects":false,"has_downloads":false,"has_wiki":false,"has_pages":false,"forks_count":4672,"mirror_url":null,"archived":false,"open_issues_count":93,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":4672,"open_issues":93,"watchers":10865,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/jenkinsci/jenkins/pulls/3575"},"html":{"href":"https://github.com/jenkinsci/jenkins/pull/3575"},"issue":{"href":"https://api.github.com/repos/jenkinsci/jenkins/issues/3575"},"comments":{"href":"https://api.github.com/repos/jenkinsci/jenkins/issues/3575/comments"},"review_comments":{"href":"https://api.github.com/repos/jenkinsci/jenkins/pulls/3575/comments"},"review_comment":{"href":"https://api.github.com/repos/jenkinsci/jenkins/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jenkinsci/jenkins/pulls/3575/commits"},"statuses":{"href":"https://api.github.com/repos/jenkinsci/jenkins/statuses/1113413e89a62defd4e70962e33f0c819d382a0f"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"jglick"}}