← Back to Home

Type challenge: Datadog Logs Preview

Generate a link to a log with filters for Datadog with Typescript types

At Slash, we love exploring what we can do with Typescript's type system to make our code more type-safe and maintainable. While not all uses of type safety are actually practically useful, we find them interesting and fun and when they don't affect maintainability, we'll occasionally keep them in our codebase as "easter eggs".

If you have a solution, send it over to us at engineering@slash.com.

Overview

0:00 / 0:00

We define "structured" logs in code and also define corresponding metrics on top of those logs that enable us to build dashboards and setup automated alerting. On Datadog, defining a metric on top of a log is called a Log Metric. A log metric is created with filters and aggregation rules to determine how to derive the metric from logs.

In our codebase, we have a simple set of strongly typed helpers to make it easier to define new logs and metrics for them (which is the code that you see on the right). We also have a "preview" helper for DX purposes. As a developer configures the filters for a metric, they can in real-time, preview the URL that Typescript computes and view the results in the browser to make sure they are applying the correct filters.

Challenge

Implement the type GetDatadogLogPreviewResponse so that we the correct Datadog URL is generated through types when we call metric.preview. The URL in the existing code is correct so you need to "fix" the type error.

These are Datadog's docs around how their log search syntax works. Any searchable log is also encodable in a URL of which they expose. Here's generally how URL encoded filters for logs works:

  1. The base URL is https://app.datadoghq.com/logs
  2. There is a single query parameter query that supports a URL encoded string of the entire search query.

Below lists examples for what an input -> output looks like. These all list the filters in a non-URI encoded string:

  1. Target: "apply duration equals 100" -> Output: query=@duration:100
  2. Target: "apply duration greater than 100" -> Output: query=@duration:>100
  3. Target: "apply http.status_code is not 200" -> Output: query=-@http.status_code:200
  4. Target: "apply http.status_code is 200 or 400" -> Output: query=(@http.status_code:200 OR @http.status_code:400)
  5. Target: "apply http.route is like /api/v1/*" -> Output: query=@http.route:/api/v1/*