from/prod
← All companies

THE COMPANY INDEX TRACKED BLOG

Marc Plano-Lesay

Ideas, decisions, and lessons from the team.

enoent.fr (opens on the source site)
18Posts tracked
6 months agoLatest publication
0.2Posts / month over the last 12 months

Latest writing

18 of 18 posts

Shipping logs to Loki (opens on the source site)

When metrics aren't the whole story In the previous post, we set up metrics collection with Prometheus. We can now see what is happening on our devices — a sensor is failing, the WiFi signal is degrading, or the main loop is running slow. But metrics alone don't tell us why. When a device reboots, the uptime metric resets — but what caused the reboot? When an entity fails, the _failed metric goes to 1 — but what error occurred?

Read at the source

Scraping ESPHome metrics with Prometheus (opens on the source site)

What is observability and why does it matter? ESPHome is an amazing tool. Devices you build with it are very useful. But how do you notice when they don't work? You would eventually notice if a temperature sensor stopped working and your climate control automations aren't working as intended. While that's not ideal, it gets worse: what about a sensor part of an alarm system, detecting that a window is open?

Read at the source

Ktor: Altering served content (opens on the source site)

When serving files with Ktor, there might be times when you need to alter those files. For example, you might want to inject a script in every served HTML file. For this purpose, we can leverage plugins. Plugins can hook at different stages of the request/response pipeline: graph LR Request --> Plugin1[Plugin] Plugin1 --> Handler Handler --> Plugin2[Plugin] Plugin2 --> Response Ktor request/response pipeline Let's write a plugin that transforms a specific type of files - going with the previous example of injecting a script to every served HTML file. Our plugin needs to: Take a script URL as…

Read at the source

Serving static files with Ktor (opens on the source site)

Serving static files with Ktor for a static website seems easy enough: fun main() { embeddedServer(Netty, port = 8080) { routing { static { files("static-data") } } }.start(wait = true) } Done? Not quite. Opening http://localhost:8080 will only get you a 404, even if you have an index.html file in the static-data folder. You have to let Ktor know you want to opt-in serving a default file. Let's try again (omitting anything outside the static block): static { files("static-data") default("static-data/index.html") } Surely now this works? Well, kind of. The root folder will have a default…

Read at the source

Writing a Bazel rule set (opens on the source site)

This post will cover two things: How to run an arbitrary tool with Bazel (in this case, PlantUML, a tool to generate diagrams), by writing a rule set How to test this rule set. It should be mentioned that while I was working on this rule set, it became more and more apparent PlantUML is not a great candidate for this kind of integration, as its output is platform-dependent (the font rendering). Despite that, it's still a simple tool and as such its integration is simple, albeit not perfect (the rendering tests I wrote need to run on the same platform every time). PlantUML usage PlantUML is a…

Read at the source

Compiling a Kotlin application with Bazel (opens on the source site)

This post will describe how to compile a small application written in Kotlin using Bazel, tests, as well as how to use static analyzers. Phosphorus Phosphorus is the application that this post will cover. It's a small utility that I wrote to check if an image matches a reference. If it doesn't, Phosphorus generates an image highlighting the differences. The goal is to be able to check that something generates an image in a given way, and doesn't change - at least if it's not expected. The actual usage will be covered later in this series. While it's not open-source yet, it's something I…

Read at the source

Why Bazel? (opens on the source site)

In this post, we'll cover what Bazel is, how to use it, and why I chose to use it. What is Bazel? Bazel is a build-system released by Google in 2015. It actually is derived from the internal build-system Google uses internally for most of its own code-base, called Blaze. Building at scale Bazel has a huge focus on hermetic builds, and reproducibility. Every build step is, from a really broad perspective, defined as a list of inputs, tools, and outputs. This allows for efficient and robust caching (if no inputs nor tools changed, then this target doesn't need to be rebuilt, and this cascades…

Read at the source

A new beginning (opens on the source site)

This blog has been inactive for a long time. I tried to at least post an article yearly, and next thing you know, two years and a half fly by… Halloween seemed like a good time to resurrect it. I wanted to start writing again recently, and faced an issue: this blog was using Octopress 2. Well, Octopress has apparently been dead for even longer than this blog. So I wanted to switch to another static generator. I found Hugo, which is actively maintained and ticked all the boxes I had, so that's what I settled for (sorry for the probable RSS feed mess - while I set up 301 redirects for the old…

Read at the source

Compat libraries incompatibilities (opens on the source site)

Compat libraries are great. They allow us to work with the newest Android APIs, without thinking (much) about your minimum API level. Instead of thousands of devices, you can reach billions. With nearly no changes in your code. But sometimes, they're not so great…

Read at the source

Android Things: first look (opens on the source site)

What is Android Things? Android Things is an alternative Android version, announced at Google I/O 2015, and released as a first developer preview in December 2016. Its purpose is to develop embedded IoT devices, with a known and widely documented Android ecosystem basis. It's currently running on three different boards: the Intel Edison, the NXP Pico i.MX6UL, and the Raspberry Pi 3. Some higher-end boards are coming soon. On the SDK side, Android Things comes with a specific support library to ease low-level hardware usage. It consists in two parts: the Peripheral I/O API, which supports…

Read at the source

Use Apache HTTP Client on Android SDK 23 (opens on the source site)

With the Android M SDK (API 23), Google removed the Apache HTTP Client library. It was deprecated since API 22, and Google recommended to use HttpURLConnection instead since API 9. While the classes are still bundled in Android 6 ROMs, it won't be long until we see them completely go away. Some applications are still relying on this library, and need to be updated to use the SDK 23, without having time/budget/whatever required to switch from HTTP Client. While I strongly recommend you to still take time to move to something else (there are many high-level libraries, like OkHttp or Ion, or you…

Read at the source

Share code across multiple platforms (opens on the source site)

When writing an application, you probably want it to run on most platforms possible. Having a game on Android is great, but what about this weird friend with his iPhone? It would be nice to be able to play with him. Of course there are cross-platforms technologies like Cordova or Titanium. But sadly, you can't achieve both a perfect user experience and great performances with this kind of tools. And even if you could: what about reusing code on the back-end? We need to share some code.

Read at the source

RecyclerView basics (opens on the source site)

Introduction to RecyclerView RecyclerView has been introduced with Android 5, in the support-v7 package. It allows to display a collection of items in an arbitrary disposition (think of a ListView, but much more flexible). As the name of the support package indicates, it's available from the API level 7 (Android 2.1). Its name comes from the way it works: when an item is hidden, instead of being destroyed and a new one being created for each newly displayed item, hidden ones are recycled: they are reused, with new data bound on them.

Read at the source

Hosting different kinds of apps on nginx (opens on the source site)

Engine what? Nginx (engine-x) is a web server and reverse proxy for web and mail protocols (HTTP, HTTPS, SMTP, POP3 and IMAP). It has been first released in 2004, and its usage keeps growing ever since (according to Netcraft, it was hosting 14.47% of active sites in August 2014). It's capable of hosting many kinds of applications: static HTML pages PHP, using PHP-FPM Ruby on Rails and any kind of Rack-based Ruby application, using Phusion Passenger proxying requests to another webserver (e.g. a software launching its own web server, like Kodi)

Read at the source

Using an API - Trakt.tv example (opens on the source site)

A lot of websites are generating data which could be really useful outside a web browser. Having the weather shown on your smartphone's lock-screen, the delay until your next bus… How can we use this from an application? This article will explain what's behind these hidden data flows, and how to use them. For this purpose, I'll use Trakt.tv as an example. If you don't know it: Trakt allows you to manage your movie/TV series library, keep track of watch progress, your ratings, comments… and see those of other people. Some code will show how to send such requests. It will be written in Ruby.

Read at the source

Compile FFmpeg for Android (opens on the source site)

When you have to manipulate audio or video on Android, being used to open-source software, you have a single name which comes directly to you: FFmpeg. However, FFmpeg is a C software, meant to be used as an executable, and not officially supporting Android. There are a lot of partial and/or out-of-date how-to out there on how to get FFmpeg running on Android, like halfninja's build. However, I needed to use FFmpeg concat demuxer, introduced in FFmpeg 1.1. Most builds target 0.9. There's a ton of questions on StackOverflow about getting newer FFmpeg releases working on Android. So, here's a…

Read at the source

Android: display a Dialog from an AppWidget (opens on the source site)

Issue When you want to display a dialog, you don't only need a context, you need an activity context. From an activity, displaying a dialog is pretty straightforward: Display a dialog from an activity new AlertDialog.Builder(MyActivity.this) .setTitle("Dialog title") .setMessage("Dialog message") .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // Handle a positive answer } }) .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int…

Read at the source

Privacy choices

Reading never requires analytics. These choices last 90 days on this browser.

Essential sign-in and security storage always stays on. Read the privacy notice.