Helpful Tools for Apache Kafka Developers
Tags: devops, apachekafka, kafka, eventstreaming
Published: 2021-07-08 19:59:42

<p><em>This blog post was originally published on the&nbsp;</em><a href="https://www.confluent.io/blog/best-kafka-tools-that-boost-developer-productivity/?utm_source=dev&utm_medium=blogpost&utm_campaign=tm.devx_ch.bp-kafka-tools-that-boost-developer-productivity_content.apache-kafka"><em>Confluent blog</em></a><em>.</em></p><p>Apache Kafka<sup>&reg;</sup> is at the core of a large ecosystem that includes powerful components, such as Kafka Connect and Kafka Streams. This ecosystem also includes many tools and utilities that make us, as Kafka developers, more productive while making our jobs easier and more enjoyable. Below, we&#39;ll take a look at a few of these tools and how they can help us get work done.</p>
<h2>kafkacat</h2>
<p>We like to save the best for last, but this tool is too good to wait. So, we&#39;ll start off by covering kafkacat.</p>
<p><a href="https://docs.confluent.io/platform/current/app-development/kafkacat-usage.html?_ga=2.221456093.492995071.1624902453-363840567.1611349348&utm_source=dev&utm_medium=blogpost&utm_campaign=tm.devx_ch.bp-kafka-tools-that-boost-developer-productivity_content.apache-kafka" rel="noopener noreferrer" target="_blank">kafkacat</a> is a fast and flexible command line Kafka producer, consumer, and more. Magnus Edenhill, the author of the librdkafka C/C++ library for Kafka, developed it. kafkacat is great for quickly producing and consuming data to and from a topic. In fact, the same command will do both, depending on the context. Check this out:</p><pre>$  ~ echo &quot;Hello World&quot; | kafkacat -b localhost:29092 -t hello-topic
% Auto-selecting Producer mode (use -P or -C to override)</pre>
<p>We&rsquo;ve sent data to <code>stdout</code> with echo and piped it to kafkacat. We only needed two simple flags: <code>-b</code> for the broker and <code>-t</code> for the topic. kafkacat realizes that we are sending it data and switches into producer mode. Now, we can read that data with the exact same kafkacat command:</p><pre>$  ~ kafkacat -b localhost:29092 -t hello-topic
% Auto-selecting Consumer mode (use -P or -C to override)
Hello World
% Reached end of topic hello-topic [0] at offset 1</pre>
<p>If we want to send a record with a key, we just need to use a delimiter and tell kafkacat what it is with the <code>-K</code> flag. In this case, we&#39;ll use a colon:</p><pre>$  ~ echo &quot;123:Jane Smith&quot; | kafkacat -b localhost:29092 -t customers -K:
% Auto-selecting Producer mode (use -P or -C to override)</pre>
<p>Again, the same kafkacat command will read the record from the topic:</p><pre>$  ~ kafkacat -b localhost:29092 -t customers -K:
% Auto-selecting Consumer mode (use -P or -C to override)
123:Jane Smith
% Reached end of topic customers [0] at offset 1</pre>
<p>Alternatively, we can leave the <code>-K</code> flag off when reading, if we only want the value:</p><pre>$  ~ kafkacat -b localhost:29092 -t customers
% Auto-selecting Consumer mode (use -P or -C to override)
Jane Smith
% Reached end of topic customers [0] at offset 1</pre>
<p>Note that piping data from <code>stdout</code> to kafkacat, as we did above, will spin up a producer, send the data, and then shut the producer down. To start a producer and leave it running to continue sending data, use the <code>-P</code> flag, as suggested by the <code>auto-selecting</code> message above.&nbsp;</p>
<p>The consumer will stay running just as the <code>kafka-console-consumer</code> would. In order to consume from a topic and immediately exit, we can use the <code>-e</code> flag.&nbsp;</p>
<p>To consume data that is in <code>Avro</code> format, we can use the <code>-s</code> flag. This flag can be used for the whole record <code>-s avro</code>, for just the key <code>-s key=avro</code>, or just the value <code>-s value=avro</code>. Here&#39;s an example using the <code>movies</code> topic from the popular <a href="https://kafka-tutorials.confluent.io/join-a-stream-to-a-table/kstreams.html?_ga=2.191112175.492995071.1624902453-363840567.1611349348&utm_source=dev&utm_medium=blogpost&utm_campaign=tm.devx_ch.bp-kafka-tools-that-boost-developer-productivity_content.apache-kafka">movie rating tutorial</a>:</p><pre>$  ~ kafkacat -C -b localhost:29092 -t movies -s value=avro -r http://localhost:8081
------------------------------------------------------
{&quot;id&quot;: 294, &quot;title&quot;: &quot;Die Hard&quot;, &quot;release_year&quot;: 1988}
{&quot;id&quot;: 354, &quot;title&quot;: &quot;Tree of Life&quot;, &quot;release_year&quot;: 2011}
{&quot;id&quot;: 782, &quot;title&quot;: &quot;A Walk in the Clouds&quot;, &quot;release_year&quot;: 1995}
{&quot;id&quot;: 128, &quot;title&quot;: &quot;The Big Lebowski&quot;, &quot;release_year&quot;: 1998}
{&quot;id&quot;: 780, &quot;title&quot;: &quot;Super Mario Bros.&quot;, &quot;release_year&quot;: 1993}</pre>
<p>There is a lot of power packed into this little tool, and there are many other flags that can be used with it. Running <code>kafkacat -h</code> will provide the complete list. For more great examples of kafkacat in action, <a href="https://rmoff.net/categories/kafkacat/" rel="noopener noreferrer" target="_blank">check out related posts</a> on Robin Moffatt&rsquo;s blog. One piece missing from kafkacat is the <a href="https://github.com/edenhill/kafkacat/issues/226" rel="noopener noreferrer" target="_blank">ability to produce data in <code>Avro</code> format</a>. As we saw, we can consume <code>Avro</code> with kafkacat using the Confluent Schema Registry, but we can&#39;t produce it. This leads us to our next tool.</p>
<h2>Confluent REST Proxy</h2>
<p><a href="https://docs.confluent.io/platform/current/kafka-rest/index.html?_ga=2.191112175.492995071.1624902453-363840567.1611349348&utm_source=dev&utm_medium=blogpost&utm_campaign=tm.devx_ch.bp-kafka-tools-that-boost-developer-productivity_content.apache-kafka">Confluent REST Proxy</a> is a feature-rich HTTP Kafka client. It can be used to provide Kafka support to applications written in a language without a native Kafka client. This is probably its most common use, but it can also be a handy developer tool. It can easily produce <code>Avro</code> data to a Kafka topic, as shown here:</p><pre>$ ~ curl -X POST \
-H &quot;Content-Type: application/vnd.kafka.avro.v2+json&quot; \
-H &quot;Accept: application/vnd.kafka.v2+json&quot; \
--data @newMovieData.json &quot;http://localhost:8082/topics/movies&quot;
------------------------------------------------------------------------------
{&quot;offsets&quot;:[{&quot;partition&quot;:0,&quot;offset&quot;:5,&quot;error_code&quot;:null,&quot;error&quot;:null}],&quot;key_schema_id&quot;:null,&quot;value_schema_id&quot;:3}</pre>
<p>REST Proxy is part of the Confluent Platform under the Confluent Community License, but it can be used on its own with any Kafka cluster. It can do a lot more than what we&rsquo;ll cover here, as you can <a href="https://docs.confluent.io/platform/current/kafka-rest/index.html?_ga=2.191112175.492995071.1624902453-363840567.1611349348&utm_source=dev&utm_medium=blogpost&utm_campaign=tm.devx_ch.bp-kafka-tools-that-boost-developer-productivity_content.apache-kafka">see from the docs</a>. As shown above, REST Proxy can be used from the command line with <code>curl</code> or something similar. It can also be used with tools such as Postman to build a user-friendly Kafka UI. Here&#39;s an example of producing to a topic with Postman (the <code>Content-Type</code> and <code>Accept</code> headers were set under the &ldquo;Headers&rdquo; tab):&nbsp;<img class="aligncenter wp-image-29190 fr-fic fr-dib" src="https://cdn.confluent.io/wp-content/uploads/producing-to-a-topic.png" alt="Producing to a topic with Postman" width="802" height="373"> As we can see from both the <code>curl</code> and Postman versions, REST Proxy does require that the schema for <code>Avro</code> messages be passed in with each produce request. A tool like Postman, which allows you to build up a library of saved queries, can make this easier to manage. To consume from topics with REST Proxy, we first create a consumer in a consumer group, then subscribe to a topic or topics, and finally fetch records to our heart&rsquo;s content. We&#39;ll switch back to <code>curl</code> so that we can see all the necessary bits at once. First, we <code>POST</code> to the consumer&rsquo;s endpoint with our consumer group name. In this <code>POST</code> request, we will pass a name for our new consumer instance, the internal data format (in this case, <code>Avro</code>), and the <code>auto.offset.reset</code> value.</p><pre>$ ~ curl -X POST  -H &quot;Content-Type: application/vnd.kafka.v2+json&quot; \
      --data &#39;{&quot;name&quot;: &quot;movie_consumer_instance&quot;, &quot;format&quot;: &quot;avro&quot;, &quot;auto.offset.reset&quot;: &quot;earliest&quot;}&#39; \
      http://localhost:8082/consumers/movie_consumers
------------------------------------------------------------------------------
{&quot;instance_id&quot;:&quot;movie_consumer_instance&quot;,&quot;base_uri&quot;:&quot;http://localhost:8082/consumers/movie_consumers/instances/movie_consumer_instance&quot;}</pre>
<p>This will return the <code>instance id</code> and base <code>URI</code> of the newly created consumer instance. Next, we&#39;ll use that <code>URI</code> to subscribe to a topic with a <code>POST</code> to the <code>subscription</code> endpoint.</p><pre>$  ~ curl -X POST -H &quot;Content-Type: application/vnd.kafka.v2+json&quot; --data &#39;{&quot;topics&quot;:[&quot;movies&quot;]}&#39; \      http://localhost:8082/consumers/movie_consumers/instances/movie_consumer_instance/subscription</pre>
<p>This doesn&#39;t return anything, but should get a <code>204</code> response. Now we can use a <code>GET</code> request to the <code>records</code> endpoint of that same <code>URI</code> to fetch records.</p><pre>$  ~ curl -X GET -H &quot;Accept: application/vnd.kafka.avro.v2+json&quot; \      http://localhost:8082/consumers/movie_consumers/instances/movie_consumer_instance/records
----------------------------------------------------------------------
[{&quot;topic&quot;:&quot;movies&quot;,&quot;key&quot;:null,&quot;value&quot;:{&quot;id&quot;: 294, &quot;title&quot;: &quot;Die Hard&quot;, &quot;release_year&quot;: 1988},&quot;partition&quot;:0,&quot;offset&quot;:0},
{&quot;topic&quot;:&quot;movies&quot;,&quot;key&quot;:null,&quot;value&quot;:{&quot;id&quot;: 354, &quot;title&quot;: &quot;Tree of Life&quot;, &quot;release_year&quot;: 2011},&quot;partition&quot;:0,&quot;offset&quot;:1},{&quot;topic&quot;:&quot;movies&quot;,&quot;key&quot;:null,&quot;value&quot;:{&quot;id&quot;: 782, &quot;title&quot;: &quot;A Walk in the Clouds&quot;, &quot;release_year&quot;: 1995},&quot;partition&quot;:0,&quot;offset&quot;:2},{&quot;topic&quot;:&quot;movies&quot;,&quot;key&quot;:null,&quot;value&quot;:{&quot;id&quot;: 128, &quot;title&quot;: &quot;The Big Lebowski&quot;, &quot;release_year&quot;: 1998},&quot;partition&quot;:0,&quot;offset&quot;:3},{&quot;topic&quot;:&quot;movies&quot;,&quot;key&quot;:null,&quot;value&quot;:{&quot;id&quot;: 780, &quot;title&quot;: &quot;Super Mario Bros.&quot;, &quot;release_year&quot;: 1993},&quot;partition&quot;:0,&quot;offset&quot;:4},{&quot;topic&quot;:&quot;movies&quot;,&quot;key&quot;:null,&quot;value&quot;:{&quot;id&quot;:101,&quot;title&quot;:&quot;Chariots of Fire&quot;,&quot;release_year&quot;:1981},&quot;partition&quot;:0,&quot;offset&quot;:5}]</pre>
<p>The consumer that we created will remain, and we can make the same <code>GET</code> request anytime to check for new data. If we no longer need this consumer, we can <code>DELETE</code> it using the base <code>URI</code>.</p><pre>$  ~ curl -X DELETE -H &quot;Content-Type: application/vnd.kafka.v2+json&quot; \    http://localhost:8082/consumers/movie_consumers/instances/movie_consumer_instance</pre>
<p>We can also get information about <code>brokers</code>, <code>topics</code>, and <code>partitions</code> with simple <code>GET</code> requests.</p><pre>$  ~ curl &quot;http://localhost:8082/brokers&quot;</pre><pre>$  ~ curl &quot;http://localhost:8082/topics&quot;</pre><pre>$  ~ curl &quot;http://localhost:8082/topics/movies&quot;</pre><pre>$  ~ curl &quot;http://localhost:8082/topics/movies/partitions&quot;</pre>
<p>These requests can return quite a bit of <code>JSON</code> data, which we&#39;ll leave off for the sake of space. However, this does lead us nicely to our next tool.</p>
<h2><code>jq</code>: A command line processor for JSON</h2>
<p>Though not specific to Kafka, <code>jq</code> is an incredibly helpful tool when working with other command line utilities that return <code>JSON</code> data. <code>jq</code> is a command line utility that allows us to format, manipulate, and extract data from the <code>JSON</code> output of other programs. Instructions for downloading and installing <code>jq</code> can be found on <a href="https://stedolan.github.io/jq/download" rel="noopener noreferrer" target="_blank">GitHub</a>, along with links to tutorials and other resources.&nbsp;</p>
<p>Let&#39;s go back and take a look at the REST Proxy output from the <code>GET</code> call to our consumer above. It&#39;s not the largest blob of <code>JSON</code> out there, but it&rsquo;s still a bit hard to read. Let&#39;s try again, this time piping the output to <code>jq</code>:</p><pre>$  ~ curl -X GET -H &quot;Accept: application/vnd.kafka.avro.v2+json&quot; \
      http://localhost:8082/consumers/movie_consumers/instances/movie_consumer_instance/records | jq

[
  {
    &quot;topic&quot;: &quot;movies&quot;,
    &quot;key&quot;: null,
    &quot;value&quot;: {
      &quot;id&quot;: 294,
      &quot;title&quot;: &quot;Die Hard&quot;,
      &quot;release_year&quot;: 1988
    },
    &quot;partition&quot;: 0,
    &quot;offset&quot;: 0
  },
  {
    &quot;topic&quot;: &quot;movies&quot;,
    &quot;key&quot;: null,
    &quot;value&quot;: {
      &quot;id&quot;: 354,
      &quot;title&quot;: &quot;Tree of Life&quot;,
      &quot;release_year&quot;: 2011
    },
    &quot;partition&quot;: 0,
    &quot;offset&quot;: 1
  },
  {
    &quot;topic&quot;: &quot;movies&quot;,
    &quot;key&quot;: null,
    &quot;value&quot;: {
      &quot;id&quot;: 782,
      &quot;title&quot;: &quot;A Walk in the Clouds&quot;,
      &quot;release_year&quot;: 1995
    },
    &quot;partition&quot;: 0,
    &quot;offset&quot;: 2
  },
  {
    &quot;topic&quot;: &quot;movies&quot;,
    &quot;key&quot;: null,
    &quot;value&quot;: {
      &quot;id&quot;: 128,
      &quot;title&quot;: &quot;The Big Lebowski&quot;,
      &quot;release_year&quot;: 1998
    },
    &quot;partition&quot;: 0,
    &quot;offset&quot;: 3
  },
  {
    &quot;topic&quot;: &quot;movies&quot;,
    &quot;key&quot;: null,
    &quot;value&quot;: {
      &quot;id&quot;: 780,
      &quot;title&quot;: &quot;Super Mario Bros.&quot;,
      &quot;release_year&quot;: 1993
    },
    &quot;partition&quot;: 0,
    &quot;offset&quot;: 4
  },
  {
    &quot;topic&quot;: &quot;movies&quot;,
    &quot;key&quot;: null,
    &quot;value&quot;: {
      &quot;id&quot;: 101,
      &quot;title&quot;: &quot;Chariots of Fire&quot;,
      &quot;release_year&quot;: 1981
    },
    &quot;partition&quot;: 0,
    &quot;offset&quot;: 5
  }
]</pre>
<p>It&rsquo;s much easier to read now but still a bit noisy. Let&#39;s say we only want the movie titles and their release years. We can do that easily with <code>jq</code>:</p><pre>$  ~ curl -X GET -H &quot;Accept: application/vnd.kafka.avro.v2+json&quot; \
      http://localhost:8082/consumers/movie_consumers/instances/movie_consumer_instance/records | jq \
      | jq &#39;.[] | {title: .value.title, year: .value.release_year}&#39;

{
  &quot;title&quot;: &quot;Die Hard&quot;,
  &quot;year&quot;: 1988
}
{
  &quot;title&quot;: &quot;Tree of Life&quot;,
  &quot;year&quot;: 2011
}
{
  &quot;title&quot;: &quot;A Walk in the Clouds&quot;,
  &quot;year&quot;: 1995
}
{
  &quot;title&quot;: &quot;The Big Lebowski&quot;,
  &quot;year&quot;: 1998
}
{
  &quot;title&quot;: &quot;Super Mario Bros.&quot;,
  &quot;year&quot;: 1993
}
{
  &quot;title&quot;: &quot;Chariots of Fire&quot;,
  &quot;year&quot;: 1981
}</pre>
<p>Let&#39;s take a look at what we just did (and you can <a href="https://jqplay.org/s/FZiB3AoAeo" rel="noopener noreferrer" target="_blank">follow along with the live example at jqplay</a>):</p>
<ol>
    <li>We piped the output from the REST Proxy to <code>jq</code>. The bit between the single quotes is a <code>jq</code> program with two steps. <code>jq</code> uses the same pipe character to pass the output of one step to the input of another.</li>
    <li>In our example, the first step in <code>jq</code> is an iterator, which will read each movie record from the array and pass it to the next step.</li>
    <li>The second step in <code>jq</code> creates a new <code>JSON</code> object from each record. The keys are arbitrary, but the values are derived from the input using <code>jq</code>&#39;s <code>identity</code> operator, <code>&#39;.&#39;</code>.</li>
</ol>
<p>Pretty cool, huh? There is much more that can be done with <code>jq</code>, and you can <a href="https://stedolan.github.io/jq/manual" rel="noopener noreferrer" target="_blank">read all about it in the documentation</a>. The way that <code>jq</code> operates on a stream of <code>JSON</code> data, allowing us to combine different operations in order to achieve our desired results, reminds me of Kafka Streams&mdash;bringing us to our final tool.</p>
<h2>Kafka Streams Topology Visualizer</h2>
<p>The <a href="https://zz85.github.io/kafka-streams-viz/" rel="noopener noreferrer" target="_blank">Kafka Streams Topology Visualizer</a> takes the text description of a Kafka Streams topology and produces a graphic representation showing input topics, processing nodes, interim topics, state stores, etc. It&#39;s a great way to get a big-picture view of a complex Kafka Streams topology. The topology for the movie ratings tutorial is not all that complex, but it will serve nicely to demonstrate this tool.&nbsp;</p>
<p>Here&#39;s the text of our topology, which we captured with the <code>Topology::describe</code> method:</p><pre>Topologies:
   Sub-topology: 0
    Source: KSTREAM-SOURCE-0000000000 (topics: [movies])
      --&gt; KSTREAM-MAP-0000000001
    Processor: KSTREAM-MAP-0000000001 (stores: [])
      --&gt; KSTREAM-SINK-0000000002
      &lt;-- KSTREAM-SOURCE-0000000000
    Sink: KSTREAM-SINK-0000000002 (topic: rekeyed-movies)
      &lt;-- KSTREAM-MAP-0000000001 Sub-topology: 1 Source: KSTREAM-SOURCE-0000000010 (topics: [KSTREAM-MAP-0000000007-repartition]) --&gt; KSTREAM-JOIN-0000000011
    Processor: KSTREAM-JOIN-0000000011 (stores: [rekeyed-movies-STATE-STORE-0000000003])
      --&gt; KSTREAM-SINK-0000000012
      &lt;-- KSTREAM-SOURCE-0000000010 Source: KSTREAM-SOURCE-0000000004 (topics: [rekeyed-movies]) --&gt; KTABLE-SOURCE-0000000005
    Sink: KSTREAM-SINK-0000000012 (topic: rated-movies)
      &lt;-- KSTREAM-JOIN-0000000011 Processor: KTABLE-SOURCE-0000000005 (stores: [rekeyed-movies-STATE-STORE-0000000003]) --&gt; none
      &lt;-- KSTREAM-SOURCE-0000000004 Sub-topology: 2 Source: KSTREAM-SOURCE-0000000006 (topics: [ratings]) --&gt; KSTREAM-MAP-0000000007
    Processor: KSTREAM-MAP-0000000007 (stores: [])
      --&gt; KSTREAM-FILTER-0000000009
      &lt;-- KSTREAM-SOURCE-0000000006 Processor: KSTREAM-FILTER-0000000009 (stores: []) --&gt; KSTREAM-SINK-0000000008
      &lt;-- KSTREAM-MAP-0000000007
    Sink: KSTREAM-SINK-0000000008 (topic: KSTREAM-MAP-0000000007-repartition)
      &lt;-- KSTREAM-FILTER-0000000009</pre>
<p>You may be adept at reading this kind of output, but most people will find a graphical representation very helpful:&nbsp;<img class="aligncenter wp-image-29192 fr-fic fr-dib" src="https://cdn.confluent.io/wp-content/uploads/kafka-streams-topology-visualizer-e1611097800555.png" alt="Kafka Streams Topology Visualizer" width="486" height="1404"> The Kafka Streams Topology Visualizer is a web app that you can host yourself (the source is available on <a href="https://github.com/zz85/kafka-streams-viz" rel="noopener noreferrer" target="_blank">GitHub</a>). For occasional use, the <a href="https://zz85.github.io/kafka-streams-viz" rel="noopener noreferrer" target="_blank">public hosted version</a> is probably sufficient.&nbsp;</p>
<p>A complex topology might be difficult to view all at once, so you can also visualize sub-topologies and then combine the images in a way that is easier to view. This can be a huge help in bringing new developers up to speed on an existing Kafka Streams application.</p>
<h3>ksqlDB topologies</h3>
<p><a href="https://www.confluent.io/product/ksql?utm_source=dev&utm_medium=blogpost&utm_campaign=tm.devx_ch.bp-kafka-tools-that-boost-developer-productivity_content.apache-kafka">ksqlDB</a> is an event streaming database that allows us to build complex topologies using syntax familiar to any SQL developer. Since ksqlDB is built on top of Kafka Streams, the Kafka Streams Topology Visualizer also works on these types of topologies.&nbsp;</p>
<p>We can get the topology description from ksqlDB with the <code>EXPLAIN</code> command. First, find the executing query:</p><pre>ksql&gt; SHOW QUERIES;

 Query ID              | Query Type | Status    | Sink Name      | Sink Kafka Topic | Query String
--------------------------------------------------------------------------------------------------------------------------
 CSAS_SHIPPED_ORDERS_0 | PERSISTENT | RUNNING:1 | SHIPPED_ORDERS | SHIPPED_ORDERS   | CREATE STREAM SHIPPED_ORDERS WITH 
 ...</pre>
<p>Now we can use that generated query name, <code>CSAS_SHIPPED_ORDERS_0</code>, to get the topology:</p><pre>ksql&gt; EXPLAIN CSAS_SHIPPED_ORDERS_0;</pre>
<p>This gives us a fair amount of output, so we won&#39;t show it all here, but toward the end, we see the topology description. Copying and pasting it into the visualizer results in this diagram:&nbsp;<img class="wp-image-29191 aligncenter fr-fic fr-dib" src="https://cdn.confluent.io/wp-content/uploads/ksqldb-topologies-e1611098767178.png" alt="Kafka Streams Topology Visualizer | ksqlDB topology" width="555" height="1583"></p>
<h2>Tip of the iceberg</h2>
<p>We&rsquo;ve looked at four helpful tools for Apache Kafka developers, but there are many others out there, which is one of the benefits of working in such a vibrant community. If there is a command line tool or a graphical application that you find helpful in getting the most out of Kafka, tell others about it. The <a href="https://forum.confluent.io/?_ga=2.220213213.492995071.1624902453-363840567.1611349348&utm_source=dev&utm_medium=blogpost&utm_campaign=tm.devx_ch.bp-kafka-tools-that-boost-developer-productivity_content.apache-kafka">Confluent Community Forum</a> is a great place to share this kind of information. We look forward to continuing this discussion with you there!</p>