<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bits & Bytes]]></title><description><![CDATA[Thoughts and ramblings by @riyaz-ali]]></description><link>https://riyazali.net</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 08:21:22 GMT</lastBuildDate><atom:link href="https://riyazali.net/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Observability in Action: Exploring logs, metrics and traces]]></title><description><![CDATA[In the previous posts, we discussed the Grafana Stack's components and how to set up a single-node deployment. Now, let's bring it all together by exploring how to visualize and analyze logs, metrics, and traces within Grafana. We'll use a simple exa...]]></description><link>https://riyazali.net/observability-in-action-exploring-logs-metrics-and-traces</link><guid isPermaLink="true">https://riyazali.net/observability-in-action-exploring-logs-metrics-and-traces</guid><category><![CDATA[Grafana]]></category><category><![CDATA[Grafana Monitoring]]></category><category><![CDATA[#prometheus]]></category><category><![CDATA[Grafana loki]]></category><category><![CDATA[observability]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Sun, 25 May 2025 10:51:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/21mJd5NUGZU/upload/d73d8b9ca0f808308f906a7892097e20.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the <a target="_blank" href="https://riyazali.net/series/grafana-stack">previous posts</a>, we discussed the Grafana Stack's components and how to set up a single-node deployment. Now, let's bring it all together by exploring how to visualize and analyze logs, metrics, and traces within Grafana. We'll use a simple example application, instrumented with <a target="_blank" href="https://opentelemetry.io">OpenTelemetry</a>, to generate the data, demonstrating the power of unified observability.</p>
<h2 id="heading-understanding-opentelemetry">Understanding OpenTelemetry</h2>
<p><a target="_blank" href="https://opentelemetry.io">OpenTelemetry</a> (often abbreviated as OTel) is an open-source observability framework providing APIs, SDKs, and tools to generate, collect, and export telemetry data (traces, metrics, and logs). It standardizes how observability data is produced and transmitted, promoting vendor neutrality and simplifying instrumentation across diverse systems.</p>
<h3 id="heading-why-opentelemetry-for-observability">Why OpenTelemetry for Observability?</h3>
<p>OTel is crucial for modern observability because:</p>
<ul>
<li><p><strong>Standardization</strong>: Instrument your application once and send data to various backends without code changes.</p>
</li>
<li><p><strong>Three Pillars</strong>: Directly supports collecting traces (request flow), metrics (numerical data), and logs (event records), increasingly with correlation.</p>
</li>
<li><p><strong>Vendor Neutrality</strong>: Offers flexibility to choose your preferred observability tools.</p>
</li>
<li><p><strong>Rich Ecosystem</strong>: A growing community provides SDKs and integrations for many technologies.</p>
</li>
</ul>
<h2 id="heading-sample-application-overview">Sample Application Overview</h2>
<p>To illustrate the concepts, we'll utilize a basic Go web service that simulates a "request processing" workflow. This application is designed to generate the three pillars of observability data:</p>
<ol>
<li><p><strong>Logs</strong>: It outputs log messages to <code>stdout</code>, which Grafana Alloy will collect and forward to Loki.</p>
</li>
<li><p><strong>Metrics</strong>: It produces standard HTTP metrics, such as a counter for total requests and a gauge for current active requests, which Prometheus will scrape.</p>
</li>
<li><p><strong>Traces</strong>: It emits distributed traces, including spans for the main request handler and simulated internal operations, which Tempo will ingest.</p>
</li>
</ol>
<p>This example application serves as a practical data source to help us understand how to query and visualize different types of observability data within Grafana.</p>
<p>To keep the article focused, and to not get into framework specifics I won’t be discussing the Go application in detail here. Its source (along with the manifest for <code>docker-compose</code>) can be found at <a target="_blank" href="https://github.com/riyaz-ali/observability-with-grafana-stack">riyaz-ali/observability-with-grafana-stack</a>.</p>
<h3 id="heading-running-the-application">Running the application</h3>
<p>To generate some sample data you need to run the application and generate some artificial load.</p>
<p>To start the application and bring up the stack run:</p>
<pre><code class="lang-bash">docker-compose up -d
</code></pre>
<p>Once the stack is up, make some API calls and generate some traffic. The repository comes with a <a target="_blank" href="https://k6.io"><code>k6</code></a> script <a target="_blank" href="https://github.com/riyaz-ali/observability-with-grafana-stack/blob/main/k6-script.js"><code>k6-script.js</code></a> that you can use to generate some load. To apply the <code>k6</code> script, run:</p>
<pre><code class="lang-bash">k6 run k6-script.js
</code></pre>
<p>This will generate some traffic and cause the application to emit logs, metrics and traces that we can then view in Grafana.</p>
<h2 id="heading-exploring-data-in-grafana">Exploring Data in Grafana</h2>
<p>Now, let's dive into Grafana and see our observability data! This is where the real magic happens ✨</p>
<h3 id="heading-logs-with-loki">Logs with Loki</h3>
<ul>
<li><p>Go to Grafana’s <strong>Explore</strong> view and select <strong>Loki</strong> from the data source dropdown</p>
</li>
<li><p>In the <a target="_blank" href="https://grafana.com/docs/loki/latest/query/">LogQL</a> query input, try the following queries to filter and view logs from the application</p>
<ul>
<li><p><code>{service_name=”jokes”}</code> : this will show all logs emitted by the application</p>
</li>
<li><p><code>{service_name="jokes"} | json | level="info"</code> : this will show all <code>info</code> logs</p>
</li>
<li><p><code>{service_name="jokes"} | json | level="info" | line_format "ip={{.remote}} path={{.path}}"</code> : you can also reformat the log line using <code>line_format</code> operator</p>
</li>
</ul>
</li>
<li><p>I encourage you to play around with different operators and filters in <a target="_blank" href="https://grafana.com/docs/loki/latest/query/">LogQL</a> ✌️</p>
</li>
</ul>
<h3 id="heading-metrics-with-prometheus">Metrics with Prometheus</h3>
<ul>
<li><p>Go to Grafana’s <strong>Explore</strong> view and select <strong>Prometheus</strong> from the data source dropdown</p>
</li>
<li><p>In the <a target="_blank" href="https://prometheus.io/docs/prometheus/latest/querying/basics/">PromQL</a> query input, try the following queries to explore metrics generated from the application</p>
<ul>
<li><p><code>rate(joke_fetched_total{job="jokes"}[1m])</code>: this shows the per-second rate of “how many jokes were fetched”. This shows how a custom, business-specifc metric can be queried and visualised</p>
</li>
<li><p><code>sum (rate(http_requests_total{job="jokes"}[1m]))</code> and <code>sum(rate(http_error_total{job="jokes"}[1m]))</code> shows the Requests/sec and Errors/sec rate. This also demonstrates how separate metrics can be plotted on the same graph to better understand the numbers in context.</p>
</li>
</ul>
</li>
</ul>
<p>In later articles in this series, we will deep-dive into more complex queries and visualize key latency metrics such as <code>P95</code>, <code>P90</code> and <code>P70</code>, undertsand what they mean and how we can query them using Prometheus.</p>
<h3 id="heading-traces-with-tempo">Traces with Tempo</h3>
<ul>
<li><p>Go to Grafana’s <strong>Explore</strong> view and select <strong>Tempo</strong> from the data source dropdown</p>
</li>
<li><p>In the TraceQL query input, try the following queries to view traces generated from the application</p>
<ul>
<li><p><code>{</code><a target="_blank" href="http://resource.service.name"><code>resource.service.name</code></a><code>="observability-with-grafana" }</code>: will show all traces generated from application</p>
</li>
<li><p><code>{</code><a target="_blank" href="http://resource.service.name"><code>resource.service.name</code></a><code>="observability-with-grafana" &amp;&amp; status=error}</code>: will show traces where an error had ocurred</p>
</li>
</ul>
</li>
</ul>
<p>When you select a specific trace it’ll open a detailed view showing a <a target="_blank" href="https://www.brendangregg.com/flamegraphs.html">flamegraph</a> of the trace and all the nested spans.</p>
]]></content:encoded></item><item><title><![CDATA[Beginner's Guide to setting up Grafana Stack]]></title><description><![CDATA[This post will guide you through setting up a single-node deployment of the Grafana Stack – including Grafana, Prometheus, Loki, and Tempo – using Docker Compose.
Component Setup
We’ll setup each component step-by-step, with annotated configuration s...]]></description><link>https://riyazali.net/beginners-guide-to-setting-up-grafana-stack</link><guid isPermaLink="true">https://riyazali.net/beginners-guide-to-setting-up-grafana-stack</guid><category><![CDATA[Grafana]]></category><category><![CDATA[#prometheus]]></category><category><![CDATA[Grafana Monitoring]]></category><category><![CDATA[Grafana loki]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Sun, 25 May 2025 10:18:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ErO0E8wZaTA/upload/bd6278044fb9e299185ccd8956e53f41.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This post will guide you through setting up a single-node deployment of the Grafana Stack – including Grafana, Prometheus, Loki, and Tempo – using Docker Compose.</p>
<h2 id="heading-component-setup">Component Setup</h2>
<p>We’ll setup each component step-by-step, with annotated configuration source.</p>
<h3 id="heading-loki">Loki</h3>
<p>Loki's architecture is microservices-based, horizontally scalable, and distributed system designed for multi-tenant log aggregation. It consists of multiple components that can run independently and in parallel.</p>
<p>Loki primarily uses two data types: 1) Index, which acts as a table-of-contents that helps locate logs based on specific labels, and 2) Chunks, which acts as containers that hold log entries for a particular set of labels.</p>
<p>All data, including both index and chunks, is stored in a single object storage backend like Amazon S3, Google Cloud Storage, or Azure Blob Storage. This is referred to as <a target="_blank" href="https://grafana.com/docs/loki/latest/configure/storage/#single-store">Single Store</a>, where the <em>same storage backend</em> is used for both the index as well as the chunks.</p>
<p>For this article, we will run Loki in “<a target="_blank" href="https://grafana.com/docs/loki/latest/get-started/deployment-modes/#monolithic-mode">monolithic mode</a>” with all components running simultaneously in one process. Monolithic mode is useful for getting started quickly to experiment with Loki, as well as for small read/write volumes of up to approximately 20GB per day.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">auth_enabled:</span> <span class="hljs-literal">false</span> <span class="hljs-comment"># for demonstration only!</span>

<span class="hljs-attr">server:</span>
  <span class="hljs-attr">http_listen_port:</span> <span class="hljs-number">3100</span>

<span class="hljs-attr">common:</span>
  <span class="hljs-attr">ring:</span>
    <span class="hljs-attr">instance_addr:</span> <span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>
    <span class="hljs-attr">kvstore:</span>
      <span class="hljs-attr">store:</span> <span class="hljs-string">inmemory</span>
  <span class="hljs-attr">replication_factor:</span> <span class="hljs-number">1</span>
  <span class="hljs-attr">path_prefix:</span> <span class="hljs-string">/tmp/loki</span>

<span class="hljs-attr">storage_config:</span>
  <span class="hljs-comment"># configures storing index in an object store in a prometheus TSDB-like format.</span>
  <span class="hljs-attr">tsdb_shipper:</span>
    <span class="hljs-comment"># Directory where ingesters would write index files which would then be</span>
    <span class="hljs-comment"># uploaded by shipper to configured storage</span>
    <span class="hljs-attr">active_index_directory:</span> <span class="hljs-string">"/loki/index"</span>

    <span class="hljs-comment"># Cache location for restoring index files from storage for queries</span>
    <span class="hljs-attr">cache_location:</span> <span class="hljs-string">"/loki/index_cache"</span>
    <span class="hljs-attr">cache_ttl:</span> <span class="hljs-string">24h</span> <span class="hljs-comment"># TTL for index files restored in cache for queries</span>

  <span class="hljs-comment"># configuring filesystem backend; for other supported stores see https://grafana.com/docs/loki/latest/configure/storage/#object-storage</span>
  <span class="hljs-comment"># for a real-world, production deployment, pick a reliable object store like s3, gcs, etc.</span>
  <span class="hljs-attr">filesystem:</span>
    <span class="hljs-comment"># directory to store chunks in</span>
    <span class="hljs-attr">directory:</span> <span class="hljs-string">"/loki/chunks"</span>

<span class="hljs-comment"># Log retention in Loki is achieved through the Compactor (https://grafana.com/docs/loki/latest/get-started/components/#compactor)</span>
<span class="hljs-attr">compactor:</span>
  <span class="hljs-attr">retention_enabled:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">delete_request_store:</span> <span class="hljs-string">filesystem</span>

<span class="hljs-attr">limits_config:</span>
  <span class="hljs-attr">retention_period:</span> <span class="hljs-string">15d</span> <span class="hljs-comment"># retention period to apply to stored data</span>

<span class="hljs-comment"># configures the chunk index schema and where it is stored.</span>
<span class="hljs-attr">schema_config:</span>
  <span class="hljs-comment"># configures what index schemas should be used for from specific time periods.</span>
  <span class="hljs-attr">configs:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">from:</span> <span class="hljs-number">2025-01-01</span>          <span class="hljs-comment"># since when this config should take effect; see: https://grafana.com/docs/loki/latest/configure/storage/#schema-config</span>
      <span class="hljs-attr">store:</span> <span class="hljs-string">tsdb</span>               <span class="hljs-comment"># storage used for index</span>
      <span class="hljs-attr">object_store:</span> <span class="hljs-string">filesystem</span>  <span class="hljs-comment"># storage used for chunks</span>
      <span class="hljs-attr">schema:</span> <span class="hljs-string">v13</span>
      <span class="hljs-attr">index:</span>
        <span class="hljs-attr">prefix:</span> <span class="hljs-string">index_</span>
        <span class="hljs-attr">period:</span> <span class="hljs-string">24h</span>
</code></pre>
<h3 id="heading-alloy">Alloy</h3>
<p><a target="_blank" href="https://grafana.com/oss/alloy-opentelemetry-collector/">Grafana Alloy</a> is an open source OpenTelemetry collector that acts as an agent to collect, transform and write logs to Loki (and other supported stores). It supersedes <a target="_blank" href="https://grafana.com/docs/agent/latest/">Grafana Agent</a> and <a target="_blank" href="https://grafana.com/docs/loki/latest/send-data/promtail/">Promtail</a>.</p>
<p>Alloy’s configuration is written in <a target="_blank" href="https://cuelang.org">CUE</a>-like configuration language. The following configuration configures Alloy to discover local containers, apply labels (like <code>service_name</code>, <code>project</code>, etc.) and push data to our Loki instance.</p>
<p>Alloy can do much more than this simple forward. Make sure to checkout its <a target="_blank" href="https://grafana.com/docs/alloy/latest/?pg=oss-alloy&amp;plcmt=hero-btn-3">documentation</a> to learn more.</p>
<pre><code class="lang-plaintext">// This configuration uses Grafana Alloy's native syntax (based on CUE)
// to scrape Docker container logs and forward them to Loki.

// discover all containers running on the docker instance
discovery.docker "containers" {
  host = "unix:///var/run/docker.sock"
}

// relabel configuration to annotate entry with service_name, instance_id etc.
discovery.relabel "add_metadata" {
  targets = []

  rule {
    source_labels = ["__meta_docker_container_label_com_docker_compose_service"]
    target_label  = "service_name"
  }

  rule {
    source_labels = ["__meta_docker_container_label_com_docker_compose_project"]
    target_label  = "project"
  }

  rule {
    source_labels = ["__meta_docker_container_id"]
    target_label  = "instance_id"
  }
}

// define a loki.source.docker component to scrape logs from discovered docker containers.
loki.source.docker "docker_logs" {
  host = "unix:///var/run/docker.sock"
  targets = discovery.docker.containers.targets

  relabel_rules = discovery.relabel.add_metadata.rules

  forward_to = [loki.write.default.receiver] // connect the output to relabel configuration below
}

// define a loki.write component to send the processed logs to the Loki instance.
loki.write "default" {
  endpoint {
    url = "http://loki:3100/loki/api/v1/push" // Loki push endpoint
  }
}
</code></pre>
<h3 id="heading-prometheus">Prometheus</h3>
<p>Unlike Loki, Prometheus is deployed as a single service / component. Scaling and high-availability of Prometheus is achieved using alternative tools like <a target="_blank" href="https://thanos.io">Thanos</a> or <a target="_blank" href="https://grafana.com/oss/mimir/">Grafana Mimir</a>, but is outside the scope of this article.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">global:</span>
  <span class="hljs-attr">scrape_interval:</span> <span class="hljs-string">15s</span> <span class="hljs-comment"># How frequently to scrape targets.</span>
  <span class="hljs-attr">evaluation_interval:</span> <span class="hljs-string">15s</span> <span class="hljs-comment"># How frequently to evaluate rules.</span>

<span class="hljs-attr">scrape_configs:</span>
  <span class="hljs-comment"># Job 'prometheus' scrapes metrics from prometheus instance itself</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">job_name:</span> <span class="hljs-string">'prometheus'</span>
    <span class="hljs-attr">static_configs:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">targets:</span> [<span class="hljs-string">'localhost:9090'</span>]
</code></pre>
<h3 id="heading-tempo">Tempo</h3>
<p>Tempo can be deployed in <em>monolithic</em> or <em>microservices</em> modes. The only external dependency required is an object store, though Tempo also supports using the local filesystem as the backend for trace storage.</p>
<p>For this article, we’ll deploy a monolithic / single-binary configuration with filesystem storage. For production deployment, the general recommendation is to use Object Store such as S3, GCS, etc.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">server:</span>
  <span class="hljs-attr">http_listen_port:</span> <span class="hljs-number">3200</span>

<span class="hljs-comment"># Distributors receive spans and forward them to the appropriate ingesters.</span>
<span class="hljs-comment"># The following configuration enables OpenTelemetry receiver</span>
<span class="hljs-attr">distributor:</span>
  <span class="hljs-attr">receivers:</span>
    <span class="hljs-attr">otlp:</span>
      <span class="hljs-attr">protocols:</span>
        <span class="hljs-attr">grpc:</span>
        <span class="hljs-attr">http:</span>

<span class="hljs-comment"># The ingester is responsible for batching up traces and pushing them to TempoDB.</span>
<span class="hljs-attr">ingester:</span>
  <span class="hljs-attr">max_block_duration:</span> <span class="hljs-string">5m</span>

<span class="hljs-comment"># Compactors stream blocks from the storage backend, combine them and write them back.</span>
<span class="hljs-attr">compactor:</span>
  <span class="hljs-attr">compaction:</span>
    <span class="hljs-attr">compaction_window:</span> <span class="hljs-string">1h</span>

<span class="hljs-comment"># Storage block configures TempoDB. See https://grafana.com/docs/tempo/latest/configuration/#storage</span>
<span class="hljs-attr">storage:</span>
  <span class="hljs-attr">trace:</span>
    <span class="hljs-attr">backend:</span> <span class="hljs-string">local</span>
    <span class="hljs-attr">local:</span> <span class="hljs-comment"># configuration block for local storage</span>
      <span class="hljs-attr">path:</span> <span class="hljs-string">/tmp/tempo/blocks</span>
    <span class="hljs-attr">wal:</span>   <span class="hljs-comment"># configuration block for the Write Ahead Log (WAL)</span>
      <span class="hljs-attr">path:</span> <span class="hljs-string">/tmp/tempo/wal</span>
</code></pre>
<h3 id="heading-docker-compose">Docker Compose</h3>
<p>With this we have all our components configured 🚀 Next, we’ll use Docker Compose and create a deployment for our stack.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Make sure the configuration files are placed in the correct location, under <code>scripts/</code> for docker compose setup to work.</div>
</div>

<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">'3.8'</span>

<span class="hljs-attr">networks:</span>
  <span class="hljs-attr">grafana-net:</span>
    <span class="hljs-attr">driver:</span> <span class="hljs-string">bridge</span>

<span class="hljs-attr">volumes:</span>
  <span class="hljs-attr">grafana_data:</span>
  <span class="hljs-attr">prometheus_data:</span>
  <span class="hljs-attr">loki_data:</span>
  <span class="hljs-attr">tempo_data:</span>

<span class="hljs-attr">services:</span>
  <span class="hljs-comment"># Grafana dashboard service accessible over port 3030</span>
  <span class="hljs-attr">grafana:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">grafana/grafana:latest</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">grafana</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"3030:3000"</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">grafana_data:/var/lib/grafana</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">grafana-net</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">prometheus</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">loki</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">tempo</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">GF_AUTH_ANONYMOUS_ENABLED=true</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">GF_AUTH_ANONYMOUS_ORG_ROLE=Admin</span> <span class="hljs-comment"># Allows anonymous users to have Admin role</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>

  <span class="hljs-comment"># Prometheus monitoring service</span>
  <span class="hljs-attr">prometheus:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">prom/prometheus:latest</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">prometheus</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./scripts/prometheus.yml:/etc/prometheus/prometheus.yml</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">prometheus_data:/prometheus</span>
    <span class="hljs-attr">command:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">'--config.file=/etc/prometheus/prometheus.yml'</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">'--storage.tsdb.path=/prometheus'</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">grafana-net</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>

  <span class="hljs-comment"># Loki Service (Log Aggregation)</span>
  <span class="hljs-attr">loki:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">grafana/loki:3.5</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">loki</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./scripts/loki.yml:/etc/loki/config.yaml</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">loki_data:/loki</span>
    <span class="hljs-attr">command:</span> <span class="hljs-string">-config.file=/etc/loki/config.yaml</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">grafana-net</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>

  <span class="hljs-comment"># Tempo Service (Distributed Tracing)</span>
  <span class="hljs-attr">tempo:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">grafana/tempo:2.7.0</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">tempo</span>
    <span class="hljs-attr">user:</span> <span class="hljs-string">root</span> <span class="hljs-comment"># to temporarily fix permission issues; do not use on prod</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./scripts/tempo.yml:/etc/tempo/config.yaml</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">tempo_data:/tmp/tempo</span>
    <span class="hljs-attr">command:</span> <span class="hljs-string">-config.file=/etc/tempo/config.yaml</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">grafana-net</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>

  <span class="hljs-comment"># Grafana Alloy Service (Agent for Logs and Metrics)</span>
  <span class="hljs-attr">alloy:</span>
      <span class="hljs-attr">image:</span> <span class="hljs-string">grafana/alloy:v1.8.3</span>
      <span class="hljs-attr">container_name:</span> <span class="hljs-string">alloy</span>
      <span class="hljs-attr">volumes:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">./scripts/config.alloy:/etc/config.alloy</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">/var/lib/docker/containers:/var/lib/docker/containers:ro</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">/var/run/docker.sock:/var/run/docker.sock:ro</span>
      <span class="hljs-attr">command:</span> <span class="hljs-string">run</span> <span class="hljs-string">/etc/config.alloy</span> <span class="hljs-string">--server.http.listen-addr=0.0.0.0:12345</span>
      <span class="hljs-attr">networks:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">grafana-net</span>
      <span class="hljs-attr">depends_on:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">loki</span>
      <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>
</code></pre>
<p>Next, run <code>docker-compose up -d</code> to start all the services and go to http://localhost:3030</p>
<h2 id="heading-configuring-grafana">Configuring Grafana</h2>
<p>After you’ve setup all services, head over to Grafana and add data sources for Loki, Prometheus and Tempo.</p>
<h3 id="heading-adding-a-new-data-source">Adding a new data source</h3>
<p>To add a new data source, follow the steps below:</p>
<ul>
<li><p>Go to <a target="_blank" href="http://localhost:3030/connections/datasources">datasources page</a></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748012482102/8a176624-453f-4d94-8ce8-097599cb9b3b.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Pick the connection type. Here, we’ll pick Loki. Enter the URL to the Loki instance.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748012618298/ade9e3f8-c599-43a8-8b41-dc526679aedc.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Click on “Save &amp; Test”. It’ll create a new data source.</p>
</li>
</ul>
<p>Repeat the same steps and add data source for Prometheus and Tempo as well.</p>
<hr />
<p>In the next article, we’ll deploy a sample application that generates logs, metric and traces, and use Grafana to setup an observability dashboard 🚀</p>
]]></content:encoded></item><item><title><![CDATA[Observability With Grafana Stack]]></title><description><![CDATA[In modern software systems, especially those with distributed architectures, merely knowing "what happened" isn't enough. We also need to understand "why it happened".
This is the essence of observability, a critical capability for maintaining system...]]></description><link>https://riyazali.net/observability-with-grafana-stack</link><guid isPermaLink="true">https://riyazali.net/observability-with-grafana-stack</guid><category><![CDATA[Grafana]]></category><category><![CDATA[observability]]></category><category><![CDATA[monitoring]]></category><category><![CDATA[Reliability]]></category><category><![CDATA[#prometheus]]></category><category><![CDATA[Grafana Monitoring]]></category><category><![CDATA[Grafana loki]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Thu, 22 May 2025 13:55:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/JKUTrJ4vK00/upload/cf948c316374873610c066dacd6e762c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In modern software systems, especially those with distributed architectures, merely knowing <em>"what happened"</em> isn't enough. We also need to understand <em>"why it happened".</em></p>
<p>This is the essence of observability, a critical capability for maintaining system health and accelerating incident resolution. This post will explore the Grafana Stack, an open-source powerhouse that unifies metrics, logs, and traces to deliver comprehensive observability for today's IT and DevOps challenges.</p>
<h2 id="heading-what-is-observability">What is Observability?</h2>
<p>Observability is the ability to understand a system's internal state by examining its external outputs. Unlike traditional monitoring, which often focuses on predefined alerts for known issues, observability provides the necessary insights to debug novel problems, leading to faster <a target="_blank" href="https://www.pagerduty.com/resources/devops/learn/what-is-mttr/#heading-2">Mean Time To Resolution (MTTR)</a>.</p>
<h3 id="heading-importance-of-observability-in-it-and-devops">Importance of Observability in IT and DevOps</h3>
<p>For fast-moving IT and DevOps teams, robust observability is non-negotiable. It provides the visibility required to proactively identify issues, understand system behavior under various loads, and pinpoint root causes rapidly. This capability directly translates to improved system reliability, enhanced performance, and a better user experience.</p>
<h2 id="heading-enter-the-grafana-stack">Enter, the Grafana Stack</h2>
<p>The Grafana Stack is a collection of open-source tools designed to provide a comprehensive observability solution. At its core is <strong>Grafana</strong>, a powerful <strong>visualization and analytics platform</strong>, complemented by specialized tools like <strong>Prometheus for metrics</strong>, <strong>Loki for logs</strong>, and <strong>Tempo for traces</strong>. Together, they offer a unified view of your system's health.</p>
<h3 id="heading-components-of-the-grafana-stack">Components of the Grafana Stack</h3>
<p>The Grafana Stack is built upon a synergy of specialized tools, each contributing a vital piece to the observability puzzle.</p>
<h3 id="heading-grafana">Grafana</h3>
<p><a target="_blank" href="https://grafana.com/grafana/">Grafana</a> serves as <strong>the visualization layer</strong>, bringing together data from various sources into intuitive dashboards.</p>
<p>It is an open-source platform for monitoring and observability that allows you to query, visualize, alert on, and understand your metrics, logs, and traces no matter where they are stored.</p>
<p>Its key features include highly customizable dashboards, support for numerous data sources, alerting capabilities, and a rich ecosystem of plugins, making it the central hub for observing your systems. It provides <em>a single pane of glass</em> for all three pillars of observability.</p>
<h3 id="heading-prometheus">Prometheus</h3>
<p><a target="_blank" href="http://prometheus.io">Prometheus</a> is a leading open-source monitoring system that <strong>collects and stores metrics as time series data</strong>. It’s an open-source monitoring system with a flexible data model, powerful query language (<a target="_blank" href="https://prometheus.io/docs/prometheus/latest/querying/basics/">PromQL</a>), and robust alerting capabilities. It primarily focuses on collecting numerical time series data.</p>
<p>It's crucial for collecting and storing metrics, enabling real-time monitoring and sophisticated alerting based on predefined thresholds and patterns in your system's performance. It forms the metrics pillar of the Grafana Stack.</p>
<h3 id="heading-loki">Loki</h3>
<p><a target="_blank" href="https://grafana.com/oss/loki/">Loki</a> is a <strong>log aggregation system</strong> designed to be highly cost-effective and easy to operate. It’s a horizontally scalable, highly available, multi-tenant log aggregation system inspired by Prometheus. It <em>indexes metadata about logs</em> rather than the logs themselves, making it very efficient.</p>
<p>Loki excels at collecting and storing logs from various sources. Its unique indexing approach allows for efficient log aggregation and powerful analysis using LogQL, enabling quick searching and filtering of vast amounts of log data.</p>
<h3 id="heading-tempo">Tempo</h3>
<p><a target="_blank" href="https://grafana.com/oss/tempo/">Tempo</a> is an open-source, high-volume <strong>distributed tracing backend</strong>. It’s an open-source distributed tracing backend designed for high scale and low cost. It ingests traces from various sources like <a target="_blank" href="https://www.jaegertracing.io">Jaeger</a>, <a target="_blank" href="https://zipkin.io">Zipkin</a>, and <a target="_blank" href="https://opentelemetry.io">OpenTelemetry</a>, and stores them efficiently.</p>
<p>Tempo is essential for distributed tracing, allowing you to follow the journey of a request as it propagates through multiple services in a microservices architecture. This provides deep visibility into latency, errors, and the flow of execution, completing the traces pillar of the Grafana Stack.</p>
<hr />
<p>In the next article, we’ll discuss how you can setup Grafana stack and have it up and running 🚀</p>
]]></content:encoded></item><item><title><![CDATA[The less taken path with sqlite]]></title><description><![CDATA[Lately, I've been tinkering around a bit with sqlite3, and this post contains a brief of some exciting set of features and interfaces that I've re-discovered during the process.

sqlite3 isn't exactly new. It's been around for almost two decades now ...]]></description><link>https://riyazali.net/the-less-taken-path-with-sqlite</link><guid isPermaLink="true">https://riyazali.net/the-less-taken-path-with-sqlite</guid><category><![CDATA[SQLite]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Sat, 27 Mar 2021 02:00:00 GMT</pubDate><content:encoded><![CDATA[<p>Lately, I've been tinkering around a bit with <code>sqlite3</code>, and this post contains a brief of some exciting set of features and interfaces that I've re-discovered during the process.</p>
<hr />
<p><code>sqlite3</code> isn't exactly new. It's been around for almost two decades now (much longer than I've known coding myself 😛). There's plethora of articles on the internet describing <a target="_blank" href="https://www.sqlite.org/about.html">what it is</a>, what makes it special, <a target="_blank" href="https://www.sqlite.org/whentouse.html">when you should ideally use it</a> (and when not) and why <em><a target="_blank" href="https://unixsheikh.com/articles/sqlite-the-only-database-you-will-ever-need-in-most-cases.html">"it's the only database you will ever need"</a>.</em></p>
<p>So, I'm not gonna repeat all those advices here. Instead I'll try to cover some of other exciting, specialised interfaces that <code>sqlite3</code> offers and how we can profit from it!</p>
<hr />
<h3 id="heading-1-custom-functions-in-sql">#1 Custom functions in SQL</h3>
<p><code>sqlite3</code> provides support for registering <a target="_blank" href="https://www.sqlite.org/appfunc.html">custom, application-defined functions</a> in C that can be exposed to queries in SQL.</p>
<p>Custom functions can be used to integrate your queries with the rest of the system, or provide access to external functionality. They can be used to perform complex calculation or do statistical operations on data.</p>
<p>Custom functions can be used to marshal / un-marshal and / or manipulate data in alternative formats (such as <code>json</code>). They can be used to compute hashes and do much more!</p>
<p><code>sqlite3</code> comes with a bunch of built-in <a target="_blank" href="https://www.sqlite.org/lang_corefunc.html">scalar</a> and <a target="_blank" href="https://www.sqlite.org/lang_aggfunc.html">aggregate</a> functions, and with <a target="_blank" href="https://www.sqlite.org/lang_datefunc.html">routines to manipulate date / time information</a>. There is also <a target="_blank" href="https://github.com/nalgeon/sqlean">nalgeon/sqlean</a> on Github that aims to pack a lot more set of functions into convenient extensions that can be loaded on-demand.</p>
<h3 id="heading-2-virtual-tables">#2 Virtual Tables</h3>
<p><a target="_blank" href="http://sqlite.org/vtab.html">Virtual Tables</a> are one of the most exciting features of <code>sqlite3</code> that I found! Essentially, virtual table allows us to register objects with <code>sqlite3</code> that, from the perspective of an SQL statement, looks like any other table / view.</p>
<p>This allows the user to be able to query them just as they would do with any other table / view. When a user executes a query against a virtual table <code>sqlite3</code> invokes callback methods on the virtual table object.</p>
<p>This has the potential to unlock a ton of different use-cases. For eg., there's an <a target="_blank" href="https://www.sqlite.org/csv.html">official</a> <a target="_blank" href="https://www.sqlite.org/csv.html"><code>csv</code></a> <a target="_blank" href="https://www.sqlite.org/csv.html">virtual table implementation</a> that allow users to query data from a <code>csv</code> file just as they would with a normal table. There are other implementations that make it possible to interface with other systems, such as <a target="_blank" href="https://github.com/augmentable-dev/askgit">augmentable-dev/askgit</a> uses <code>sqlite3</code> virtual tables to allow users to query data from <code>git</code> repositories, <a target="_blank" href="https://osquery.io">osquery.io</a> that allow users to run queries against the operating systems!</p>
<h3 id="heading-3-authorizer-to-check-limit-what-a-user-can-query">#3 Authorizer to check / limit what a user can query</h3>
<p><code>sqlite3</code> supports registering <a target="_blank" href="https://www.sqlite.org/c3ref/set_authorizer.html">a custom authorizer function</a> that can limit what data a query can access and what action can it perform. This, together with <a target="_blank" href="https://www.sqlite.org/security.html">other defensive settings</a>, can be used to turn <code>sqlite3</code> into a sandbox where we can execute raw, user-supplied, untrusted statements <em>with confidence</em> that it won't cause any un-intended <em>side-effects.</em></p>
<h3 id="heading-4-capture-a-change-set-of-differences-in-a-session">#4 Capture a change-set of differences in a session</h3>
<p><a target="_blank" href="https://www.sqlite.org/sessionintro.html"><code>sqlite3</code> session extension</a> provides a mechanism for recording changes to some or all of the <em>rowid tables</em> in an SQLite database, and packaging those changes into a "changeset" file that can later be used to apply the same set of changes to another database. This can be used to capture <em>diffs</em> generated by multiple users, working asynchronously, capturing and merging it together into a unified database file.</p>
<p>Sessions can be useful when <code>sqlite3</code> is used as an <em>application data format</em> __ and multiple users work on the same file at the same time. Each user can generate a patch for their side of work (much like how one would do it with a vcs like <code>git</code>) and the system could combine those into a unified database file.</p>
<h3 id="heading-5-online-backup-api">#5 Online Backup API</h3>
<p><a target="_blank" href="https://www.sqlite.org/backup.html"><code>sqlite3</code>Online Backup API</a> allows the contents of one database to be copied into another database, in an incremental fashion where the database is only locked for the brief periods of time when it is actually being read from. This allows other database users to continue uninterrupted while a backup of an online database is made.</p>
<p>It provides a basic building block onto which other, more complex replication solutions can be built.</p>
<h3 id="heading-6-dynamically-loaded-extensions">#6 Dynamically loaded extensions</h3>
<p><code>sqlite3</code> has <a target="_blank" href="https://www.sqlite.org/loadext.html">support for building extensions</a> that can either be loaded dynamically (as a shared object file) or linked statically into the final build.</p>
<p>The <a target="_blank" href="https://sqlite.org/src/file?name=src/sqlite3ext.h&amp;ci=trunk"><code>sqlite3ext.h</code></a> defines the Extension API which the module can use to interact with the database connection (that loaded the extension). The extension can do pretty much anything that you could normally do with the <code>sqlite3</code> core, like registering custom functions, defining virtual table modules and more!</p>
<p>One should consider building re-usable modules as loadable extensions to allow for easier distribution and better re-use.</p>
<hr />
<p>In the follow-up articles, I would try to cover some of the features I've discussed here and how one can leverage those while coding with Golang using <a target="_blank" href="http://go.riyazali.net/sqlite">http://go.riyazali.net/sqlite</a>, a library that I recently open-sourced 🤗</p>
]]></content:encoded></item><item><title><![CDATA[Berkeley Packet Filter in Golang]]></title><description><![CDATA[Recently I stumbled upon a use case where I was looking to setup a Wireguard (udp) tunnel across two nodes behind different NATs. I wanted to implement something like 
UDP Hole Punching and came across this mailing list message
from 2016 which linked...]]></description><link>https://riyazali.net/berkeley-packet-filter-in-golang</link><guid isPermaLink="true">https://riyazali.net/berkeley-packet-filter-in-golang</guid><category><![CDATA[golang]]></category><category><![CDATA[networking]]></category><category><![CDATA[#howtos]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Sun, 24 Jan 2021 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>Recently I stumbled upon a use case where I was looking to setup a Wireguard (udp) tunnel across two nodes behind different NATs. I wanted to implement something like 
<a target="_blank" href="https://en.wikipedia.org/wiki/UDP_hole_punching">UDP Hole Punching</a> and came across <a target="_blank" href="https://lists.zx2c4.com/pipermail/wireguard/2016-August/000372.html">this mailing list message</a>
from 2016 which linked to the <a target="_blank" href="https://git.zx2c4.com/wireguard-tools/tree/contrib/nat-hole-punching"><code>contrib/nat-hole-punching</code></a> source in Wireguard.</p>
<p>I'll cover the whole <em>hole punching</em> mechanism, perhaps, in a different article. But for context, the mentioned source used <a target="_blank" href="https://linux.die.net/man/7/raw"><code>raw</code> linux sockets</a>
and <a target="_blank" href="https://en.wikipedia.org/wiki/Berkeley_Packet_Filter"><em>classic</em> Berkeley Packet Filter</a> to inject custom packets and do hole punching. </p>
<p>The source is written in C but I wanted my implementation in Golang. So, I started looking and soon came across <a target="_blank" href="https://pkg.go.dev/golang.org/x/net/bpf"><code>golang.org/x/net/bpf</code></a>
which provides an implementation of raw <code>bpf</code> assembly codes and <a target="_blank" href="https://pkg.go.dev/golang.org/x/net/bpf#VM">a virtual machine</a> written in Golang. I wanted to use the assembly codes but not necessarily depend on the <code>bpf.VM</code> (that would've defeated the purpose of filters in the first place 😅).</p>
<p>Instead, I started looking for ways in which I could use <a target="_blank" href="https://linux.die.net/man/2/setsockopt"><code>setsockopt</code></a> with <code>SO_ATTACH_FILTER</code> to attach the filter directly to the native
file descriptor. I came across <a target="_blank" href="https://pkg.go.dev/golang.org/x/net/ipv4#PacketConn.SetBPF"><code>ipv4#PacketConn.SetBPF</code></a> method from <a target="_blank" href="https://pkg.go.dev/golang.org/x/net/ipv4"><code>golang.org/x/net/ipv4</code></a> which takes in a <code>[]bpf.RawInstructions</code> and applies it onto the underlying socket, although the socket in this case wasn't exactly the <code>raw</code> socket I was working with.</p>
<p>To circumvent this, I started looking further into the source, till I found <a target="_blank" href="https://github.com/golang/net/blob/5f4716e94777e714bc2fb3e3a44599cb40817aac/ipv4/sys_bpf.go#L17-L24"><code>sockOpt.setAttachFilter</code></a> and, consequently, <a target="_blank" href="https://github.com/golang/net/blob/5f4716e94777e714bc2fb3e3a44599cb40817aac/internal/socket/sys_unix.go#L20-L23"><code>setsockopt</code>'s implementation on unix</a>. The <code>setsockopt</code> used <a target="_blank" href="https://pkg.go.dev/syscall#Syscall6"><code>syscall.Syscall6</code></a> with 
<code>syscall.SYS_SETSOCKOPT</code> to implement the system call and passed through the given arguments as <code>unsafe.Pointer</code> to the syscall. </p>
<h3 id="heading-putting-it-all-together">Putting it all together</h3>
<p>After all this I came with something close the following code snippet to enable using berkeley filter with sockets in Golang 🚀</p>
<pre><code class="lang-Golang"><span class="hljs-keyword">package</span> filter

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"golang.org/x/net/bpf"</span>
    <span class="hljs-string">"golang.org/x/sys/unix"</span>

    <span class="hljs-string">"syscall"</span>
    <span class="hljs-string">"unsafe"</span>
)

<span class="hljs-comment">// Filter represents a classic BPF filter program that can be applied to a socket</span>
<span class="hljs-keyword">type</span> Filter []bpf.Instruction

<span class="hljs-comment">// ApplyTo applies the current filter onto the provided file descriptor</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(filter Filter)</span> <span class="hljs-title">ApplyTo</span><span class="hljs-params">(fd <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(err error)</span></span> {
    <span class="hljs-keyword">var</span> assembled []bpf.RawInstruction
    <span class="hljs-keyword">if</span> assembled, err = bpf.Assemble(filter); err != <span class="hljs-literal">nil</span> {
        <span class="hljs-keyword">return</span> err
    }

    <span class="hljs-keyword">var</span> program = unix.SockFprog{
        Len: <span class="hljs-keyword">uint16</span>(<span class="hljs-built_in">len</span>(assembled)), 
        Filter: (*unix.SockFilter)(unsafe.Pointer(&amp;assembled[<span class="hljs-number">0</span>])),
    }
    <span class="hljs-keyword">var</span> b = (*[unix.SizeofSockFprog]<span class="hljs-keyword">byte</span>)(unsafe.Pointer(&amp;program))[:unix.SizeofSockFprog]

    <span class="hljs-keyword">if</span> _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT,
        <span class="hljs-keyword">uintptr</span>(fd), <span class="hljs-keyword">uintptr</span>(syscall.SOL_SOCKET), <span class="hljs-keyword">uintptr</span>(syscall.SO_ATTACH_FILTER),
        <span class="hljs-keyword">uintptr</span>(unsafe.Pointer(&amp;b[<span class="hljs-number">0</span>])), <span class="hljs-keyword">uintptr</span>(<span class="hljs-built_in">len</span>(b)), <span class="hljs-number">0</span>); errno != <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> errno
    }

    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
}
</code></pre>
<p>Using this is simple too! You just have to define the filter program using <code>bpf</code> assembly codes, like:</p>
<pre><code class="lang-Golang"><span class="hljs-comment">// filter packet by checking if they are destined to local port 8080</span>
<span class="hljs-keyword">var</span> filter = Filter{
    bpf.LoadAbsolute{Off: <span class="hljs-number">22</span>, Size: <span class="hljs-number">2</span>},  <span class="hljs-comment">// load the destination port</span>
    bpf.JumpIf{Val: <span class="hljs-number">8080</span>, SkipFalse: <span class="hljs-number">1</span>}, <span class="hljs-comment">// if Val != 8080 skip next instruction</span>

    bpf.RetConstant{Val: <span class="hljs-number">0xffff</span>}, <span class="hljs-comment">// return 0xffff bytes (or less) from packet</span>
    bpf.RetConstant{Val: <span class="hljs-number">0x0</span>},    <span class="hljs-comment">// return 0 bytes, effectively ignore this packet</span>
}
</code></pre>
<p>and call <code>ApplyTo</code> on the socket's file descriptor.</p>
<pre><code class="lang-Golang"><span class="hljs-comment">// import "syscall"</span>

<span class="hljs-comment">// open a raw socket</span>
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP)
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-comment">// ... define error handling</span>
}

<span class="hljs-comment">// then apply the filter</span>
err = filter.ApplyTo(fd)
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-comment">// ... define error handling</span>
}
</code></pre>
<p>And that's it! the kernel would filter out packets based on specified filter program and next time you do a <code>syscall.Read</code> on your <code>fd</code> you'd only see the packets you're interested in 🎉 🚀</p>
]]></content:encoded></item><item><title><![CDATA[Using interfaces in Go]]></title><description><![CDATA[A lot have changed in the past few months!
I've started a new job @ CloudCover and have also started contributing to golang projects!
The inspiration for this post comes from a (slightly) confusing topic in golang which I initially struggled to under...]]></description><link>https://riyazali.net/using-interfaces-in-go</link><guid isPermaLink="true">https://riyazali.net/using-interfaces-in-go</guid><category><![CDATA[golang]]></category><category><![CDATA[Interfaces Go]]></category><category><![CDATA[#howtos]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Sat, 21 Mar 2020 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>A lot have changed in the past few months!</p>
<p>I've started a new job @ <a target="_blank" href="https://cldcvr.com/">CloudCover</a> and have also started <a target="_blank" href="https://github.com/cavaliercoder/grab/pull/67">contributing</a> <a target="_blank" href="https://github.com/riyaz-ali/shhh">to</a> golang projects!</p>
<p>The inspiration for this post comes from a (slightly) confusing topic in golang which I initially struggled to understand, and that's <strong>interfaces</strong>!</p>
<p>This post <strong>doesn't</strong> cover what interfaces are! There are lots of <a target="_blank" href="https://www.callicoder.com/golang-interfaces/">really</a> <a target="_blank" href="https://medium.com/rungo/interfaces-in-go-ab1601159b3a">good</a> <a target="_blank" href="https://www.alexedwards.net/blog/interfaces-explained">articles</a> on the internet for that.</p>
<p>What I really want to focus on is "how" you can use them and what common <em>pitfalls</em> to avoid (especially if you come from Java / C#)</p>
<hr />
<h2 id="heading-1-define-interfaces-close-to-site-of-use"><small>#1</small> Define interfaces close to site of use</h2>
<p>This allows the code (that makes use of the interface) to depend on abstractions rather than on concrete implementations.</p>
<p>And because <a target="_blank" href="https://tour.golang.org/methods/10">interfaces in go are implemented implicitly</a>, your actual implementation would just work auto-magically!</p>
<pre><code class="lang-golang"><span class="hljs-comment">// UserService defines a service that's responsible to manage user profiles</span>
<span class="hljs-keyword">type</span> UserService <span class="hljs-keyword">interface</span> {
    <span class="hljs-comment">// FetchAll returns a cursor that lists all users on the platform</span>
    FetchAll() UserIterator

    <span class="hljs-comment">// ......</span>
    <span class="hljs-comment">// this interface could contains more (but related) methods</span>
    <span class="hljs-comment">// just make sure to not bloat it (see Rule #3)</span>
}

<span class="hljs-comment">// Now we could utilize UserService abstraction in our code.</span>
<span class="hljs-comment">// Here we pass it to a function that returns an http.HandlerFunc</span>
<span class="hljs-comment">// When that handler is executed, the code could utilize the supplied user service</span>
<span class="hljs-comment">// without having to worry about where the actual implementation came from</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">ListAllUser</span><span class="hljs-params">(svc UserService)</span> <span class="hljs-title">http</span>.<span class="hljs-title">HandlerFunc</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(w http.ResponseWriter, r *http.Request)</span></span> {
        <span class="hljs-keyword">var</span> cursor = svc.FetchAll()
        <span class="hljs-comment">//...</span>
    }
}
</code></pre>
<p>This allows you to decouple your code and it's dependencies enabling you to write modular code.</p>
<p><strong>DO NOT</strong> place the interface in the package that provides the dependency and than make the provided service <em>implement</em> that interface. This seems like a common pattern used in other languages (namely, Java) where you'd declare an interface <code>com.example.UserService</code> and than provide a package-private implementation of it <code>com.example.UserServiceImpl</code> (along with a factory perhaps)</p>
<p>The <em>real power</em> of Go interfaces comes from the fact that they can be implemented implicitly! This reduces the overhead of <em>arranging</em> for an implementation before-hand and also allows a single type to implement multiple (but un-related) interfaces or implement interfaces that doesn't even exist yet (crazy right!)</p>
<p>A common example from the standard library to support this would be the <code>fmt.Stringer</code> interface which is defined close to it's site of use (the methods in <code>fmt</code> package) yet anyone can provide an implementation by adding a method with compatible signature <code>String() string</code></p>
<h2 id="heading-2-if-its-gonna-be-used-at-multiple-places-declare-it-only-once"><small>#2</small> If it's gonna be used at multiple places, declare it only once</h2>
<p>If you feel like your interface definition is going to be used in multiple places, it's better to declare it once (and maybe in a shared package)</p>
<p>Wait a minute.. doesn't that contradict #1 ?</p>
<p>Umm no, not really. You need to declare them in a single place and make the symbol (the interface) available to your <em>site of use</em>. This doesn't mean you need to couple it with your actual implementation.</p>
<p>A notable project which makes use of this pattern is <a target="_blank" href="https://github.com/drone/drone">drone.io</a></p>
<p>All the <em>core</em> interfaces used by drone are declared under the <a target="_blank" href="https://github.com/drone/drone/tree/d1a2f2174db51f4011ec4ab212ad4704c71c751e/core"><code>core</code></a> package which is than used by various other packages and satisfied by another set of packages.</p>
<h2 id="heading-3-keep-it-small-silly"><small>#3</small> Keep it small silly 😛</h2>
<p>Try and stick with <a target="_blank" href="https://en.wikipedia.org/wiki/SOLID">SOLID</a>! </p>
<p>More specifically one should try to follow <a target="_blank" href="https://en.wikipedia.org/wiki/Interface_segregation_principle">Interface Segregation</a> principle.</p>
<p>Quoting from Wikipedia,</p>
<blockquote>
<p>The <strong>Interface Segregation</strong> principle states that no client should be forced to depend on methods it does not use.</p>
</blockquote>
<p>One way to achieve this would be to keep your interfaces <em>lean</em> and focused. Model your interfaces around <em>behaviour</em>, and not data, and prefer <a target="_blank" href="https://golang.org/doc/effective_go.html#embedding">embedding</a> over large interfaces.</p>
<p>A very popular example from the standard library would be the interfaces in <a target="_blank" href="https://github.com/golang/go/tree/release-branch.go1.13/src/io"><code>io</code></a> package</p>
<pre><code class="lang-golang"><span class="hljs-keyword">type</span> Reader <span class="hljs-keyword">interface</span> {
    Read(p []<span class="hljs-keyword">byte</span>) (n <span class="hljs-keyword">int</span>, err error)
}

<span class="hljs-keyword">type</span> Closer <span class="hljs-keyword">interface</span> {
    Close() error
}

<span class="hljs-keyword">type</span> ReadCloser <span class="hljs-keyword">interface</span> {
    Reader
    Closer
}
</code></pre>
<h2 id="heading-4-accept-interfaces-return-structs"><small>#4</small> Accept interfaces return structs</h2>
<p>Lol no, I didn't come up with it 😅 in fact, <a target="_blank" href="https://redd.it/dfe1qr">no one's actually sure who did</a> 🙄 but people often cite <a target="_blank" href="https://en.wikipedia.org/wiki/Robustness_principle">Postel's Law</a></p>
<p>The basic idea is that your method should accept (as arguments) values of interface types while <em>should</em> return values which are concrete types.</p>
<p>A few examples from the standard library would be</p>
<ul>
<li><p><a target="_blank" href="https://pkg.go.dev/io?tab=doc#Pipe"><code>io.Pipe</code></a> method whose signature declares the concrete underlying type of the return values</p>
<pre><code class="lang-golang"> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Pipe</span><span class="hljs-params">()</span> <span class="hljs-params">(*PipeReader, *PipeWriter)</span></span>
</code></pre>
</li>
<li><p><a target="_blank" href="https://pkg.go.dev/io?tab=doc#Copy"><code>io.Copy</code></a> method whose signature declares accepted argument types to be interfaces</p>
<pre><code class="lang-golang">  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Copy</span><span class="hljs-params">(dst Writer, src Reader)</span> <span class="hljs-params">(written <span class="hljs-keyword">int64</span>, err error)</span></span>
</code></pre>
</li>
</ul>
<p>The primary advantage here is that your function is now decoupled and depends on <em>behaviour</em> rather than concrete types of the arguments. </p>
<p>Yet consumers of your function have the flexibility to choose the way they want to use the return type (by casting it appropriately) based on their use case.</p>
<p>This doesn't mean that you should (or can) always declare methods like that. There are exceptions. For example, <a target="_blank" href="https://pkg.go.dev/io?tab=doc#TeeReader"><code>io.TeeReader</code></a> method</p>
<pre><code class="lang-golang"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TeeReader</span><span class="hljs-params">(r Reader, w Writer)</span> <span class="hljs-title">Reader</span></span>
</code></pre>
<p>Here, it actually makes sense to wrap the underlying implementation and return an <code>io.Reader</code></p>
<p>Another <em>common</em> use case for returning interface types from method is to <em>ensure</em> that the value being returned <em>actually</em> satisfies the interface. I think this is rather a hack around Go's philosophy that "interfaces are implemented implicitly". </p>
<p>If what you actually need is a way to ensure that your custom implementation satisfies an interface you can use <em>interface guards</em>.</p>
<hr />
<h2 id="heading-bonus">Bonus</h2>
<h3 id="heading-interface-guards">Interface guards</h3>
<p>An interface guard (not an official term) is a simple no-cost hack to add checks in your code to ensure that your implementation satisfies some interface. Use this if you are building a custom implementation for an interface that is exported by a third-party library.</p>
<p>Following snippet is taken from <a target="_blank" href="https://caddyserver.com/docs/extending-caddy#interface-guards">Caddy's documentation on interface guards</a></p>
<pre><code class="lang-golang"><span class="hljs-keyword">var</span> _ InterfaceName = (*YourType)(<span class="hljs-literal">nil</span>)
</code></pre>
<p>This is simple yet no-cost way of ensuring <code>*YourType</code> <em>implemements</em> <code>InterfaceName</code> at compile-time rather than running into errors at runtime.</p>
<hr />
<p>Got doubts / queries / suggestions, feel free to <a target="_blank" href="https://github.com/riyaz-ali/riyaz-ali.github.io/issues/new">open an issue on Github</a>!</p>
]]></content:encoded></item><item><title><![CDATA[Why documentation matters]]></title><description><![CDATA[tl;dr

Good documentation gives the developers the necessary control to maintain a system - nochance @ stackexchange

But good code doesn't need documentation 🤔
Remember, documentation go way beyond the comments that are inserted in code. Often time...]]></description><link>https://riyazali.net/why-documentation-matters</link><guid isPermaLink="true">https://riyazali.net/why-documentation-matters</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[documentation]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Thu, 14 Mar 2019 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-tldr">tl;dr</h3>
<blockquote>
<p>Good documentation gives the developers the necessary control to maintain a system - <a target="_blank" href="https://softwareengineering.stackexchange.com/users/34148/nochance">nochance</a> @ stackexchange</p>
</blockquote>
<h2 id="heading-but-good-code-doesnt-need-documentation">But good code doesn't need documentation 🤔</h2>
<p>Remember, documentation go way beyond the comments that are inserted in code. Often times, they're a combination of <a target="_blank" href="http://antirez.com/news/124">well describing code comments</a>, <a target="_blank" href="/design-docs.html">design documents</a>, business requirement documents and other relevant pieces.</p>
<h2 id="heading-aint-nobody-got-time-for-that">Ain’t nobody got time for that ⏰</h2>
<p>The main reason code goes undocumented is because of <em>time</em>!</p>
<p>Developers often argue that they could rather be <em>more productive</em> and be writing code than spending time documenting the software.</p>
<h2 id="heading-the-case-for-documentation">The case for documentation</h2>
<p>No matter what you're building, chances are that some day you (or somebody else) would need to re-visit it, to fix some bug or extend it to add new feature or refactor it or any other reason.. and when that day comes, you will not remember so vividly what you wrote and why.</p>
<p>And if you do remember, there may be some edge cases or specific uses which may not be clearly apparent. The obvious solution is <strong>documentation</strong>.</p>
<p>And after all, when we, as developers, need to understand something about certain aspect of coding / library / framework, what do we do?</p>
<p>We go look at the documentation!</p>
<h2 id="heading-but-arent-comments-a-code-smellhttpssoftwareengineeringstackexchangecomquestions1">But <a target="_blank" href="https://softwareengineering.stackexchange.com/questions/1">aren't comments a code smell</a> 🤷‍♂️</h2>
<p>Umm... <span>only if the comment describes <em>what the code is doing</em></span> <sup><a target="_blank" href="https://softwareengineering.stackexchange.com/a/13">[1]</a></sup></p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{
  <span class="hljs-comment">// add b to a and return the result</span>
  <span class="hljs-keyword">return</span> a + b;
}
</code></pre>
<p>👆 that's  🤷‍♂️</p>
<p>But have a look at following snippet from <a target="_blank" href="https://git.io/JeZrK">Spring Data Commons' <code>CrudRepository.java</code></a></p>
<pre><code class="lang-java"><span class="hljs-comment">/**
 * Interface for generic CRUD operations on a repository for a specific type.
 *
 * <span class="hljs-doctag">@author</span> Oliver Gierke
 * <span class="hljs-doctag">@author</span> Eberhard Wolff
 */</span>
<span class="hljs-meta">@NoRepositoryBean</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">CrudRepository</span>&lt;<span class="hljs-title">T</span>, <span class="hljs-title">ID</span>&gt; <span class="hljs-keyword">extends</span> <span class="hljs-title">Repository</span>&lt;<span class="hljs-title">T</span>, <span class="hljs-title">ID</span>&gt; </span>{

  <span class="hljs-comment">/**
   * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
   * entity instance completely.
   *
   * <span class="hljs-doctag">@param</span> entity must not be {<span class="hljs-doctag">@literal</span> null}.
   * <span class="hljs-doctag">@return</span> the saved entity; will never be {<span class="hljs-doctag">@literal</span> null}.
   */</span>
  &lt;S extends T&gt; <span class="hljs-function">S <span class="hljs-title">save</span><span class="hljs-params">(S entity)</span></span>;

  <span class="hljs-comment">// other definitions omitted..</span>
}
</code></pre>
<p>The comments here describe <em>why</em> the interface is there and <em>what</em> the function does (not how it does it!)</p>
<p>This makes it very clear for any future reader to know about the purpose of the interface and what the function is supposed to do.</p>
<p>This instance is just one example! There are several other places where comments can be very useful.</p>
<p><a target="_blank" href="https://twitter.com/antirez">@antirez</a>, creator of Redis, had put together an <a target="_blank" href="http://antirez.com/news/124">excellent blog about comments</a>! Make sure you check it out.</p>
<hr />
<p>👆only covers code comments / documentation.. what about other forms of documentation?</p>
<p>They are all important and are there to serve different use cases!</p>
<ul>
<li><a target="_blank" href="/design-docs.html">Design docs</a> are there to describe and postulate the approach a project took to solve a given problem</li>
<li>System documentation represents documents that describe the system itself and its parts.</li>
<li>User documentation covers manuals that are mainly prepared for end-users of the product and system administrators. User documentation includes tutorials, user guides, troubleshooting manuals, installation, and reference manuals.</li>
</ul>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Guide">MDN</a>, <a target="_blank" href="https://docs.spring.io/spring/docs/current/spring-framework-reference">Spring</a>, <a target="_blank" href="https://docs.djangoproject.com/en/2.2/">Django</a>, <a target="_blank" href="https://stripe.com/docs">Stripe</a> are all good examples of products / tools / services with an excellent documentation.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://softwareengineering.stackexchange.com/questions/121775">Why should you document code?</a></li>
<li><a target="_blank" href="https://softwareengineering.stackexchange.com/a/13">This Answer</a> to <a target="_blank" href="https://softwareengineering.stackexchange.com/q/1">"comments are code smell"</a></li>
<li><a target="_blank" href="http://antirez.com/news/124">Writing system software: code comments</a> by <a target="_blank" href="https://twitter.com/antirez">@antirez</a></li>
<li><a target="_blank" href="https://freecodecamp.org/news/41ef62dd5c2f">Why documentation matters, and why you should include it in your code</a> by <a target="_blank" href="https://github.com/TomerPacific">Tomer Ben Rachel</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Git Workflow]]></title><description><![CDATA[In this post I'm going to write about the fork-clone-pull that we've been using for some time now at work.
To begin with, the Fork workflow (just workflow from now on) extend Github's Workflow and adds forking to the mix..
And why do that?
Several be...]]></description><link>https://riyazali.net/git-workflow</link><guid isPermaLink="true">https://riyazali.net/git-workflow</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[Git]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Thu, 21 Feb 2019 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>In this post I'm going to write about the <em>fork-clone-pull</em> that we've been using for some time now at work.</p>
<p>To begin with, the Fork workflow (just workflow from now on) extend <a target="_blank" href="https://guides.github.com/introduction/flow/index.html">Github's Workflow</a> and adds <a target="_blank" href="https://help.github.com/en/articles/fork-a-repo">forking</a> to the mix..</p>
<h2 id="heading-and-why-do-that">And why do that?</h2>
<p>Several benefits.</p>
<ul>
<li>You don't need to give <em>everyone</em> write access to the <em>central repository</em></li>
<li>It keeps the central repository "clean" (arguable..) by not polluting it with developers' feature branches</li>
<li>Developers can form <em>subteams</em> (by adding other dev's clone as a <code>remote</code>) (useful for collaborating, pair-programming etc.)</li>
<li><em>Enforce</em> review guidelines by limiting direct write access</li>
<li>Very useful for remote teams (personal experience..)</li>
</ul>
<p>Convinced? nice! read ahead to know more about how to implement..</p>
<h2 id="heading-implementation">Implementation</h2>
<ul>
<li><a target="_blank" href="https://help.github.com/en/articles/about-organizations">Organsiation</a> admins <sup>[1]</sup> (or users with write access) start by creating the central repository (the <code>upstream</code>)</li>
<li>Members than <a target="_blank" href="https://help.github.com/en/articles/fork-a-repo#fork-an-example-repository">fork the upstream</a> under their <em>own account</em> (the <code>origin</code> for that dev)</li>
<li>The developers than start by <a target="_blank" href="https://git-scm.com/docs/git-clone">cloning</a> their respective <code>origin</code> (each dev has complete access over their forks) and add the upstream remote  </li>
</ul>
<pre><code class="lang-shell">git clone git@github.com:user/repo
git remote add upstream git@github.com:organisation/repo
</code></pre>
<ul>
<li>One can then follow the <a target="_blank" href="https://nvie.com/posts/a-successful-git-branching-model/#supporting-branches">git branching</a> workflow that they are already familiar with.</li>
</ul>
<pre><code class="lang-shell">git checkout -b feature/the-next-big-stuff
</code></pre>
<ul>
<li>Once they've started working on the feature, they can push it up to their fork.</li>
</ul>
<pre><code class="lang-shell">git push -u origin HEAD
</code></pre>
<ul>
<li>Once they've pushed the code to <code>origin</code>, they can then open a <a target="_blank" href="https://help.github.com/en/articles/about-pull-requests">Pull Request</a> to the <code>upstream</code> where the project owner / maintainer can review the code and merge it (or suggest any changes)</li>
</ul>
<h2 id="heading-keeping-the-code-in-sync">Keeping the code in sync</h2>
<p>When multiple developers are working on a project it's very likely that the <code>upstream</code> would move much faster than the devs' <code>origin</code>. In that case, the dev would need to periodically (ideally, they should do it daily) <em>sync</em> their <code>origin</code> with the <code>upstream</code>.</p>
<p>To do that, devs need to execute following (on their local machine) -</p>
<pre><code class="lang-shell"># fetch upstream and all branches
&gt; git fetch upstream
# checkout local or own develop
&gt; git checkout develop
# get the changes from the upstream and merge to your local.
&gt; git merge upstream/develop
# push the code to the develop branch of your fork
&gt; git push origin develop
</code></pre>
<p>The devs should also execute ☝️ once they've their PR merged.</p>
<hr />
<p>And that's it! you've got a scalable git workflow model that would work well even for remote teams (we've used it quite extensively!)..  </p>
<p>And just to make it clear.. we are not the first ones who've used this or anything like that 😛.. this flow is used extensively in open-source world where generally there is a central <code>upstream</code> <em>canonical</em> repository (where all issues are made and project is released) and each contributor has his/her own "fork" of that repository. The beauty of this flow is that it scales so well even for a highly distributed open source project!</p>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://guides.github.com/introduction/flow/index.html">Understanding the GitHub Flow</a> by GitHub</li>
<li><a target="_blank" href="https://nvie.com/posts/a-successful-git-branching-model/">A successful Git branching model</a> by Vincent Driessen @ <a target="_blank" href="https://nvie.com/about/">nvie</a></li>
<li>A big shout to my friend <a target="_blank" href="https://twitter.com/vinitkme">@vinitkme</a> for familiarising me with this!</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Design Docs]]></title><description><![CDATA[A design doc — also known as a technical spec — is a description of how you plan to solve a problem. It's one of the most useful tool for making sure the right work gets done.
It's just more overhead man..
🤷‍♂️ people often claim that it’s because t...]]></description><link>https://riyazali.net/design-docs</link><guid isPermaLink="true">https://riyazali.net/design-docs</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[documentation]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Tue, 22 Jan 2019 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>A design doc — also known as a technical spec — is a description of how you plan to solve a problem. It's one of the most useful tool for making sure the right work gets done.</p>
<h2 id="heading-its-just-more-overhead-man">It's just more overhead man..</h2>
<p>🤷‍♂️ people often claim that it’s because they’re saving time by skipping the spec-writing phase.</p>
<p>But what they don't realise is that in the long run (even for a smaller project that's true), they might be spending a lot more time fixing, iterating and communicating all the same stuff (over and over again) what they could have done once if they had written a proper spec for it.</p>
<p>Joel Spolsky (<a target="_blank" href="https://twitter.com/spolsky">@spolsky</a>) has written [quite extensively] about this in his <a target="_blank" href="https://www.joelonsoftware.com/2000/10/02/painless-functional-specifications-part-1-why-bother">article</a>.</p>
<h2 id="heading-so-why-does-it-matter">So, why does it matter?</h2>
<p>A well-structured design doc can save you days, or even weeks of <em>wasted time</em>!</p>
<p>The main goal of a design doc is to make you more effective by <strong>forcing you to think</strong> through the design and gather [early] feedback from others.</p>
<p>Point is that when you design your product in a human language, it only takes a few minutes to try thinking about several possibilities, revising, and improving your design whereas when you <em>design</em> the same product in a computer language, it takes <em>weeks</em> to do iterative designs / changes.</p>
<p>Another big reason of having well-written design docs is that they <em>save us time communicating</em> the stuff by making sure that <strong>everyone is on the same page</strong>, and that can help us build great products and innovate quickly. Everybody on the team can <em>"just read the spec"</em>.</p>
<p>What happens when you don’t have a spec is that all this communication <em>still happens</em>, because <em>it has to</em>, but it happens ad-hoc..</p>
<h2 id="heading-how-do-i-go-about-writing-a-design-doc">How do I go about writing a design doc?</h2>
<p>Umm... I won't go into <em>too much</em> detail. There are already <a target="_blank" href="https://www.freecodecamp.org/news/66fcf019569c">several</a> <a target="_blank" href="https://blog.nuclino.com/how-to-write-a-technical-specification-or-software-design-document-sdd">good</a> <a target="_blank" href="https://people.eecs.berkeley.edu/~kubitron/courses/cs162-F06/design.html">articles</a> on the internet that does that. I'll try and summarize the points (and maybe add a few from my side) into the following list -</p>
<ul>
<li>Try and stick with <em>high-level</em> overview without diving too much into implementation detail</li>
<li>Define what service you're building and what are the objectives</li>
<li>Provide a context to the readers, describing where the service fits in the overall architecture</li>
<li>Outline goals and non-goals of the service and make them quite explicit</li>
<li>Give a high level technical overview. Use user / case stories to depict scenarios</li>
<li>Highlight your dependencies (what other services your service will depend on) and tell "why"</li>
<li>Describe your choice of stack (but don't dive too much into technicalities) and the reason why you chose them</li>
<li>Highlight any potential issues / open questions and get feedback from peers</li>
<li>Add links to other sites, references or articles that might be helpful</li>
<li>Get feedback early-on rather (and perhaps on each step)</li>
</ul>
<p>I personally found that following ☝️ steps is generally very helpful and makes one more productive than doing it the other way</p>
<h3 id="heading-references">References</h3>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-write-a-good-software-design-document-66fcf019569c/">How to write a good software design doc</a> by <a target="_blank" href="https://twitter.com/zhangelaz">Angela Zhang</a></li>
<li><a target="_blank" href="https://www.joelonsoftware.com/2000/10/02/painless-functional-specifications-part-1-why-bother">Painless Functional Specification - Part 1</a> by <a target="_blank" href="https://twitter.com/spolsky">Joel Spolsky</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Google Image Proxy]]></title><description><![CDATA[Continuing with app that I created as a project for the Udacity Android Nanodegree program, I faced a new challenge! The challenge was to load poster images from
TMDb Image server inside my app!
Is it even a challenge? One could say that I could've s...]]></description><link>https://riyazali.net/google-image-proxy</link><guid isPermaLink="true">https://riyazali.net/google-image-proxy</guid><category><![CDATA[Android]]></category><category><![CDATA[#howtos]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Wed, 06 Jun 2018 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>Continuing with <a target="_blank" href="https://github.com/riyaz-ali/tringo">app that I created</a> as a project for the <a target="_blank" href="https://in.udacity.com/course/android-developer-nanodegree-by-google--nd801">Udacity Android Nanodegree program</a>, I faced a new challenge! The challenge was to load <em>poster images</em> from
TMDb Image server inside my app!</p>
<p>Is it even a challenge? One could say that I could've simply used a library like <a target="_blank" href="http://square.github.io/picasso/">Picasso</a> or <a target="_blank" href="https://bumptech.github.io/glide/">Glide</a> to offload image loading to the <em>tried and trusted tools</em>. But my main challenge <strong>was not just to load the image but to load the <em>perfect image</em></strong>. </p>
<p>And that means the image <em>should</em> fit-well into <code>ImageView</code> without much need to resize and/or scale it, and thus, giving a <em>crisp and sharp</em> look and improving
UX.</p>
<p>So, what's the big deal? Why don't I just use the <a target="_blank" href="https://api.themoviedb.org/3/configuration">different bucket sizes</a> (<code>w185</code>, <code>w300</code>, etc.) that TMDb offers?</p>
<p>The thing is that the aspect size of the images served by TMDb is a bit weird (IMO!). For example, for the <code>w185</code> bucket, the image served has an aspect ratio of <code>185:278</code>!</p>
<p>What can be done? Well, the only thing we can do is to download a bigger image (from <code>original</code> bucket) and resize it  on device. But that's a total no-go because the <code>original</code> image is too large (<code>2000x3000</code>) and would consume <em>signifacntly more</em> resources. And also, performing <em>resize</em> on user's device is not a good idea!</p>
<p>What I initally thought was to setup a <a target="_blank" href="http://thumbor.org/">Thumbor</a> server. But I quickly dropped the idea because then I would have to maintain the server (which I didn't want) for the (atleast) lifetime of the project or else the app would simply not work!</p>
<p>This led me to search for <em>open, free and hosted</em> alternatives. Although, I couldn't find a <em>trustworthy</em> solution, what I found was <a target="_blank" href="https://gist.github.com/coolaj86/2b2c14b1745028f49207">this Gist</a>. In the Gist, the author <em>reverse engineered</em> (sort of) the URL for the Google Image proxy and the required parameters and leveraged it as a <em>caching and resizing proxy</em> to serve his images!</p>
<p>Cool! how to use that in the project app? Simple! create the primary TMDb image url, append it as a parameter to the Google Image Proxy url and load the resulting url into the <code>ImageView</code> using your favorite library!</p>
<p>So, here's a <a target="_blank" href="https://www.quora.com/What-is-a-utility-class">Utility class</a> that I created to handle the stuff!</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImageUtils</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">ImageUtils</span><span class="hljs-params">()</span></span>{
    <span class="hljs-comment">/*  ¯\_(ツ)_/¯ */</span>
  }

 <span class="hljs-comment">// Google's image caching and resizing proxy</span>
 <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String GOOGLE_CACHE_BASE =
  <span class="hljs-string">"https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy"</span>;


  <span class="hljs-comment">/**
   * Create base tmdb url
   */</span>
  <span class="hljs-meta">@NonNull</span> <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">tmdbUrl</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> String poster)</span></span>{
    <span class="hljs-keyword">return</span> String.format(
      <span class="hljs-string">"%s/original%s"</span>, 
      <span class="hljs-comment">// or however you get the base url...</span>
      BuildConfig.TMDB_IMAGE_BASE, 
      poster);
  }

  <span class="hljs-comment">/**
   * Calculate aspect
   */</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">aspect</span><span class="hljs-params">(<span class="hljs-keyword">int</span> width, <span class="hljs-keyword">int</span> height)</span> </span>{
    <span class="hljs-keyword">return</span> height / width;
  }

  <span class="hljs-comment">/**
   * Calculate the other dimension (either height or width) 
   * given one dimension and an aspect
   *
   * Use as: calculateOtherDimension(aspect(4, 3), 400) -&gt; 300
   *
   * <span class="hljs-doctag">@param</span> aspect aspect ratio
   * <span class="hljs-doctag">@param</span> dimension measurement of one dimension
   */</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">calculateOtherDimension</span><span class="hljs-params">(<span class="hljs-keyword">int</span> aspect, <span class="hljs-keyword">int</span> dimension)</span></span>{
    <span class="hljs-keyword">return</span> aspect * dimension;
  }

  <span class="hljs-meta">@NonNull</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">createTmdbImageUrl</span><span class="hljs-params">(
    <span class="hljs-meta">@NonNull</span> String poster, 
    <span class="hljs-keyword">int</span> height, 
    <span class="hljs-keyword">int</span> width)</span></span>{
      <span class="hljs-keyword">return</span> Uri.parse(GOOGLE_CACHE_BASE).buildUpon()
        .appendQueryParameter(<span class="hljs-string">"container"</span>, <span class="hljs-string">"focus"</span>)
        .appendQueryParameter(<span class="hljs-string">"resize_h"</span>, <span class="hljs-string">""</span> + height)
        .appendQueryParameter(<span class="hljs-string">"resize_w"</span>, <span class="hljs-string">""</span> + width)
        .appendQueryParameter(<span class="hljs-string">"url"</span>, tmdbUrl(poster))
        .toString();
  }

}
</code></pre>
<p>Now to use it, just call it as</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> ImageUtils.*;

<span class="hljs-comment">// ...</span>
createTmdbImageUrl(
  movie.getPoster(), 
  <span class="hljs-number">300</span> <span class="hljs-comment">/* height */</span>, 
  calculateOtherDimension(aspect(<span class="hljs-number">2</span> <span class="hljs-comment">/*w*/</span>, <span class="hljs-number">3</span> <span class="hljs-comment">/*h*/</span>), <span class="hljs-number">300</span>)
);
<span class="hljs-comment">//...</span>
</code></pre>
<p>{{&lt; image src="https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy?container=focus&amp;resize_w=200&amp;resize_h=300&amp;url=http%3A%2F%2Fimage.tmdb.org%2Ft%2Fp%2Foriginal%2Fto0spRl1CMDvyUbOnbb4fTk3VAd.jpg" alt="Deadpool" position="center" &gt;}}</p>
<p>And that's it! Using this you can load image of any aspect that you need and deliver a <em>crispier and sharper experience</em> to your users. But, I'd sincerely like to request to you to <em>only use this</em> for small, open source projects so that you don't need to maintain a server!<br />
If you are developing a closed-source business application, than it would be much better to use something like <a target="_blank" href="http://thumbor.org/">Thumbor</a> or <a target="_blank" href="https://github.com/willnorris/imageproxy">ImageProxy</a> as they are dedicated solutions and provide more features!</p>
]]></content:encoded></item><item><title><![CDATA[Android Support Paging Library]]></title><description><![CDATA[Recently, I was working on a project for the Udacity Android Nanodegree program to develop an Android application for TMDb to list movies using the TMDb API.
As you might've guessed, TMDb has a huge collection of movies, and so a need for paging the ...]]></description><link>https://riyazali.net/android-support-paging-library</link><guid isPermaLink="true">https://riyazali.net/android-support-paging-library</guid><category><![CDATA[Android]]></category><category><![CDATA[#howtos]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Fri, 01 Jun 2018 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>Recently, I was working on a project for the <a target="_blank" href="https://in.udacity.com/course/android-developer-nanodegree-by-google--nd801">Udacity Android Nanodegree program</a> to develop an Android application for <a target="_blank" href="https://www.themoviedb.org/"><strong>TMDb</strong></a> to list movies using the <a target="_blank" href="https://developers.themoviedb.org/3/getting-started/introduction">TMDb API</a>.</p>
<p>As you might've guessed, TMDb has a <em>huge collection of movies</em>, and so a need for <em>paging the data</em> was quite obvious from the very begining of the project.</p>
<p>So I started looking into ways in which I could've implemented paging with my <code>RecyclerView</code>. Turns out there are a few ways to achieve this!</p>
<ol>
<li><p><em>The old way</em> (as documented in <a target="_blank" href="https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews-and-RecyclerView"><u>this CodePath guide</u></a>) is to use <a target="_blank" href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.OnScrollListener"><code>RecyclerView.OnScrollListener</code></a> and <em>listen for</em> scroll events and load data accordingly! But with the release of the <a target="_blank" href="https://developer.android.com/topic/libraries/architecture/paging">Android Paging Library</a>, the guide is now considered <em>deprecated</em>!</p>
</li>
<li><p><em>The new way</em> (yeah! you guessed it) is to use <a target="_blank" href="https://developer.android.com/topic/libraries/architecture/paging">Android Paging Library</a> and the rest of this post is all about how to integrate it!</p>
</li>
</ol>
<h3 id="heading-architecture">Architecture</h3>
<p>So you ask, how this Paging Library works?</p>
<p>Well, there are four major components in the Paging Library:</p>
<ol>
<li><p><code>DataSource</code>: The <code>DataSource</code> is where you write code to interact with your source (REST API, sqlite database, etc.) All the requests for data from the <code>DataSource</code> are made on a background thread and so you can safely write <em>synchronous</em> code to interact with your source, if you want to. <code>DataSource</code> is responsible to load a <code>List&lt;T&gt;</code> of your model object given a page/key and implement business logic for the same.</p>
</li>
<li><p><code>PagedListAdapter&lt;T, VH&gt;</code>: <code>PagedListAdapter</code> is a <code>RecyclerView.Adapter</code> which uses a <code>PagedList</code> (see below) to load data into the UI. <code>PagedListAdapter</code> uses a <code>DiffUtils.ItemCallback&lt;T&gt;</code> implementation to calculate <em>difference</em> between your model objects in the list and animates add/remove operations on UI.</p>
</li>
<li><p><code>DiffUtils.ItemCallback&lt;T&gt;</code>: The <code>DiffUtils.ItemCallback&lt;T&gt;</code> for your model class is utilized by the <code>PagedListAdapter</code> to calculate <em>diff</em> between two list and animate changes in the UI. You must provide an implementation of this callback. The callback is executed on a background thread to prevent stalling the UI.</p>
</li>
<li><p><code>PagedList&lt;T&gt;</code>: A <code>PagedList</code> is a Java-collection which loads it's data in chunks (pages) from a <code>DataSource</code>. The <code>PagedList</code> connects your <code>PagedListAdapter</code> and your <code>DataSource</code> together and is responsible to <em>lazy load</em> data by calling appropriate methods on the <code>DataSource</code>.</p>
</li>
</ol>
<p>{{&lt; image src="https://cdn-images-1.medium.com/max/800/1*O1acN3yAOS70zbRMfThXrw.gif" alt="Paging Library Architecture" position="center" &gt;}}</p>
<p>First, we create a <em>model POJO</em> class (referred in the post as <code>Movie</code>) and implement <a target="_blank" href="https://developer.android.com/reference/android/support/v7/util/DiffUtil.ItemCallback"><code>DiffUtil.ItemCallback&lt;T&gt;</code></a></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Movie</span> </span>{
  <span class="hljs-comment">// id of the movie</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">long</span> id;
  <span class="hljs-comment">// title of the movie</span>
  <span class="hljs-keyword">private</span> String title;
  <span class="hljs-comment">// path to movie's poster</span>
  <span class="hljs-keyword">private</span> String poster;

  <span class="hljs-comment">// DiffCallback to assist Adapter</span>
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> DiffUtil.ItemCallback&lt;Movie&gt; DIFF_CALLBACK = 
    <span class="hljs-keyword">new</span> DiffUtil.ItemCallback&lt;Movie&gt;() {
      <span class="hljs-meta">@Override</span> 
      <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">areItemsTheSame</span><span class="hljs-params">(Movie oldItem, Movie newItem)</span> </span>{
        <span class="hljs-keyword">return</span> oldItem.id == newItem.id;
      }

      <span class="hljs-meta">@Override</span>
      <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">areContentsTheSame</span><span class="hljs-params">(Movie oldItem, Movie newItem)</span> </span>{
        <span class="hljs-keyword">return</span> TextUtils.equals(oldItem.poster, newItem.poster)
            &amp;&amp; TextUtils.equals(oldItem.title, newItem.title);
      }
    };
}
</code></pre>
<p>Then, we subclass <a target="_blank" href="https://developer.android.com/reference/android/arch/paging/PagedListAdapter">PagedListAdapter</a> and create our custom <a target="_blank" href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter">adapter</a> which will be used to display <code>Movie</code></p>
<pre><code class="lang-java"><span class="hljs-comment">// required imports</span>
<span class="hljs-keyword">import</span> android.arch.paging.PagedListAdapter;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MovieAdapter</span> 
  <span class="hljs-keyword">extends</span> <span class="hljs-title">PagedListAdapter</span>&lt;<span class="hljs-title">Movie</span>, <span class="hljs-title">MovieAdapter</span>.<span class="hljs-title">ViewHolder</span>&gt; </span>{
  <span class="hljs-comment">// ViewHolder removed for brevity... nothing special in the ViewHolder</span>

  <span class="hljs-comment">/**
   * Create new adapter and pass the diff callback to parent
   */</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MovieAdapter</span><span class="hljs-params">(
      <span class="hljs-meta">@NonNull</span> DiffUtil.ItemCallback&lt;Movie&gt; diffCallback)</span> </span>{
    <span class="hljs-keyword">super</span>(diffCallback);
  }

  <span class="hljs-comment">// ... then the usual create(...) and bind(...) view holder methods</span>
}
</code></pre>
<p>Next we need to create a <a target="_blank" href="https://developer.android.com/reference/android/arch/paging/DataSource"><code>DataSource</code></a> that will <em>connect</em> with the API and fetch data! There are 3 types of <code>DataSource</code> provided by the Paging Library:</p>
<ul>
<li><p><a target="_blank" href="https://developer.android.com/reference/android/arch/paging/ItemKeyedDataSource"><code>ItemKeyedDataSource&lt;Key, Value&gt;</code></a>: Use it if you need to use data from item <code>N-1</code> to load item <code>N</code></p>
</li>
<li><p><a target="_blank" href="https://developer.android.com/reference/android/arch/paging/PageKeyedDataSource"><code>PageKeyedDataSource&lt;Key, Value&gt;</code></a>: Use it if pages you load embed keys for loading adjacent pages.</p>
</li>
<li><p><a target="_blank" href="https://developer.android.com/reference/android/arch/paging/PositionalDataSource"><code>PositionalDataSource&lt;T&gt;</code></a>: Use it if you can load pages of a requested size at arbitrary positions, and provide a fixed item count.</p>
</li>
</ul>
<p>You can read more about the types of <code>DataSource</code> and when to use which one on <a target="_blank" href="https://developer.android.com/reference/android/arch/paging/DataSource"><code>DataSource</code> documentation</a></p>
<p>For our example, we will use <a target="_blank" href="https://developer.android.com/reference/android/arch/paging/PageKeyedDataSource"><code>PageKeyedDataSource&lt;Key, Value&gt;</code></a></p>
<pre><code class="lang-java"><span class="hljs-comment">// required imports</span>
<span class="hljs-keyword">import</span> android.arch.paging.PageKeyedDataSource;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MoviesDataSource</span> 
  <span class="hljs-keyword">extends</span> <span class="hljs-title">PageKeyedDataSource</span>&lt;<span class="hljs-title">Integer</span>, <span class="hljs-title">Movie</span>&gt; </span>{
    <span class="hljs-comment">// constant max retry count, see Bonus section for more!</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> MAX_RETRY = <span class="hljs-number">3</span>;
    <span class="hljs-comment">// retrofit service instance</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Tmdb.Api tmdbApi;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MoviesDataSource</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> Tmdb.Api tmdbApi)</span> </span>{
      <span class="hljs-keyword">this</span>.tmdbApi = tmdbApi;
    }

    <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">loadInitial</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> LoadInitialParams&lt;Integer&gt; params,
      <span class="hljs-meta">@NonNull</span> LoadInitialCallback&lt;Integer, Movie&gt; callback)</span> </span>{

    <span class="hljs-comment">// load the first page</span>
    tmdbApi.getPopularMovies(<span class="hljs-number">1</span> <span class="hljs-comment">/* page */</span>).enqueue(<span class="hljs-keyword">new</span> CallbackWithRetry&lt;MovieResponse&gt;(MAX_RETRY) {
      <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onResponse</span><span class="hljs-params">(Call&lt;MovieResponse&gt; call, Response&lt;MovieResponse&gt; response)</span> </span>{
        <span class="hljs-keyword">if</span> (response.isSuccessful()) {
          MovieResponse movieResponse = response.body();

          <span class="hljs-comment">// send response back</span>
          callback.onResult(movieResponse.getMovies(), <span class="hljs-keyword">null</span>, <span class="hljs-comment">// null because there is no page before this</span>
              movieResponse.getPage() + <span class="hljs-number">1</span>); <span class="hljs-comment">// TMDb follows incrementing integer as pages numbers</span>
        } <span class="hljs-keyword">else</span> {
          onFailure(call, <span class="hljs-keyword">new</span> Exception(<span class="hljs-string">"unknown error"</span>));
        }
      }

      <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onFinalFailure</span><span class="hljs-params">(Call&lt;MovieResponse&gt; call, Throwable t)</span> </span>{
        callback.onResult(Collections.emptyList(), <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>);
      }
    });
  }

  <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">loadBefore</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> LoadParams&lt;Integer&gt; params,
      <span class="hljs-meta">@NonNull</span> LoadCallback&lt;Integer, Movie&gt; callback)</span> </span>{

    <span class="hljs-comment">// params.key contains the page number of the page to load</span>
    tmdbApi.getPopularMovies(params.key).enqueue(<span class="hljs-keyword">new</span> CallbackWithRetry&lt;MovieResponse&gt;(MAX_RETRY) {
      <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onResponse</span><span class="hljs-params">(Call&lt;MovieResponse&gt; call, Response&lt;MovieResponse&gt; response)</span> </span>{
        <span class="hljs-keyword">if</span> (response.isSuccessful()) {
          MovieResponse movieResponse = response.body();
          <span class="hljs-comment">// return response, since we are moving backward adjacent page is - 1 from current position</span>
          callback.onResult(movieResponse.getMovies(), movieResponse.getPage() - <span class="hljs-number">1</span>);
        } <span class="hljs-keyword">else</span> {
          onFailure(call, <span class="hljs-keyword">new</span> Exception(<span class="hljs-string">"unknown error"</span>));
        }
      }

      <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onFinalFailure</span><span class="hljs-params">(Call&lt;MovieResponse&gt; call, Throwable t)</span> </span>{
        callback.onResult(Collections.emptyList(), <span class="hljs-keyword">null</span>);
      }
    });
  }

  <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">loadAfter</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> LoadParams&lt;Integer&gt; params,
      <span class="hljs-meta">@NonNull</span> LoadCallback&lt;Integer, Movie&gt; callback)</span> </span>{

    <span class="hljs-comment">// params.key contains the page number of the page to load</span>
    tmdbApi.getPopularMovies(params.key).enqueue(<span class="hljs-keyword">new</span> CallbackWithRetry&lt;MovieResponse&gt;(MAX_RETRY) {
      <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onResponse</span><span class="hljs-params">(Call&lt;MovieResponse&gt; call, Response&lt;MovieResponse&gt; response)</span> </span>{
        <span class="hljs-keyword">if</span>(response.isSuccessful()){
          MovieResponse movieResponse = response.body();
          <span class="hljs-comment">// return response, since we are moving forward adjacent page is + 1 from current position</span>
          callback.onResult(movieResponse.getMovies(), movieResponse.getPage() + <span class="hljs-number">1</span>);
        } <span class="hljs-keyword">else</span> {
          onFailure(call, <span class="hljs-keyword">new</span> Exception(<span class="hljs-string">"unknown error"</span>));
        }
      }

      <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onFinalFailure</span><span class="hljs-params">(Call&lt;MovieResponse&gt; call, Throwable t)</span> </span>{
        callback.onResult(Collections.emptyList(), <span class="hljs-keyword">null</span>);
      }
    });
  }
}
</code></pre>
<p>The only thing that remains for us is to connect our <code>MovieAdapter</code> with our <code>MovieDataSource</code> using a <a target="_blank" href="https://developer.android.com/reference/android/arch/paging/PagedList"><code>PagedList</code></a>. </p>
<p>To use a <code>PagedList</code>, we first create a <a target="_blank" href="https://developer.android.com/reference/android/arch/paging/PagedList.Config"><code>PagedList.Config</code></a>. We also need to create two <a target="_blank" href="https://developer.android.com/reference/java/util/concurrent/Executor"><code>Executor</code></a> which will be used to <em>execute</em> fetch and notification calls from the <code>PagedList</code>, i.e., data fetching via <code>DataSource</code> will execute on the <em>fetch executor</em> and load- and boundary- callbacks will be executed by the <em>notify executor</em>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.Executor;
<span class="hljs-keyword">import</span> java.util.concurrent.ExecutorService;

<span class="hljs-comment">// Ui thread executor to execute runnable on UI thread</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UiThreadExecutor</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Executor</span> </span>{
  <span class="hljs-keyword">private</span> Handler handler = <span class="hljs-keyword">new</span> Handler(Looper.getMainLooper());

  <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> Runnable command)</span> </span>{
    handler.post(command);
  }
}

<span class="hljs-comment">// Background thread executor to execute runnable on background thread</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BackgroundThreadExecutor</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Executor</span> </span>{
  <span class="hljs-keyword">private</span> ExecutorService executorService = 
        Executors.newFixedThreadPool(<span class="hljs-number">2</span>);

  <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> Runnable command)</span> </span>{
    executorService.execute(command);
  }
}
</code></pre>
<p>Then in your <code>Activity</code></p>
<pre><code class="lang-java"><span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Bundle savedInstanceState)</span> </span>{
  <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);

  <span class="hljs-comment">// usual onCreate code...</span>

  <span class="hljs-comment">// setup recycler view</span>
  RecyclerView recycler = findViewById(R.id.movies);
  recycler.setLayoutManager(<span class="hljs-keyword">new</span> GridLayoutManager(<span class="hljs-keyword">this</span>, <span class="hljs-number">2</span>));
  <span class="hljs-comment">// create new movie adapter</span>
  MovieAdapter adapter = <span class="hljs-keyword">new</span> MovieAdapter(Movie.DIFF_CALLBACK);
  <span class="hljs-comment">// add adapter to recyclerview</span>
  recycler.setAdapter(adapter);

  <span class="hljs-comment">// create data source</span>
  MoviesDataSource dataSource = <span class="hljs-keyword">new</span> MoviesDataSource(getRetofitApi());
  <span class="hljs-comment">// create configuration</span>
  <span class="hljs-comment">// see https://is.gd/l4hv42</span>
  PagedList.Config config = <span class="hljs-keyword">new</span> PagedList.Config.Builder()
      <span class="hljs-comment">// this is not used by TMDb as we cannot pass page size to API</span>
      <span class="hljs-comment">// but is required by PagedList to use as hint</span>
      .setPageSize(<span class="hljs-number">10</span>)
      .setPrefetchDistance(<span class="hljs-number">5</span>)
      .build();
  <span class="hljs-comment">// create paged list</span>
  PagedList&lt;Movie&gt; pagedList = 
    <span class="hljs-keyword">new</span> PagedList.Builder&lt;&gt;(dataSource, config)
      <span class="hljs-comment">// get list notifications on Ui thread</span>
      .setNotifyExecutor(<span class="hljs-keyword">new</span> UiThreadExecutor())
      <span class="hljs-comment">// execute fetches on a background thread</span>
      .setFetchExecutor(<span class="hljs-keyword">new</span> BackgroundThreadExecutor())
      <span class="hljs-comment">// build!</span>
      .build();
  <span class="hljs-comment">// update adapter's paged list (and data source)</span>
  adapter.submitList(pagedList);
}
</code></pre>
<p>That's it! In a (sort of) few lines of code (if we remove the inherent verbosity in Java), we get a <code>RecyclerView.Adapter</code> that is capable of <em>efficiently</em> loading data and presenting it on the UI all while keeping it <em>low</em> on resources and preventing janky UI!</p>
<h3 id="heading-bonus">Bonus!</h3>
<p>Here is the source of the <code>retrofit2.Callback&lt;T&gt;</code> with <em>exponential backoff</em> retry policy, i.e., it will retry the request each time on failure with exponentially increasing delay to prevent network and API abuse!</p>
<pre><code class="lang-java"><span class="hljs-comment">// retrofit callback implementation with retry policy</span>
<span class="hljs-comment">// adapted from https://stackoverflow.com/a/41884400/6611700</span>
<span class="hljs-comment">// adapted from https://is.gd/KaEwPt (exponential delay)</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CallbackWithRetry</span>&lt;<span class="hljs-title">T</span>&gt; <span class="hljs-keyword">implements</span> <span class="hljs-title">retrofit2</span>.<span class="hljs-title">Callback</span>&lt;<span class="hljs-title">T</span>&gt; </span>{
  <span class="hljs-comment">// exponential backoff delay</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> RETRY_DELAY = <span class="hljs-number">300</span>; <span class="hljs-comment">/* ms */</span>

  <span class="hljs-comment">// max allowed retries</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> maxAttempts;
  <span class="hljs-comment">// current attempts</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> attempts = <span class="hljs-number">0</span>;

  CallbackWithRetry(<span class="hljs-keyword">int</span> max){
    <span class="hljs-keyword">this</span>.maxAttempts = max;
  }

  <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onFailure</span><span class="hljs-params">(Call&lt;T&gt; call, Throwable t)</span> </span>{
    attempts++;
    <span class="hljs-keyword">if</span>(attempts &lt; maxAttempts){
      <span class="hljs-keyword">int</span> delay = 
          (<span class="hljs-keyword">int</span>) (RETRY_DELAY * Math.pow(<span class="hljs-number">2</span>, Math.max(<span class="hljs-number">0</span>, attempts - <span class="hljs-number">1</span>)));
      <span class="hljs-keyword">new</span> Handler().postDelayed(() -&gt; retry(call), delay);
    } <span class="hljs-keyword">else</span> {
      onFinalFailure(call, t);
    }
  }

  <span class="hljs-comment">// failure hook called when retries are consumed</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onFinalFailure</span><span class="hljs-params">(Call&lt;T&gt; call, Throwable t)</span></span>;

  <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">retry</span><span class="hljs-params">(Call&lt;T&gt; call)</span></span>{
    call.clone().enqueue(<span class="hljs-keyword">this</span>);
  }
}
</code></pre>
<p>Hope you enjoyed the post! If you've any doubts regarding any of the stuff here feel free to <a target="_blank" href="https://github.com/riyaz-ali/riyaz-ali.github.io/issues/new">open an issue on GitHub</a>{:target="_blank"} and I'll try my best to explain it! Till then goodbye!</p>
]]></content:encoded></item><item><title><![CDATA[Discourse Login on Android]]></title><description><![CDATA[A few days back, I was looking for a hobby side-project to work on. I wanted to develop an Android application (open source) and to collaborate with my peers on Google Udacity Android scholarship program. On the Udacity discussion forum, there were m...]]></description><link>https://riyazali.net/discourse-login-on-android</link><guid isPermaLink="true">https://riyazali.net/discourse-login-on-android</guid><category><![CDATA[Android]]></category><category><![CDATA[#howtos]]></category><dc:creator><![CDATA[Riyaz Kagzi]]></dc:creator><pubDate>Tue, 10 Apr 2018 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>A few days back, I was looking for a hobby side-project to work on. I wanted to develop an Android application (open source) and to collaborate with my peers on <a target="_blank" href="https://in.udacity.com/google-india-scholarships">Google Udacity Android scholarship program</a>. On the Udacity discussion forum, there were many threads filled with exciting ideas but they all were either <em>too</em> ambitious or required quite a bit of time.</p>
<p>Then, one day while checking into the forum an idea struck me! Why not make an app for the discussion forum itself! I knew the forum was powered by <a target="_blank" href="https://discourse.org">Discourse</a> and quickly started looking up for ways in which in could create an app for it...</p>
<p>And voila! I found the official <a target="_blank" href="https://docs.discourse.org">Discourse API</a>. I quickly went through the API and found that for <em>most</em> of the calls the user needed to be authenticated (due to obivious reasons). But the <em>only</em> way to <em>authenticate</em> was to use an <em>Admin generated API key</em>. Obviously, I couldn't generate the API keys myself and didn't want to bother the forum moderators or admins. Besides that the Admin API key would grant complete read/write access to the forum to anyone who have it, not something a forum admin would want. So I thought to scrape the idea...</p>
<p>But then something struck me! I knew a user could log into the forum from a browser (very obvious) and the Discourse frontend (written in Ember) communicated to the backend (written in Ruby) using an API. I suspected if it was the <em>same</em> API? Turns out the API used by Discourse frontend is a <em>superset</em> of the <a target="_blank" href="https://docs.discourse.org/">public API</a> and it uses the <code>_t</code> cookie as the Session Cookie.</p>
<p>And so I started looking for ways I could use this to create a login for the user of my app. Turns out it's not that easy.</p>
<p>First I thought to use <a target="_blank" href="https://developer.chrome.com/multidevice/android/customtabs">Chrome Custom Tabs</a> but it turns out that you <em>cannot pass cookies</em> between an app and a chrome custom tab for <a target="_blank" href="https://bugs.chromium.org/p/chromium/issues/detail?id=539240">security reasons</a></p>
<p>Then I tried using the <a target="_blank" href="https://developer.android.com/reference/android/webkit/WebView.html"><code>WebView</code></a> and succeeded to some extent. But the solution was very fragile as there is no well-defined <code>/login</code> page on Discourse and the user could easily navigate away from the <code>WebView</code>. I know I could've prevented the navigation but Discourse allows 3<sup>rd</sup> party login integration and then I would have to account for all possible domains a user could have navigated too! And besides these there are no autofill and <em>password remembering</em> features in <code>WebView</code> which means the user would have to login <em>manually</em> then.</p>
<p>{{&lt; image src="https://media.giphy.com/media/YoGX4OZFjUwRq/giphy.gif" alt="Lo and Behold" position="center" &gt;}}</p>
<p>And then I found what I was <em>actually</em> looking for! The <a target="_blank" href="https://meta.discourse.org/t/user-api-keys-specification/48536">Discourse User API key specification</a>!! First created in Aug'16, this feature <em>facilitates</em> “application” access to Discourse instances without needing to involve moderators. The spec provides a flow <em>similar</em> to OAuth but with a few tweaks so that the Discourse instance doesn't have to <em>know</em> about the app prior to authentication. The token generation flow is documented <a target="_blank" href="https://meta.discourse.org/t/user-api-keys-specification/48536">here</a></p>
<p>The problem with User API key spec is that <em>it's documentation is outdated</em> and the canonical way is to <em>follow</em> the source of the <a target="_blank" href="https://github.com/discourse/DiscourseMobile">Discourse Mobile App</a> which is a companion app and provide features like Push notificaton, etc. (not browsing!) The app is written in React Native.</p>
<p>After a lot of trial-and-error I finally go it to work natively (in Java) on Android. And following is the Gist of what I did.</p>
<p>  1 . Create a <code>DiscourseAuthAgent</code> class.</p>
<pre><code class="lang-java">  <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DiscourseAuthAgent</span> </span>{
    <span class="hljs-comment">// Randomly generated or static client id for your app</span>
    <span class="hljs-keyword">private</span> String clientId;

    <span class="hljs-comment">// Random string to verify that the </span>
    <span class="hljs-comment">// reply indeed comes from Discourse server</span>
    <span class="hljs-keyword">private</span> String nonce;

    <span class="hljs-comment">// RSA Public key</span>
    <span class="hljs-keyword">private</span> String publicKey;

    <span class="hljs-comment">// RSA Private key</span>
    <span class="hljs-keyword">private</span> String privateKey;

    <span class="hljs-comment">// API key we get from the server</span>
    <span class="hljs-keyword">private</span> String apiKey;
  }
</code></pre>
<p>  2 . To generate the RSA <a target="_blank" href="https://developer.android.com/reference/java/security/KeyPair.html"><code>KeyPair</code></a></p>
<pre><code class="lang-java">  String[] generateKeyPair(){
    String[] result = <span class="hljs-keyword">new</span> String[<span class="hljs-number">2</span>];

    <span class="hljs-comment">// generate KeyPair</span>
    KeyPairGenerator kpg = KeyPairGenerator.getInstance(<span class="hljs-string">"RSA"</span>);
    kpg.initialize(<span class="hljs-number">2048</span>);
    KeyPair keyPair = kpg.generateKeyPair();

    <span class="hljs-comment">// get and base64 encode public key</span>
    <span class="hljs-keyword">byte</span>[] publicKey  = keyPair.getPublic().getEncoded();
    String b64PublicKey = Base64.encodeToString(publicKey, Base64.DEFAULT);
    result[<span class="hljs-number">0</span>] = b64PublicKey;

    <span class="hljs-comment">// get and base63 encode private key</span>
    <span class="hljs-keyword">byte</span>[] privateKey = keyPair.getPrivate().getEncoded();
    String b64PrivateKey = Base64.encodeToString(privateKey, Base64.DEFAULT);
    b64PublicKey[<span class="hljs-number">1</span>] = b64PrivateKey;

    <span class="hljs-keyword">return</span> result;
  }
</code></pre>
<p>  3 . For the <code>clientId</code> and <code>nonce</code> you <em>should</em> generate a random string of length 32 and 16 respectively. I tried with other length options but failed so I guess it's good to go with these values.</p>
<pre><code class="lang-java">  <span class="hljs-function"><span class="hljs-keyword">static</span> String <span class="hljs-title">randomString</span><span class="hljs-params">(<span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> sizeOfRandomString)</span> </span>{
    <span class="hljs-comment">// taken from https://stackoverflow.com/a/12116194/6611700</span>
    String ALLOWED_CHARACTERS = 
      <span class="hljs-string">"0123456789qwertyuiopasdfghjklzxcvbnm"</span>;

    <span class="hljs-keyword">final</span> Random random= <span class="hljs-keyword">new</span> Random();
    <span class="hljs-keyword">final</span> StringBuilder sb= <span class="hljs-keyword">new</span> StringBuilder(sizeOfRandomString);

    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;sizeOfRandomString;++i)
      sb.append(
        ALLOWED_CHARACTERS.charAt(
          random.nextInt(ALLOWED_CHARACTERS.length())
        )
      );
    <span class="hljs-keyword">return</span> sb.toString();
  }
</code></pre>
<p>  4 . Now to generate a <a target="_blank" href="https://developer.android.com/reference/android/net/Uri.html"><code>Uri</code></a>,</p>
<pre><code class="lang-java">  <span class="hljs-comment">/**
   * <span class="hljs-doctag">@param</span> appName Your Application name that will be displayed to the user
   * <span class="hljs-doctag">@param</span> scopes Permission scopes that you want (e.g. read, write)
   * <span class="hljs-doctag">@param</span> redirectUri Uri to redirect to after authentication
   */</span>
  <span class="hljs-function">Uri <span class="hljs-title">generateAuthUri</span><span class="hljs-params">(String appName, String[] scopes, String redirectUri)</span> </span>{
    clientId = randomString(<span class="hljs-number">32</span> <span class="hljs-comment">/* size */</span>);
    nonce = randomString(<span class="hljs-number">16</span> <span class="hljs-comment">/* size */</span>);
    String[] rsaKeyPair = generateKeyPair();
    publicKey = rsaKeyPair[<span class="hljs-number">0</span>];
    privateKey = rsaKeyPair[<span class="hljs-number">1</span>];

    <span class="hljs-keyword">return</span> Uri.parse(BASE_URL).buildUpon()
      .appendEncodedPath(<span class="hljs-string">"user-api-key/new"</span>)
      .appendQueryParameter(<span class="hljs-string">"scopes"</span>, TextUtils.join(<span class="hljs-string">","</span>, scopes))
      .appendQueryParameter(<span class="hljs-string">"client_id"</span>, clientId)
      .appendQueryParameter(<span class="hljs-string">"nonce"</span>, nonce)
      .appendQueryParameter(<span class="hljs-string">"auth_redirect"</span>, redirectUri)
      .appendQueryParameter(<span class="hljs-string">"push_url"</span>, <span class="hljs-string">"https://api.discourse.org/api/publish_android"</span>)  <span class="hljs-comment">// placeholder</span>
      .appendQueryParameter(<span class="hljs-string">"application_name"</span>, appName)
      .appendQueryParameter(<span class="hljs-string">"public_key"</span>, getFormattedPublicKey(Base64.decode(rsaPublicKey, Base64.DEFAULT)))
      .build();
  }

  <span class="hljs-function">String <span class="hljs-title">getFormattedPublicKey</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] unformatted)</span></span>{
    String pkcs1pem = <span class="hljs-string">"-----BEGIN PUBLIC KEY-----\n"</span>;
    pkcs1pem += Base64.encodeToString(unformatted, Base64.DEFAULT);
    pkcs1pem += <span class="hljs-string">"-----END PUBLIC KEY-----"</span>;
    <span class="hljs-keyword">return</span> pkcs1pem;
  }
</code></pre>
<p>  5 . Finally to validate the result of the authentication and to get the API key from the redirect, we need to decrypt the <code>payload</code> query parameter that was sent with the redirection. The payload is encrypted using our <code>publicKey</code> and can only be decrypted by our <code>privateKey</code></p>
<pre><code class="lang-java">  <span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">handleAuthIntent</span><span class="hljs-params">(Intent data)</span></span>{
    <span class="hljs-keyword">if</span>(<span class="hljs-keyword">null</span> == data.getData())
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;

    <span class="hljs-keyword">try</span> {
      String payload = java.net.URLDecoder.decode(
        redirection.getData().getQueryParameter(<span class="hljs-string">"payload"</span>).replace(<span class="hljs-string">"+"</span>, <span class="hljs-string">"%2B"</span>),
        <span class="hljs-string">"UTF-8"</span>
      ).replace(<span class="hljs-string">"%2B"</span>, <span class="hljs-string">"+"</span>);

      <span class="hljs-comment">// get back the private key</span>
      <span class="hljs-keyword">byte</span>[] privateKeyBytes = Base64.decode(privateKey, Base64.DEFAULT);
      PKCS8EncodedKeySpec spec = <span class="hljs-keyword">new</span> PKCS8EncodedKeySpec(privateKeyBytes);
      PrivateKey privateKey = KeyFactory.getInstance(<span class="hljs-string">"RSA"</span>).generatePrivate(spec);

      <span class="hljs-comment">// initialize the Cipher</span>
      Cipher cipher = Cipher.getInstance(<span class="hljs-string">"RSA/NONE/PKCS1Padding"</span>);
      cipher.init(Cipher.DECRYPT_MODE, privateKey);

      <span class="hljs-comment">// decrypt the payload into json</span>
      <span class="hljs-keyword">byte</span>[] decryptedBytes = cipher.doFinal(Base64.decode(payload, Base64.DEFAULT));
      String decrypted = <span class="hljs-keyword">new</span> String(decryptedBytes);

      <span class="hljs-comment">// create json object, verify nonce and let the fun begin!!!</span>
      JSONObject payloadJson = <span class="hljs-keyword">new</span> JSONObject(decrypted);

      <span class="hljs-comment">// compare nonce</span>
      <span class="hljs-keyword">if</span>(!nonce.equals(payloadJson.getString(<span class="hljs-string">"nonce"</span>)))
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalAccessException(<span class="hljs-string">"invalid nonce"</span>);

      apiKey = payloadJson.getString(<span class="hljs-string">"key"</span>);

      <span class="hljs-comment">// and we are all done...</span>
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
    } <span class="hljs-keyword">catch</span> (Exception e) {
      <span class="hljs-comment">// failed to decrypt!</span>
      <span class="hljs-comment">// app must die :(</span>
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
    }
  }
</code></pre>
<p>  6 . And that's it!! Now you just need to persist the <code>clientId</code> and <code>apiKey</code> (preferably in <code>SharedPreferences</code>) so that you can use them later to authenticate your requests.</p>
<p>Now to use the <code>DiscourseAuthAgent</code> class in your (say) <code>LoginActivity</code>, add this to your <em>manifest</em> :</p>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">activity</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">".LoginActivity"</span> <span class="hljs-attr">android:launchMode</span>=<span class="hljs-string">"singleTask"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- deep link redirection handler after authentication --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">intent-filter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">action</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.intent.action.VIEW"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">category</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.intent.category.DEFAULT"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">category</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.intent.category.BROWSABLE"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">data</span> <span class="hljs-attr">android:scheme</span>=<span class="hljs-string">"discourse"</span> <span class="hljs-attr">android:host</span>=<span class="hljs-string">"auth_redirect"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">intent-filter</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">activity</span>&gt;</span>
</code></pre>
<p>  This will make sure that the <em>same instance</em> of the Activity gets the <a target="_blank" href="https://developer.android.com/training/app-links/deep-linking.html">deep linking</a> intent so that you can use the same <code>DiscourseAuthAgent</code> instance.</p>
<p>In the example <code>LoginActivity</code>, start authentication by getting Uri and launching the <em>default</em> browser or a Chrome Cutom Tab (preferred).</p>
<pre><code class="lang-java">  <span class="hljs-comment">// on some button click</span>
  <span class="hljs-comment">// redirect uri must be exactly the same, I tried with other but failed</span>
  Uri rediectTo = discourseAgent.generateAuthUri(<span class="hljs-string">"My Amazing App"</span>, <span class="hljs-keyword">new</span> String[]{ <span class="hljs-string">"read"</span>, <span class="hljs-string">"write"</span> }, <span class="hljs-string">"discourse://auth_redirect"</span>);
  CustomTabsIntent customTabsIntent = <span class="hljs-keyword">new</span> CustomTabsIntent.Builder()
    .setToolbarColor(getResources().getColor(R.color.colorPrimary))
    .build();
  customTabsIntent.launchUrl(<span class="hljs-keyword">this</span>, redirectTo);
</code></pre>
<p>Then, when Chrome redirects the user back to your Activity:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onNewIntent</span><span class="hljs-params">(Intent intent)</span> </span>{
  <span class="hljs-keyword">super</span>.onNewIntent(intent);
  <span class="hljs-keyword">if</span>(<span class="hljs-keyword">null</span> != intent.getData() &amp;&amp; intent.getData().toString().startsWith(REDIRECT_URI)){
    <span class="hljs-comment">// redirection intent</span>
    Timber.d(<span class="hljs-string">"reply: %s"</span>, intent.getData());
    <span class="hljs-keyword">if</span>(discourseAgent.handleAuthIntent(intent)){
      <span class="hljs-comment">// authentication completed!</span>
      Timber.d(<span class="hljs-string">"Session authenticated!"</span>);
    } <span class="hljs-keyword">else</span> {
      Timber.d(<span class="hljs-string">"Failed to authenticate session :("</span>);
    }
  }
}
</code></pre>
<p>And well that's it! Now that you have an <code>api key</code> you can make <em>autheticated</em> calls to the <a target="_blank" href="http://docs.discourse.org">Discourse Public API</a> using the key. Just send the key in the <code>User-Api-Key</code> HTTP header and your <code>client id</code> in the <code>User-Api-Client-Id</code> HTTP header.</p>
]]></content:encoded></item></channel></rss>