{"action":"created","comment":{"url":"https://api.github.com/repos/confluentinc/kafka/pulls/comments/31586010","id":31586010,"diff_hunk":"@@ -0,0 +1,279 @@\n+/**\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\n+ * contributor license agreements.  See the NOTICE file distributed with\n+ * this work for additional information regarding copyright ownership.\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\n+ * (the \"License\"); you may not use this file except in compliance with\n+ * 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,\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+\n+package org.apache.kafka.clients.tools;\n+\n+import org.apache.kafka.clients.producer.Callback;\n+import org.apache.kafka.clients.producer.KafkaProducer;\n+import org.apache.kafka.clients.producer.Producer;\n+import org.apache.kafka.clients.producer.ProducerConfig;\n+import org.apache.kafka.clients.producer.ProducerRecord;\n+import org.apache.kafka.clients.producer.RecordMetadata;\n+\n+import org.json.simple.JSONObject;\n+\n+import java.io.IOException;\n+import java.util.HashMap;\n+import java.util.Map;\n+import java.util.Properties;\n+\n+import joptsimple.ArgumentAcceptingOptionSpec;\n+import joptsimple.OptionParser;\n+import joptsimple.OptionSet;\n+import joptsimple.OptionSpec;\n+import joptsimple.OptionSpecBuilder;\n+\n+/**\n+ * Primarily intended for use with system testing, this producer prints metadata\n+ * in the form of JSON to stdout on each \"send\" request. For example, this helps\n+ * with end-to-end correctness tests by making externally visible which messages have been\n+ * acked and which have not.\n+ *\n+ * When used as a command-line tool, it produces a fixed number of increasing integers.\n+ * If logging is left enabled, log output on stdout can be easily ignored by checking\n+ * whether a given line is valid JSON.\n+ */\n+public class VerifiableProducer {\n+\n+    private static final long NS_PER_MS = 1000000L;\n+    private static final long NS_PER_SEC = 1000 * NS_PER_MS;\n+    private static final long MIN_SLEEP_NS = 2 * NS_PER_MS;\n+    \n+    OptionParser commandLineParser;\n+    Map<String, OptionSpec<?>> commandLineOptions = new HashMap<String, OptionSpec<?>>();\n+  \n+    String topic;\n+    private Properties producerProps = new Properties();\n+    private Producer<String, String> producer;\n+    private int numMessages;\n+    private long throughput;\n+  \n+    /** Construct with command-line arguments */\n+    public VerifiableProducer(String[] args) throws IOException {\n+        this.configureParser();\n+        this.parseCommandLineArgs(args);\n+        this.producer = new KafkaProducer<String, String>(producerProps);\n+    }\n+  \n+    /** Set up the command-line options. */\n+    private void configureParser() {\n+        this.commandLineParser = new OptionParser();\n+        ArgumentAcceptingOptionSpec<String> topicOpt = commandLineParser.accepts(\"topic\", \"REQUIRED: The topic id to produce messages to.\")","path":"clients/src/main/java/org/apache/kafka/clients/tools/VerifiableProducer.java","position":75,"original_position":75,"commit_id":"0a5de8e0590e3a8dce1a91769ad41497b5e07d17","original_commit_id":"0a5de8e0590e3a8dce1a91769ad41497b5e07d17","user":{"login":"ewencp","id":47366,"avatar_url":"https://avatars.githubusercontent.com/u/47366?v=3","gravatar_id":"","url":"https://api.github.com/users/ewencp","html_url":"https://github.com/ewencp","followers_url":"https://api.github.com/users/ewencp/followers","following_url":"https://api.github.com/users/ewencp/following{/other_user}","gists_url":"https://api.github.com/users/ewencp/gists{/gist_id}","starred_url":"https://api.github.com/users/ewencp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ewencp/subscriptions","organizations_url":"https://api.github.com/users/ewencp/orgs","repos_url":"https://api.github.com/users/ewencp/repos","events_url":"https://api.github.com/users/ewencp/events{/privacy}","received_events_url":"https://api.github.com/users/ewencp/received_events","type":"User","site_admin":false},"body":"Have you kept track of KIP-4? I think there was some discussion of doing a better job of standardizing command line arguments in the tools. Might be worth a) double checking it to make sure nothing here would be inconsistent (unlikely since it's about admin commands) and b) check the mailing list to see if there was any discussion of argument parsing which might end up affecting this code, e.g. if they had discussed/decided on which library to use.","created_at":"2015-06-03T00:46:44Z","updated_at":"2015-06-03T00:46:44Z","html_url":"https://github.com/confluentinc/kafka/pull/3#discussion_r31586010","pull_request_url":"https://api.github.com/repos/confluentinc/kafka/pulls/3","_links":{"self":{"href":"https://api.github.com/repos/confluentinc/kafka/pulls/comments/31586010"},"html":{"href":"https://github.com/confluentinc/kafka/pull/3#discussion_r31586010"},"pull_request":{"href":"https://api.github.com/repos/confluentinc/kafka/pulls/3"}}},"pull_request":{"url":"https://api.github.com/repos/confluentinc/kafka/pulls/3","id":36554578,"html_url":"https://github.com/confluentinc/kafka/pull/3","diff_url":"https://github.com/confluentinc/kafka/pull/3.diff","patch_url":"https://github.com/confluentinc/kafka/pull/3.patch","issue_url":"https://api.github.com/repos/confluentinc/kafka/issues/3","number":3,"state":"open","locked":false,"title":"Verbose client","user":{"login":"granders","id":1295932,"avatar_url":"https://avatars.githubusercontent.com/u/1295932?v=3","gravatar_id":"","url":"https://api.github.com/users/granders","html_url":"https://github.com/granders","followers_url":"https://api.github.com/users/granders/followers","following_url":"https://api.github.com/users/granders/following{/other_user}","gists_url":"https://api.github.com/users/granders/gists{/gist_id}","starred_url":"https://api.github.com/users/granders/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/granders/subscriptions","organizations_url":"https://api.github.com/users/granders/orgs","repos_url":"https://api.github.com/users/granders/repos","events_url":"https://api.github.com/users/granders/events{/privacy}","received_events_url":"https://api.github.com/users/granders/received_events","type":"User","site_admin":false},"body":"Adds \"verbose producer\" client to help with system testing.\r\n\r\nI didn't add a corresponding consumer since console consumer was good enough for my purposes.","created_at":"2015-05-29T23:45:39Z","updated_at":"2015-06-03T00:46:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"584cac5d07f03f2a8b1c17a523250e756c2b1867","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/confluentinc/kafka/pulls/3/commits","review_comments_url":"https://api.github.com/repos/confluentinc/kafka/pulls/3/comments","review_comment_url":"https://api.github.com/repos/confluentinc/kafka/pulls/comments{/number}","comments_url":"https://api.github.com/repos/confluentinc/kafka/issues/3/comments","statuses_url":"https://api.github.com/repos/confluentinc/kafka/statuses/0a5de8e0590e3a8dce1a91769ad41497b5e07d17","head":{"label":"confluentinc:verbose-client","ref":"verbose-client","sha":"0a5de8e0590e3a8dce1a91769ad41497b5e07d17","user":{"login":"confluentinc","id":9439498,"avatar_url":"https://avatars.githubusercontent.com/u/9439498?v=3","gravatar_id":"","url":"https://api.github.com/users/confluentinc","html_url":"https://github.com/confluentinc","followers_url":"https://api.github.com/users/confluentinc/followers","following_url":"https://api.github.com/users/confluentinc/following{/other_user}","gists_url":"https://api.github.com/users/confluentinc/gists{/gist_id}","starred_url":"https://api.github.com/users/confluentinc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/confluentinc/subscriptions","organizations_url":"https://api.github.com/users/confluentinc/orgs","repos_url":"https://api.github.com/users/confluentinc/repos","events_url":"https://api.github.com/users/confluentinc/events{/privacy}","received_events_url":"https://api.github.com/users/confluentinc/received_events","type":"Organization","site_admin":false},"repo":{"id":34084045,"name":"kafka","full_name":"confluentinc/kafka","owner":{"login":"confluentinc","id":9439498,"avatar_url":"https://avatars.githubusercontent.com/u/9439498?v=3","gravatar_id":"","url":"https://api.github.com/users/confluentinc","html_url":"https://github.com/confluentinc","followers_url":"https://api.github.com/users/confluentinc/followers","following_url":"https://api.github.com/users/confluentinc/following{/other_user}","gists_url":"https://api.github.com/users/confluentinc/gists{/gist_id}","starred_url":"https://api.github.com/users/confluentinc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/confluentinc/subscriptions","organizations_url":"https://api.github.com/users/confluentinc/orgs","repos_url":"https://api.github.com/users/confluentinc/repos","events_url":"https://api.github.com/users/confluentinc/events{/privacy}","received_events_url":"https://api.github.com/users/confluentinc/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/confluentinc/kafka","description":"Mirror of Apache Kafka","fork":false,"url":"https://api.github.com/repos/confluentinc/kafka","forks_url":"https://api.github.com/repos/confluentinc/kafka/forks","keys_url":"https://api.github.com/repos/confluentinc/kafka/keys{/key_id}","collaborators_url":"https://api.github.com/repos/confluentinc/kafka/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/confluentinc/kafka/teams","hooks_url":"https://api.github.com/repos/confluentinc/kafka/hooks","issue_events_url":"https://api.github.com/repos/confluentinc/kafka/issues/events{/number}","events_url":"https://api.github.com/repos/confluentinc/kafka/events","assignees_url":"https://api.github.com/repos/confluentinc/kafka/assignees{/user}","branches_url":"https://api.github.com/repos/confluentinc/kafka/branches{/branch}","tags_url":"https://api.github.com/repos/confluentinc/kafka/tags","blobs_url":"https://api.github.com/repos/confluentinc/kafka/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/confluentinc/kafka/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/confluentinc/kafka/git/refs{/sha}","trees_url":"https://api.github.com/repos/confluentinc/kafka/git/trees{/sha}","statuses_url":"https://api.github.com/repos/confluentinc/kafka/statuses/{sha}","languages_url":"https://api.github.com/repos/confluentinc/kafka/languages","stargazers_url":"https://api.github.com/repos/confluentinc/kafka/stargazers","contributors_url":"https://api.github.com/repos/confluentinc/kafka/contributors","subscribers_url":"https://api.github.com/repos/confluentinc/kafka/subscribers","subscription_url":"https://api.github.com/repos/confluentinc/kafka/subscription","commits_url":"https://api.github.com/repos/confluentinc/kafka/commits{/sha}","git_commits_url":"https://api.github.com/repos/confluentinc/kafka/git/commits{/sha}","comments_url":"https://api.github.com/repos/confluentinc/kafka/comments{/number}","issue_comment_url":"https://api.github.com/repos/confluentinc/kafka/issues/comments{/number}","contents_url":"https://api.github.com/repos/confluentinc/kafka/contents/{+path}","compare_url":"https://api.github.com/repos/confluentinc/kafka/compare/{base}...{head}","merges_url":"https://api.github.com/repos/confluentinc/kafka/merges","archive_url":"https://api.github.com/repos/confluentinc/kafka/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/confluentinc/kafka/downloads","issues_url":"https://api.github.com/repos/confluentinc/kafka/issues{/number}","pulls_url":"https://api.github.com/repos/confluentinc/kafka/pulls{/number}","milestones_url":"https://api.github.com/repos/confluentinc/kafka/milestones{/number}","notifications_url":"https://api.github.com/repos/confluentinc/kafka/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/confluentinc/kafka/labels{/name}","releases_url":"https://api.github.com/repos/confluentinc/kafka/releases{/id}","created_at":"2015-04-16T22:32:49Z","updated_at":"2015-05-25T21:45:29Z","pushed_at":"2015-06-02T22:52:47Z","git_url":"git://github.com/confluentinc/kafka.git","ssh_url":"git@github.com:confluentinc/kafka.git","clone_url":"https://github.com/confluentinc/kafka.git","svn_url":"https://github.com/confluentinc/kafka","homepage":null,"size":16630,"stargazers_count":1,"watchers_count":1,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":1,"default_branch":"trunk"}},"base":{"label":"confluentinc:system-tests","ref":"system-tests","sha":"f1914c3ba9b52d0f8db3989c8b031127b42ac59e","user":{"login":"confluentinc","id":9439498,"avatar_url":"https://avatars.githubusercontent.com/u/9439498?v=3","gravatar_id":"","url":"https://api.github.com/users/confluentinc","html_url":"https://github.com/confluentinc","followers_url":"https://api.github.com/users/confluentinc/followers","following_url":"https://api.github.com/users/confluentinc/following{/other_user}","gists_url":"https://api.github.com/users/confluentinc/gists{/gist_id}","starred_url":"https://api.github.com/users/confluentinc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/confluentinc/subscriptions","organizations_url":"https://api.github.com/users/confluentinc/orgs","repos_url":"https://api.github.com/users/confluentinc/repos","events_url":"https://api.github.com/users/confluentinc/events{/privacy}","received_events_url":"https://api.github.com/users/confluentinc/received_events","type":"Organization","site_admin":false},"repo":{"id":34084045,"name":"kafka","full_name":"confluentinc/kafka","owner":{"login":"confluentinc","id":9439498,"avatar_url":"https://avatars.githubusercontent.com/u/9439498?v=3","gravatar_id":"","url":"https://api.github.com/users/confluentinc","html_url":"https://github.com/confluentinc","followers_url":"https://api.github.com/users/confluentinc/followers","following_url":"https://api.github.com/users/confluentinc/following{/other_user}","gists_url":"https://api.github.com/users/confluentinc/gists{/gist_id}","starred_url":"https://api.github.com/users/confluentinc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/confluentinc/subscriptions","organizations_url":"https://api.github.com/users/confluentinc/orgs","repos_url":"https://api.github.com/users/confluentinc/repos","events_url":"https://api.github.com/users/confluentinc/events{/privacy}","received_events_url":"https://api.github.com/users/confluentinc/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/confluentinc/kafka","description":"Mirror of Apache Kafka","fork":false,"url":"https://api.github.com/repos/confluentinc/kafka","forks_url":"https://api.github.com/repos/confluentinc/kafka/forks","keys_url":"https://api.github.com/repos/confluentinc/kafka/keys{/key_id}","collaborators_url":"https://api.github.com/repos/confluentinc/kafka/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/confluentinc/kafka/teams","hooks_url":"https://api.github.com/repos/confluentinc/kafka/hooks","issue_events_url":"https://api.github.com/repos/confluentinc/kafka/issues/events{/number}","events_url":"https://api.github.com/repos/confluentinc/kafka/events","assignees_url":"https://api.github.com/repos/confluentinc/kafka/assignees{/user}","branches_url":"https://api.github.com/repos/confluentinc/kafka/branches{/branch}","tags_url":"https://api.github.com/repos/confluentinc/kafka/tags","blobs_url":"https://api.github.com/repos/confluentinc/kafka/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/confluentinc/kafka/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/confluentinc/kafka/git/refs{/sha}","trees_url":"https://api.github.com/repos/confluentinc/kafka/git/trees{/sha}","statuses_url":"https://api.github.com/repos/confluentinc/kafka/statuses/{sha}","languages_url":"https://api.github.com/repos/confluentinc/kafka/languages","stargazers_url":"https://api.github.com/repos/confluentinc/kafka/stargazers","contributors_url":"https://api.github.com/repos/confluentinc/kafka/contributors","subscribers_url":"https://api.github.com/repos/confluentinc/kafka/subscribers","subscription_url":"https://api.github.com/repos/confluentinc/kafka/subscription","commits_url":"https://api.github.com/repos/confluentinc/kafka/commits{/sha}","git_commits_url":"https://api.github.com/repos/confluentinc/kafka/git/commits{/sha}","comments_url":"https://api.github.com/repos/confluentinc/kafka/comments{/number}","issue_comment_url":"https://api.github.com/repos/confluentinc/kafka/issues/comments{/number}","contents_url":"https://api.github.com/repos/confluentinc/kafka/contents/{+path}","compare_url":"https://api.github.com/repos/confluentinc/kafka/compare/{base}...{head}","merges_url":"https://api.github.com/repos/confluentinc/kafka/merges","archive_url":"https://api.github.com/repos/confluentinc/kafka/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/confluentinc/kafka/downloads","issues_url":"https://api.github.com/repos/confluentinc/kafka/issues{/number}","pulls_url":"https://api.github.com/repos/confluentinc/kafka/pulls{/number}","milestones_url":"https://api.github.com/repos/confluentinc/kafka/milestones{/number}","notifications_url":"https://api.github.com/repos/confluentinc/kafka/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/confluentinc/kafka/labels{/name}","releases_url":"https://api.github.com/repos/confluentinc/kafka/releases{/id}","created_at":"2015-04-16T22:32:49Z","updated_at":"2015-05-25T21:45:29Z","pushed_at":"2015-06-02T22:52:47Z","git_url":"git://github.com/confluentinc/kafka.git","ssh_url":"git@github.com:confluentinc/kafka.git","clone_url":"https://github.com/confluentinc/kafka.git","svn_url":"https://github.com/confluentinc/kafka","homepage":null,"size":16630,"stargazers_count":1,"watchers_count":1,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":1,"default_branch":"trunk"}},"_links":{"self":{"href":"https://api.github.com/repos/confluentinc/kafka/pulls/3"},"html":{"href":"https://github.com/confluentinc/kafka/pull/3"},"issue":{"href":"https://api.github.com/repos/confluentinc/kafka/issues/3"},"comments":{"href":"https://api.github.com/repos/confluentinc/kafka/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/confluentinc/kafka/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/confluentinc/kafka/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/confluentinc/kafka/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/confluentinc/kafka/statuses/0a5de8e0590e3a8dce1a91769ad41497b5e07d17"}}}}