linkerd / linkerd/linkerd2

Add support for configuring route name via Open API spec

Open
#6,628 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/cli area/profiles enhancement help wanted
Dominant language
Go
Stars
11.5k
Forks
1.4k
Avg merge
3d 22h
Merged PRs (30d)
53

Description

## Feature Request

### What problem are you trying to solve?

Each telemetry tool seems to have its own convention for identifying HTTP routes:
- `GET /pet/{petId}` (as in LinkerD)
- vs `get /pet/:petId` (as in Zipkin's `http.route` tag)
- vs `get_/pet/_petId_` (as in Datadog APM's `resource_name` tag)

Our SRE team is considering leveraging the Open API spec (maybe the native `operationId`) to define a _canonical identifier_ for each HTTP route in the enterprise. This concretely looks like providing "product teams" with easy hooks to associate the identifier label with all telemetry data (metris, logs, traces) associated with a given route; the ubiquity of the identifier will then make it possible for platform teams to a variety of tools with self-service capabilities (e.g. auto-generated Datadog Dashboards, CloudWatch Alarms, etc.) _without_ having to know the HTTP route formatting nuances of each tool in our ecosystem.

If there was a way to control the `route.name` of Service Profiles generated with an Open API definition it would be much easier to integrate LinkerD into our internal tool ecosystem. For instance it would be trivial to build tools that take a service's Open API definition and:
- find all Service Profile routes associated with a given service
- auto-generate a Datadog dashboard widget slicing & dicing the LinkerD metrics for each route

### How should the problem be solved?

Ideally users would be able use some aspect of the Open API spec to control the `route.name` attribute when auto-generating a Service Profile with the `--openapi` flag.

I propose offering an _info-level_ vendor extension `x-linkerd-route-lookup`* that allows users to indicate a `path` attribute to lookup (via [operation.JSONLookup](https://github.com/go-openapi/spec/blob/master/operation.go#L107)) and overwrite the `route.name`:
```yaml
info:
title: ACME Pet API
x-linkerd-route-lookup: operationId
# x-linkerd-route-lookup: x-acmecorp-route
# ...
paths:
/pets/{id}:
get:
operationId: get_pets
# x-acmecorp-route: get_pets
# ...
```

### Any alternatives you've considered?

A. The most naive approach would be to set `route.name` equal to the `operationId` when it's available. Sadly, some popular tools auto-populate the `operationId` field using [less-than-ideal conventions](https://springfox.github.io/springfox/docs/snapshot/#the-default-value-of-operationid-according-to-springfox), and it's likely that elevating the `operationId` to the default `route.name` would have unintentional & undesirable side effects for many users.

B. Another approach would be to follow the precedent set by https://github.com/linkerd/linkerd2/pull/4072 and https://github.com/linkerd/linkerd2/pull/4052 and allow users to decorate _each route_ with a vendor extension (maybe `x-linkerd-route`?). In effect, though, this would create cruft for the users who are most likely to need this feature (and might already have a _per-route_ vendor extension of their own):
```yaml
paths:
/pets/{id}:
get:
operationId: get_books
x-acmecorp-route: get_books
x-linkerd-route: get_books
# ...
```

### How would users interact with this feature?

Users would activate this feature by adding the vendor extension `x-linkerd-route-lookup`* to the `info` section of the Open API spec before passing it into the `linkerd profile --open-api {{spec}} {{service}}` command. For instance, consider a route whose `route.name` resolves to:

```
GET /pets/{id}
```
The user might want to make LinkerD routes & metrics consistent with other tools that use the `operationId` field to identify unique routes. This can be achieved using the `x-linkerd-route-lookup`*

```yaml
info:
x-linkerd-route-lookup: operationId
paths:
/pets/{id}:
get:
operationId: get_pet_by_id
```
Alternatively if the user's platform team has already coined an extension to serve the same purpose they can provide that instead:
```yaml
info:
x-linkerd-route-lookup: x-acmecorp-route
paths:
/pets/{id}:
get:
x-acmecorp-route: get_pet_by_id
```

---
*`x-linkerd-route-lookup` is the first thing that came to mind, I don't have a strong opinion for how this is named.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the `linkerd profile --open-api` entry point and trace how OpenAPI operations become Service Profile `route.name` values; the issue points to `operation.JSONLookup` as the lookup behavior to understand. Done means an info-level `x-linkerd-route-lookup` setting can select an operation field or extension for route names, with existing naming behavior preserved when it is absent.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, openapi
Domain
api, observability
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.