<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Aditya Mukerjee on Medium]]></title>
        <description><![CDATA[Stories by Aditya Mukerjee on Medium]]></description>
        <link>https://medium.com/@chimeracoder?source=rss-151af177574d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*KzfbNTe7uBc4LmWn.jpg</url>
            <title>Stories by Aditya Mukerjee on Medium</title>
            <link>https://medium.com/@chimeracoder?source=rss-151af177574d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 27 May 2026 22:44:30 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@chimeracoder/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Observing Kubernetes Services With Veneur]]></title>
            <link>https://medium.com/@chimeracoder/observing-kubernetes-services-with-veneur-365dce9b56c?source=rss-151af177574d------2</link>
            <guid isPermaLink="false">https://medium.com/p/365dce9b56c</guid>
            <category><![CDATA[monitoring]]></category>
            <category><![CDATA[observability]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[prometheus]]></category>
            <dc:creator><![CDATA[Aditya Mukerjee]]></dc:creator>
            <pubDate>Thu, 05 Apr 2018 12:50:33 GMT</pubDate>
            <atom:updated>2018-04-10T18:01:25.870Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/864/1*jR69RgPQZNGP4mAvW-GYqw.png" /></figure><p><a href="https://veneur.org/">Veneur</a> is a data pipeline for observing distributed systems. You can use Veneur for aggregating application and system data, like runtime metrics or distributed traces, and intelligently routing the data to various tools for storage and analysis. Veneur supports a number of these tools — called “data sinks” — such as SignalFX, Datadog, or Kafka. For this walkthrough, we’ll use Datadog.</p><h3>Collecting pod-local metrics with Veneur</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/613/0*bc3W8Pm7KZ0xiQnZ." /></figure><p>The first step to observing our services with Veneur is to deploy a local sidecar instance of Veneur inside our pod. To keep things simple, we’ll create a simple application whose only feature is to emit a heartbeat metric. We’ll do this using veneur-emit.</p><p>Veneur-emit is a convenience utility we wrote that allows us to emit statsd-compatible metrics at the command line for testing. It’s equivalent to using statsd client libraries (e.g. <a href="https://github.com/DataDog/datadog-go/statsd">statsd</a>) within an application. We wrote it to synthesize data transmission and is used in a similar way to netcat.. So the following netcat command:</p><pre>$ echo -n “resp_success:1|c|#method:post” | nc -4u localhost 8126</pre><p>could be written as</p><pre>$ veneur-emit -hostport udp://localhost:8126 -count 1 -name &quot;resp_success&quot; -tag &quot;method:post&quot;</pre><h3>Basic Example</h3><p>In this example, veneur-emit is a stand-in for any application you want to observe, if it’s instrumented using statsd client libraries. Since it’s the main application — and first container — in our pod, we’ll begin with the vanilla setup:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/af2b3713ef25e1df98fd39bd0baf3e26/href">https://medium.com/media/af2b3713ef25e1df98fd39bd0baf3e26/href</a></iframe><p>That’s the first container in our pod, and if we deploy it as-is, it’ll start faithfully firing off UDP metrics on port 8126. But there’s nothing listening on that port, so it’s just talking into the void. Let’s give it an audience by adding a second container in the same pod:</p><pre>- name: veneur  image: index.docker.io/stripe/veneur:3.0.0</pre><p>Veneur requires almost no configuration out of the box; it defaults to working values. This new container is almost ready to start collecting metrics. However, without a Datadog API key, it won’t be able to send the metrics anywhere, so at the very least, we’ll need to configure our downstream data sinks.</p><h3>Configuring a Pod-Local Veneur Collector</h3><p>When running in non-containerized environments, Veneur can read its configuration from a file. But in Kubernetes, environment variables are more convenient. Thanks to <a href="https://github.com/kelseyhightower/envconfig">envconfig</a>, we can use these two forms of configuration interchangeably. Every config option specified in the <a href="https://github.com/stripe/veneur/blob/master/example.yaml">yaml config example</a> has a corresponding environment variable, prefixed with VENEUR_. So, we provide the following:</p><pre>env:                     <br>    - name: VENEUR_DATADOGAPIKEY<br>      valueFrom:<br>           secretKeyRef:<br>               name: datadog<br>               key: datadog_api_key</pre><p>For more information on setting the secret key values in Kubernetes, see the <a href="https://kubernetes.io/docs/concepts/configuration/secret/">Kubernetes documentation on secrets</a>.</p><p>In addition, we listen for UDP packets on port 8126 to receive the metrics, and we also listen for HTTP traffic on port 8127. Port 8127 is used for the healthcheck endpoint. It can also be used to listen for metrics that are emitted over TCP using authenticated TLS instead of UDP, but we won’t cover that here, as it’s not needed for most Kubernetes deployments.</p><p>So, putting it all together, we have:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d6a38e94cb189e7d6e7a80c493570ef4/href">https://medium.com/media/d6a38e94cb189e7d6e7a80c493570ef4/href</a></iframe><p>If we apply this deployment (kubectl apply -f veneur-emit.yaml), we’ll start to see these metrics come in, at the rate of six per minute. We’re sending metrics all the way from our application to Datadog!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Yh0OD9TZsUUlIdnr." /></figure><p>If all you care about is collecting pod-local metrics, that’s it! You can stop here. But, there’s a good chance you want global metric aggregation as well. For that, we’ll have to add a little more.</p><h3>Global Aggregation — How it Works</h3><p>Veneur is capable of supporting global metric aggregation.</p><p>Let’s say you have an API server with 200 different replicas responding to stateless requests, load-balanced evenly across all instances. If you want to reduce your API latency, you probably want to know the 95th or 99th percentile for API latency across all 200 replicas, rather than the 99th percentile latency for the first pod, the 99th percentile for the second, and so forth. Having the separate latencies for the individual pods doesn’t help you, because percentiles aren’t monoids: there’s no mathematical operation to construct the global 99th percentile from the 200 different measurements of the 99th percentile on each pods.</p><p>Some time-series databases sidestep this problem by storing the raw data and performing the percentile aggregation at read-time, but this requires tremendous network, disk, and compute resources at scale, especially if we want good performance from our queries at read-time. Performing write-time aggregation reduces this load. But calculating percentiles before writing the results requires either sending all metrics to a single aggregator pod (which becomes a single-point-of-failure) or calculating them on a per-pod basis. Fortunately, Veneur has a nifty approach that gives the best of both worlds: global aggregate calculations at write-time, with no single-point-of-failure, and with an architecture that scales horizontally using existing Kubernetes primitives.</p><p>Veneur uses <a href="https://raw.githubusercontent.com/tdunning/t-digest/blob/master/docs/t-digest-paper/histo.pdf">t-digests</a> to compute extremely accurate percentile estimates in an <a href="https://en.wikipedia.org/wiki/Online_algorithm">online</a> manner, using constant memory. While these percentile calculations are technically approximations, in practice, the error properties yield exact results for tail ends of the distribution, like the 99th percentile. Conveniently, that’s generally what we care about when observing our services, especially latencies.</p><p>Veneur’s provides a horizontally scalable mechanism for calculating global aggregates of timers, histograms and sets. The pod-local metrics — counters and gauges — are shipped off to Datadog immediately, but timers, histograms, and sets are forwarded to a separate service for global aggregation. The aggregation happens in two layers.</p><h3>Veneur Proxy and Veneur Global</h3><p>First, the pod-local veneur processes forward all timers, histograms, and sets to the veneur-proxy service, which is exposed by Kubernetes. Because Veneur is stateless, the choice of pod and node are arbitrary for the veneur-proxy service, and this can be handled by the built-in Kubernetes support for service discovery and load-balancing.</p><p>Under-the-hood, the veneur-proxy processes have to do a bit of coordination to split up their metrics properly. Assume that we have three proxy pods and two global pods, and that each proxy pod receives three metrics — named “red”, “blue”, and “pink” for convenience — from an arbitrary number of application pods. We can’t just lean on regular load-balancing within Kubernetes — we need to ensure that all metrics of the same name end up on the same global pod, or else we won’t have aggregated them properly.</p><p>Fortunately, this is all handled automatically by the veneur-proxy and veneur-global services. The veneur-proxy pods distribute the metrics consistently — all red metrics (the solid red arrow) end up on the same global pod, all blue metrics (blue dotted arrow) end up on the same global pod, and all pink metrics (dashed pink arrow) end up on the same global pod.</p><p>Of course, the number of replicas of the veneur-proxy and veneur-global services is arbitrary (and each veneur-global pod is capable of aggregating far more than one metric at a time!). Since both services are stateless, they can be horizontally scaled and adjusted dynamically to adapt to your particular metric load.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/624/0*FPCDVGmH-UNCOonP." /></figure><p>To create the veneur-proxy and veneur-global services, we just need to provide the following definitions.</p><p>For the proxy:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ff1c8c2b3d22ee0a547a7275d895c19e/href">https://medium.com/media/ff1c8c2b3d22ee0a547a7275d895c19e/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/129cdd50ad967dabf3045bc9693a0e56/href">https://medium.com/media/129cdd50ad967dabf3045bc9693a0e56/href</a></iframe><p>The second section is the same as what we saw before — veneur-proxy is a separate application binary, and for it to emit metrics about itself, we’ll want it to have its own, pod-local Veneur instance to talk to.</p><p>The global service configuration is even easier:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fb4b4181adef74e826f216b6edc7b3db/href">https://medium.com/media/fb4b4181adef74e826f216b6edc7b3db/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3fc0377ee3cdc5fef8424ce987960026/href">https://medium.com/media/3fc0377ee3cdc5fef8424ce987960026/href</a></iframe><h3>Resource Limits</h3><p>While Veneur’s functionality extends beyond just collecting runtime metrics, compared to other dedicated metric collectors, Veneur’s resource usage is pretty lightweight. The portion that’s the most expensive computationally — global metric aggregation — is performed on dedicated pods (veneur-global).</p><p>Kubenetes has built-in support for resource limits, leveraging the power of <a href="https://en.wikipedia.org/wiki/Cgroups">cgroups</a> in a convenient abstraction. We can use resource limits to cap the CPU and memory usage of the pod-local Veneur instances.</p><pre>- name: veneur<br>   image: index.docker.io/stripe/veneur:3.0.0<br>   resources:<br>       limits:<br>           cpu: 25m</pre><h3>Invariants</h3><p>With this three-tier setup, we maintain a number of useful invariants about our observability system.</p><ul><li>Stateless. Each Veneur process is entirely stateless. No data remains in memory for longer than ten seconds, so failure or eviction of a single pod running Veneur has very limited impact on our system’s overall observability.</li><li>Distributed: There is no single point of failure. If any pod-local veneur process is killed and restarted, we only lose data for that pod, and only for one flush cycle. If any proxy or global veneur process is killed and restarted, we only lose ten seconds of data, and only for 1/n metrics (where n is the number of replicas we’re running).</li><li>Horizontally scalable: We can run as many instances of the proxy and global boxes as we need to, to support arbitrarily large loads.</li><li>Fault-tolerant: If a global veneur instance becomes unreachable, all proxy boxes will update their hashing scheme immediately for the next flush cycle.</li></ul><h3>Prometheus</h3><p>Veneur also supports pull-based metric aggregation with Prometheus. <a href="https://github.com/stripe/veneur/tree/master/cmd/veneur-prometheus">veneur-prometheus</a> is a separate binary which polls a Prometheus metrics endpoint to ingest metrics into the Veneur pipeline.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0b4c669eba43d2b5738d80e019d5d015/href">https://medium.com/media/0b4c669eba43d2b5738d80e019d5d015/href</a></iframe><h3>….and more!</h3><p>We’re just scratching the surface of how Veneur can help you get better observability into your Kubernetes systems. Observability is not just about runtime metrics — it’s about request traces and logs as well. Veneur is an embodiment of the philosophy that logs, runtime metrics, and traces are all deeply connected, and that there should be an <a href="https://vimeo.com/221049715">intelligent metrics pipeline</a> handling all three.</p><p>If any of this excites or intrigues you — or if you have more thoughts on what kinds of visibility you need in your Kubernetes deployments, you’re in luck! Veneur is actively developed, with tagged major releases every six weeks. <a href="https://github.com/stripe/veneur/issues">Drop us a line over on the issue tracker</a>!</p><h4>Acknowledgements</h4><p>Thanks to Jess Frazelle, Kris Nova, and Cory Watson for reading drafts of this post!</p><p><em>Originally published at </em><a href="https://varnull.adityamukerjee.net/2018/04/05/observing-kubernetes-services-with-veneur/"><em>varnull.adityamukerjee.net</em></a><em> on April 5, 2018.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=365dce9b56c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Don’t Read Your Logs]]></title>
            <link>https://medium.com/@chimeracoder/dont-read-your-logs-13586c790202?source=rss-151af177574d------2</link>
            <guid isPermaLink="false">https://medium.com/p/13586c790202</guid>
            <category><![CDATA[logging]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[observability]]></category>
            <category><![CDATA[monitoring]]></category>
            <category><![CDATA[sre]]></category>
            <dc:creator><![CDATA[Aditya Mukerjee]]></dc:creator>
            <pubDate>Fri, 19 May 2017 16:49:41 GMT</pubDate>
            <atom:updated>2017-07-26T02:49:59.425Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*flwD48QnPur99-Ej5hnNwg.jpeg" /><figcaption>Photo provided by Karen Arnold under the <a href="http://creativecommons.org/publicdomain/zero/1.0/">CC0 Public Domain</a> license.</figcaption></figure><p>I’ve had a number of discussions, both offline and <a href="https://twitter.com/chimeracoder/status/849455048929292289">online</a>, about logging practices. In my view, reading individual log lines is (almost) always a sign that there are gaps in your system’s monitoring tools — especially when dealing with software at a medium- or large scale. Just as I would never want to use tcpdump to analyze statsd metric packets individually, ideally, I don’t want to look at individual log lines either.</p><p>This advice follows the spirit of “Disable port 22 on your machines”. While most developers would agree that using dedicated orchestration tools is preferable to manual server wrangling, I know of very few projects or companies that take the extreme stance of disabling SSH access to all machines. Nevertheless, treating manual SSH as a sign of gaps in your system’s orchestration tools is an excellent master cue for architecting scalable and maintainable systems.</p><p>Similarly, I know of none that truly send all logs to /dev/null, or block read access to all logs. But treating logs as an extreme anti-pattern provides an excellent forcing function for designing observable systems.</p><p><strong>Logs as Metrics</strong></p><p>Let’s start with a basic example:</p><pre>log.Printf(“Loaded page in %f seconds”, duration)</pre><p>In this case, the log line serves the same purpose as a statsd metric. We could replace it immediately with</p><pre>statsd.Histogram(“page.load.time_ms”, duration)</pre><p>and the result would be better, because we’d be able to use the full extent of aggregation tools at our disposal. It’s possible to extract this information <em>from</em> a log line into a structured form, but it’s more work, and it’s unnecessary. The log line doesn’t give us any information that the structured metric doesn’t.</p><p><strong>Logs as Debugger Tracing</strong></p><p>A more common example:</p><pre>log.Println(“about to make API request on”, obj_id)</pre><pre>obj = c.Load(obj_id)</pre><pre>if obj == nil {</pre><pre>    log.Println(“could not load object”, obj_id)</pre><pre>} else {</pre><pre>    log.Println(“loaded object”, obj_id)</pre><pre>}</pre><p>Logs are oftentimes used as a runtime pseudo-debugger. In this case, we’re using logs as a way to verify that a particular line of code was called for a particular transaction. The actual text of the log doesn’t even matter. Instead of “About to make API request”, we could have written:</p><pre>log.Println(“api.request_pre”, id)</pre><p>or even:</p><pre>log.Println(“I like potato salad”, obj_id)</pre><p>As long as it’s unique to that particular line of code, it serves functionally the same purpose — it confirms that the program execution reached that point in the code.</p><p>When we use log lines this way, we’re forming a mental model of the code, and using the logs to virtually step through the code, exactly the way a traditional debugger like GDB might. Transaction-level (or request-level) tracing tools provide this same kind of visibility, with a better visual display.</p><p>Without actually counting, I’d estimate that at least 80% — if not more — of log lines that I’ve seen in most open-source projects fit this overall use case: using log lines to virtually “trace” the execution path of source code on a particular piece of problematic input.</p><p><strong>Logs as Error Reporting</strong></p><p>Another common pattern:</p><pre>try: <br>    writeResult()</pre><pre>except Exception as e:</pre><pre>    log.info(“error writing result!”, e)</pre><p>Here, we’re using logs as a way to capture context for an error. But again, this is a relatively inconvenient way to explore information like a stacktrace. Tools like Sentry or Crashlytics also allow exception reporting, but unlike logging tools, they allow us to classify and group exceptions. We can still view individual stacktraces, but we don’t have to sift through as much noise to identify problems. And by tracking the state of reported exceptions, we can identify regressions more easily. Structured logging systems are generally not capable of handling this — and even when the workflow is possible, it’s nowhere near as convenient as what dedicated exception tracking systems allow.</p><p>If you <em>really</em> can’t break the habit of logging errors, you can at least add a hook to log.error that sends the error (and a complete stacktrace) to an error reporting tool like Sentry.</p><p><strong>Logs as Durable Records</strong></p><p>Furthermore, you can’t even assume that the logs you try to write will actually get written! Even when operating on a small scale, logs can be a lossy pipeline, and the potential for failure only increases with scale.</p><p>For example, if you’re developing a script intended to run on your local machine, do you know how your code will behave if your disk hangs? If you run out of space on the partition? How reliable is your log rotation? What happens to your server if it fails?</p><p>For a very small script, these sorts of failures may not matter to you, but they <em>can</em> come back to bite you, even at that small scale. For larger-scale services with tighter reliability guarantees, there are ways to mitigate these specific problems — a buffer, a log collector, a distributed indexer — but each solution comes with its own risks and problems. If you try to keep patching these by introducing more tools to make your logging reliable, at some point, you’ll discover that you’ve reinvented your own distributed database. And writing your own database is not <em>inherently</em> a bad idea, but to do it well, it’s the sort of task that’s best undertaken intentionally, rather than by accident.</p><p>To be fair to logging, this problem is not unique to logs. It comes from the limitations set forth by the CAP theorem, which means that <em>every</em> monitoring tool has to figure out its own way to deal with them. The problem with logs, however, is that the failure modes are much more subtle and easy to overlook.</p><p>For example:</p><pre>statsd.Increment(‘api.requests_total”, tags={“country”: country.String()}, rate=.1)</pre><p>It’s relatively obvious to see that this line of code might not always emit a metric, because even under normal operating conditions, you know</p><ol><li>Network operations can have problems</li><li>It uses UDP, and</li><li>The metrics are sampled at the specified rate</li></ol><p>It’s a lot less obvious that this line of code might fail, because STDOUT and STDERR are generally assumed to be always available under normal operating conditions:</p><pre>log.Printf(“Received api request from %s”, country.String())</pre><p>Compared to logging, the failure modes of using runtime metrics, request tracing tools, or exception tracking tools are more visible and well-defined.</p><p>Instead of using logs as an accidental database, consider your underlying use case and which dedicated database would serve that need better. There’s no one-size-fits-all answer here; you may find that your use case is best served by a NoSQL database like CouchDB, or you may find that you’re really aiming to replicate the functionality of a message queue like Kafka, or another database altogether. If any of these (or other) tools fit your use case, they’re almost guaranteed to be a <em>better</em> fit, long-term, than logs.</p><p><strong>Don’t Stop Logging, But Stop Reading Log Lines</strong></p><p>By this point, it may sound like I’m firmly anti-logging. I do consider myself an <a href="https://en.wikipedia.org/wiki/Logging">environmentally-friendly person</a>, but when it comes to software, I support careful uses of logging.</p><p>Logging can be useful for some purposes. However, it’s rare that they’re the <em>only</em> tool for monitoring your code. And it’s even rarer that they’re the <em>best</em> tool. When writing software that scales, you need to be able to deal with aggregate information — the firehose is too unwieldy to parse mentally. Logs that can be aggregated are better than logs that can’t. In those cases, it’s best to keep logging, but when you need to diagnose a problem, you’ll be interested in reading aggregate queries across your logs, rather than viewing raw, unaggregated logs in chronological order. The former is a powerful way to absorb a lot of information about your systems quickly. The latter is a glorified “tail -f | grep”.</p><p>The next time you start to write a log line, ask yourself whether another observability tool would be a better fit. Oftentimes, it will! If not, that’s fine. Just remember that, ideally, nobody should ever be reading that raw line, so take care to structure the information in a way that facilitates the kind of aggregation queries you’ll need.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=13586c790202" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What Would Body Cameras Do?]]></title>
            <link>https://medium.com/@chimeracoder/what-would-body-cameras-do-199cec58a00c?source=rss-151af177574d------2</link>
            <guid isPermaLink="false">https://medium.com/p/199cec58a00c</guid>
            <category><![CDATA[imho]]></category>
            <dc:creator><![CDATA[Aditya Mukerjee]]></dc:creator>
            <pubDate>Thu, 18 Dec 2014 19:36:31 GMT</pubDate>
            <atom:updated>2014-12-18T21:00:52.041Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ofO0X1NDgaWtqa0UCy55bg.jpeg" /><figcaption><a href="https://secure.flickr.com/photos/clearlyambiguous/133427908">“From The Other Side”</a></figcaption></figure><p>On December 3rd, a New York City grand jury failed to indict NYPD officer Daniel Pantaleo in the death of Eric Garner. Protesters around the world, from Oakland to New Delhi, reacted to this decision, demanding reforms to counterbalance the power wielded by law enforcement. They adopted as a slogan Garner’s chilling final words:<em> I can’t breathe. I can’t breathe. I can’t breathe.</em></p><p>Garner is only <a href="https://en.wikipedia.org/wiki/Death_of_Eric_Garner">one</a> <a href="https://en.wikipedia.org/wiki/Shooting_of_Tamir_Rice">of</a> <a href="https://en.wikipedia.org/wiki/Shooting_of_Akai_Gurley">several</a> <a href="https://en.wikipedia.org/wiki/Shooting_of_Michael_Brown">high-profile</a> cases of black men killed by police. Sadly, these incidents are not rare. By some counts, <a href="http://www.alternet.org/news-amp-politics/1-black-man-killed-every-28-hours-police-or-vigilantes-america-perpetually-war-its">a black man is killed by police officers nearly every day</a>. Race plays heavily into this risk: a black, male teenager is 21 <a href="http://www.propublica.org/article/deadly-force-in-black-and-white">times more likely</a> to be shot dead by a police officer than a white one.</p><p>Of all the varied proposals for reform, perhaps the most popular among politicians is to outfit all police officers with body cameras. President Obama recently requested over $250 million from Congress to fund body cameras and police training. Proponents of this plan <a href="http://www.nytimes.com/roomfordebate/2013/10/22/should-police-wear-cameras/body-cameras-could-restore-trust-in-police">claim</a> that body cameras will ensure that evidence is available in all cases of alleged police misconduct. They note that people behave differently when they know they are being watched, and conclude that body cameras will reduce misconduct, both by police officers and by civilians.</p><p>This argument draws on a common narrative: photography as documentation. This narrative is by no means new. Susan Sontag <a href="http://www.susansontag.com/SusanSontag/books/onPhotographyExerpt.shtml">wrote</a>, “A photograph passes for incontrovertible proof that a given thing happened. The picture may distort; but there is always a presumption that something exists, or did exist, which is like what’s in the picture.”</p><p>And yet, we must ask ourselves: is there such a thing as an impartial photograph? After all, every photograph tells a story. Every photograph is narrated in the first person.</p><p>Sontag explains, “To photograph is to appropriate the thing photographed. It means putting oneself into a certain relation to the world that feels like knowledge — and, therefore, like power.” Body cameras, mounted on the bodies of the police, serve as a permanent record of what the officers see. Body cameras, mounted on the bodies of the police, ensure that police remain in the position of power: the allegedly infallible narrator. Body cameras, mounted on the bodies of the police, reinforce the same imbalance in power structures that they are purported to keep in check. They allow officers to appropriate every interaction by legitimizing the literal viewpoint of the officer. But the objective of reform is not to appropriate civilians targeted by law enforcement; it is to appropriate law enforcement itself.</p><blockquote><em>“To photograph is to appropriate the thing photographed. It means putting oneself into a certain relation to the world that feels like knowledge — and, therefore, like power.” — Susan Sontag, “On Photography”</em></blockquote><p>It might be a different story if we ensured that this power would be reciprocal: that citizens would be able to appropriate law enforcement, just as law enforcement appropriates black lives. But this is not the case: citizen bystanders often get harassed by officers when recording encounters, even when recording officers is legal. In fact, in Garner’s case, Pantaleo was not indicted, but Ramsey Orta, the bystander who filmed Garner’s death, <a href="http://ringoffireradio.com/2014/12/grand-jury-indicted-the-man-who-filmed-eric-garners-killing/">was</a>. At the same time as we provide police with an additional form of power, we rob citizens of this same tool. Police officers may tell their story, but citizens remain “the thing photographed.”</p><p>Defendants are <a href="http://www.nytimes.com/2004/06/20/nyregion/new-trend-before-grand-juries-meet-the-accused.html">not required</a> to testify before a grand jury. Their attorneys usually recommend against it, as it can be incredibly risky. Defendants’ attorneys are not permitted to be present, and with no judge, defendants are completely at the mercy of the prosecutor. Yet, despite these circumstances, Pantaleo felt confident enough to testify, and during the grand jury hearing, he narrated “<a href="http://www.nytimes.com/2014/12/04/nyregion/officer-told-grand-jury-he-meant-no-harm-to-eric-garner.html?_r=0">three different videos of the arrest that were taken by bystanders</a>.” If he had worn a body camera, perhaps he could have stayed at home; his account would have been presented as a fourth video, with him behind the camera.</p><p>So we must ask ourselves — would body cameras have made a difference in Garner’s case? If not, what is the goal of arming officers with one more weapon? Or more bluntly, as Sydette Harry asks, “<a href="https://modelviewculture.com/pieces/everyone-watches-nobody-sees-how-black-women-disrupt-surveillance-theory">Why must black death be broadcast and consumed to be believed, and what is it beyond spectacle if it cannot be used to obtain justice?</a>”</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=199cec58a00c" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>