<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Will's Blog (Posts about kent)</title><link>https://bluesock.org/~willkg/blog/</link><description></description><atom:link href="https://bluesock.org/~willkg/blog/tag/kent.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:willkg@bluesock.org"&gt;Will Kahn-Greene&lt;/a&gt; CC BY-SA 3.0</copyright><lastBuildDate>Fri, 05 Jun 2026 13:54:03 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Open Source Project Maintenance 2025</title><link>https://bluesock.org/~willkg/blog/dev/maintenance_2025.html</link><dc:creator>Will Kahn-Greene</dc:creator><description>&lt;div&gt;&lt;p&gt;Every October, I do a maintenance pass on all my projects. At a minimum, that
involves dropping support for whatever Python version is no longer supported
and adding support for the most recently released Python version. While doing
that, I go through the issue tracker, answer questions, and fix whatever I can
fix. Then I release new versions. Then I think about which projects I should
deprecate and figure out a deprecation plan for them.&lt;/p&gt;
&lt;p&gt;This post covers the 2025 round.&lt;/p&gt;
&lt;p&gt;TL;DR&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/sphinx-js/"&gt;sphinx-js&lt;/a&gt; -- transferred to
&lt;a class="reference external" href="https://github.com/pyodide"&gt;pyodide organization&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/crashstats-tools/"&gt;crashstats-tools&lt;/a&gt; and
&lt;a class="reference external" href="https://pypi.org/project/siggen/"&gt;siggen&lt;/a&gt; -- transferred to the Mozilla
crash ingestion team, which I'm no longer on&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/paul-mclendahand/"&gt;paul-mclendahand&lt;/a&gt; -- deprecated and archived&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://github.com/willkg/pip-stale/"&gt;pip-stale&lt;/a&gt; -- deprecated and archived&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/everett/"&gt;everett&lt;/a&gt; -- released v3.5.0, then deprecated and archived&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/fillmore/"&gt;fillmore&lt;/a&gt; -- released v2.2.0, then deprecated and archived&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/kent/"&gt;kent&lt;/a&gt; -- released v2.2.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/markus/"&gt;markus&lt;/a&gt; -- released v5.2.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a class="reference external" href="https://pypi.org/project/bleach/"&gt;bleach&lt;/a&gt; -- released v6.3.0&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://bluesock.org/~willkg/blog/dev/maintenance_2025.html"&gt;Read more…&lt;/a&gt; (7 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>bleach</category><category>dev</category><category>everett</category><category>fillmore</category><category>kent</category><category>markus</category><category>mozilla</category><category>python</category><category>work</category><guid>https://bluesock.org/~willkg/blog/dev/maintenance_2025.html</guid><pubDate>Tue, 28 Oct 2025 14:00:00 GMT</pubDate></item><item><title>Kent v0.1.0 released! And the story of Kent in the first place....</title><link>https://bluesock.org/~willkg/blog/dev/kent_0_1_0.html</link><dc:creator>Will Kahn-Greene</dc:creator><description>&lt;section id="what-is-it"&gt;
&lt;h2&gt;What is it?&lt;/h2&gt;
&lt;p&gt;Before explaining what it is, I want to talk about Why.&lt;/p&gt;
&lt;p&gt;A couple of years ago, we migrated from the Raven Sentry client (Python) to
sentry-sdk. One of the things we did was implement our own sanitization code
which removed personally identifyable information and secret information (as
best as possible) from error reports.&lt;/p&gt;
&lt;p&gt;I find the documentation for writing sanitization filters really confusing.
&lt;code class="docutils literal"&gt;before_send&lt;/code&gt;? &lt;code class="docutils literal"&gt;before_breadcrumb&lt;/code&gt;? When do those hooks kick off? What does
an event look like? There's &lt;a class="reference external" href="https://develop.sentry.dev/sdk/event-payloads/"&gt;a link to a page that describes an event&lt;/a&gt;, but there's a lot of
verbiage and no schema so it's not wildly clear what the errors my application
is sending look like. &lt;a class="brackets" href="https://bluesock.org/~willkg/blog/dev/kent_0_1_0.html#footnote-1" id="footnote-reference-1" role="doc-noteref"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;1&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Anyhow, so when we switched to sentry-sdk, we implemented some sanitization
code because while Raven had some code, sentry-sdk did not. Then at some point
between then and now, the sanitization code stopped working. It's my fault
probably. I bet something changed in the sentry-sdk and I didn't notice.&lt;/p&gt;
&lt;p&gt;Why didn't I notice? Am I a crappy engineer? Sure, but in this case the problem
here is that the sanitization code runs in the context of handling an unhandled
error. In handling the unhandled error, Sentry passes the event through our
broken sanitization code and that throws an exception. Nothing gets sent to
Sentry--neither the original error nor the sanitization error.&lt;/p&gt;
&lt;p&gt;Once I realized there were errors, I looked in the logs and I can see the
original errors--but not the sanitization errors.&lt;/p&gt;
&lt;aside class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Fun fact: turns out John Whitlock thought about this when he wrote the
sanitization code and added some code to emit a metric if the sanitization
code errors out. If I had a graph in the dashboard showing this metric, I
would have seen it.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;"You should test your sanitization code!" you say! Right on! That's what we
should be doing! We have &lt;em&gt;unit tests&lt;/em&gt; but they run with ficticious data in a
pocket dimension. So they passed wonderfully despite the issue!&lt;/p&gt;
&lt;p&gt;What we needed was a few things:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;I needed to be able to run a fake Sentry service that I could throw errors
at and debug the sanitization code in my local environment without having to
spin up a real Sentry instance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I needed to be able to see exactly what is in the error payloads for my
application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I needed something I can use for integration tests with the sentry-sdk.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That's how I ended up putting aside all the things I needed to do and built
Kent.&lt;/p&gt;
&lt;aside class="footnote-list brackets"&gt;
&lt;aside class="footnote brackets" id="footnote-1" role="doc-footnote"&gt;
&lt;span class="label"&gt;&lt;span class="fn-bracket"&gt;[&lt;/span&gt;&lt;a role="doc-backlink" href="https://bluesock.org/~willkg/blog/dev/kent_0_1_0.html#footnote-reference-1"&gt;1&lt;/a&gt;&lt;span class="fn-bracket"&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;I don't intend to bash Sentry and the Sentry folks and all the work they
do. Their docs may be great. I'm probably the dumb one here.&lt;/p&gt;
&lt;/aside&gt;
&lt;/aside&gt;
&lt;/section&gt;
&lt;section id="so-what-is-kent"&gt;
&lt;h2&gt;So what is Kent?&lt;/h2&gt;
&lt;p&gt;Kent is a fake Sentry service. You can run it, set the Sentry DSN of your
application to something like &lt;code class="docutils literal"&gt;&lt;span class="pre"&gt;http://public@localhost:8000/1&lt;/span&gt;&lt;/code&gt;, and then Kent
will capture Sentry error reports.&lt;/p&gt;
&lt;p&gt;Kent takes 2 seconds to set up. You can run it locally:&lt;/p&gt;
&lt;pre class="literal-block"&gt;$ pip install kent
$ kent-server run&lt;/pre&gt;
&lt;p&gt;You can run it in a Docker container. There's a sample &lt;code class="docutils literal"&gt;Dockerfile&lt;/code&gt; in the
repo.&lt;/p&gt;
&lt;p&gt;It doesn't require databases, credentials, caching, or any of that stuff.&lt;/p&gt;
&lt;p&gt;Kent stores things in-memory. You don't have to clean up after it.&lt;/p&gt;
&lt;p&gt;Kent has a website letting you view errors with your browser.&lt;/p&gt;
&lt;p&gt;Kent has an API letting you build integration tests that create the errors and
then fetch them and assert things against them.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-questionable-architectural-decisions-did-you-make"&gt;
&lt;h2&gt;What questionable architectural decisions did you make?&lt;/h2&gt;
&lt;p&gt;I built it with &lt;a class="reference external" href="https://flask.palletsprojects.com/"&gt;Flask&lt;/a&gt;. Flask is great
for stuff like this--that part is fine.&lt;/p&gt;
&lt;p&gt;The part that's less fine is that I decided to put in the least amount of
effort in standing it up as a service and putting it behind a real WSGI server,
so I'm (ab)using Flask's cli and monkeypatching werkzeug to not print out
"helpful" (but in this case--unhelpful) messages to the console.&lt;/p&gt;
&lt;p&gt;I used &lt;a class="reference external" href="https://picocss.com/"&gt;pico.css&lt;/a&gt; because I read about it like
yesterday and it seemed easier to use that than to go fiddling with CSS
frameworks to get a really lovely looking site for a fake Sentry service.&lt;/p&gt;
&lt;p&gt;I may replace that at some point with something that involves less horizontal
space.&lt;/p&gt;
&lt;p&gt;I only wrote one test. I have testing set up, but only wrote one test to make
sure it's minimally viable. I may write more at some point.&lt;/p&gt;
&lt;p&gt;I only tested with Python sentry-sdk. I figure if other people need it, they
can let me know what else it works with and we can fix any issues that come up.&lt;/p&gt;
&lt;p&gt;I decided to store errors in memory rather than persist things to disk. That
was easy to do and seems like the right move. Maybe we'll hit something that
requires us to do something different.&lt;/p&gt;
&lt;p&gt;I named it Kent. I like short names. Friends suggested I name it Caerbannog
because it was a sentry of a sort. I love that name, but I can't reliably spell
it.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="released"&gt;
&lt;h2&gt;0.1.0 released!&lt;/h2&gt;
&lt;p&gt;I thought about making this 1.0.0, but then decided to put it into the world
and use it for a bit and fix any issues that come up and &lt;em&gt;then&lt;/em&gt; release 1.0.0.&lt;/p&gt;
&lt;p&gt;Initial release with minimally viable feature set.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;capture errors and keep them in memory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API endpoint to list errors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API endpoint to fetch error&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section id="where-to-go-for-more"&gt;
&lt;h2&gt;Where to go for more&lt;/h2&gt;
&lt;p&gt;History of releases:
&lt;a class="reference external" href="https://github.com/willkg/kent/blob/main/HISTORY.rst"&gt;https://github.com/willkg/kent/blob/main/HISTORY.rst&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Source code, issue tracker, documentation, and quickstart here:
&lt;a class="reference external" href="https://github.com/willkg/kent"&gt;https://github.com/willkg/kent&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let me know how this helps you!&lt;/p&gt;
&lt;p&gt;I say that in a lot of my posts. "Let me know how this helps you!" or "Comment
by sending me an email!" or something like that. I occasionally get a
response--usually from Sumana--but most often, it's me talking to the void. I
do an awful lot of work that theoretically positively affects thousands of
people to be constantly talking to the void.&lt;/p&gt;
&lt;p&gt;Let me know if you have positive or negative feelings about Kent by:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;click on this link: &lt;a class="reference external" href="https://github.com/willkg/kent/issues/3"&gt;https://github.com/willkg/kent/issues/3&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;add a reaction to the description which should be like two clicks&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><category>dev</category><category>kent</category><category>python</category><category>sentry</category><guid>https://bluesock.org/~willkg/blog/dev/kent_0_1_0.html</guid><pubDate>Wed, 05 Jan 2022 01:00:00 GMT</pubDate></item></channel></rss>