Skip to content

Commit

Permalink
Edit Readme (and fix bugs) (#71)
Browse files Browse the repository at this point in the history
* fix: typescript plugin bug

* shorten the readme

* Apply suggestions from code review

Co-authored-by: Evan Schwartz <[email protected]>

* readme changes based on comments

---------

Co-authored-by: Evan Schwartz <[email protected]>
  • Loading branch information
keturiosakys and emschwartz authored Jun 16, 2023
1 parent e6f9ace commit dc129ec
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 239 deletions.
313 changes: 74 additions & 239 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,305 +2,140 @@

<div align="center">
<h1>Autometrics</h1>
<a href="https://github.com/autometrics-dev/autometrics-ts/actions?query=branch%3Amain"><img src="https://github.com/autometrics-dev/autometrics-ts/actions/workflows/check_wrappers.yml/badge.svg?event=push&branch=main" alt="Autometrics CI status" /></a>
<a href="https://github.com/autometrics-dev/autometrics-ts/actions?query=branch%3Amain"><img src="https://github.com/autometrics-dev/autometrics-ts/actions/workflows/ci.yml/badge.svg?event=push&branch=main" alt="Autometrics CI status" /></a>
<a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/npm/l/@autometrics/autometrics" alt="License"></a>
<a href="https://discord.gg/MJr7pYzZQ4" rel="nofollow"><img src="https://img.shields.io/discord/950489382626951178?label=Discord&logo=discord&logoColor=white" alt="discord server"></a>
</div>

<hr />

> A TypeScript port of the Rust
> [autometrics-rs](https://github.com/fiberplane/autometrics-rs) library
Metrics are a powerful and cost-efficient tool for understanding the health and performance of your code in production. But it's hard to decide what metrics to track and even harder to write queries to understand the data.

**A library that makes it easy to understand the error rate, response time, and
production usage of any function in your code.** Jump straight from your IDE to
live Prometheus charts for each HTTP/RPC handler, database method, or other
piece of application logic.
Autometrics provides a wrapper function and decorator to instrument functions, classes, and methods with the most useful metrics: request rate, error rate, and latency. It standardizes these metrics and then generates powerful Prometheus queries based on your function details to help you quickly identify and debug issues in production.

Autometrics for TypeScript provides a wrapper function and a decorator that can
create Prometheus or OpenTelemetry metrics for your functions and class methods
throughout your code base, as well as a language service plugin that will write
corresponding Prometheus queries for you.
[Learn more about Autometrics at autometrics.dev](https://autometrics.dev/).

See [Why Autometrics?](https://github.com/autometrics-dev#why-autometrics) for
more details on the ideas behind autometrics
## Benefits

![AutometricsTS demo](./assets/autometrics-ts-demo.gif)

## Features

-`autometrics` wrapper instruments any function or class method to track its
most useful metrics
- 🌳 Works in NodeJS and browser environments (Deno and serverless support coming soon)
- 💡 Writes Prometheus queries so you can understand the data generated without
knowing PromQL
-`autometrics()` wrapper / `@Autometrics()` decorator instruments any function or class method to track its most useful metrics
- 🌳 Works in NodeJS and has experimental support for Deno and browser environments
- 💡 Writes Prometheus queries so you can understand the data generated without knowing PromQL
- 🔗 Injects links to live Prometheus charts directly into each function's doc
comments
- [📊 Grafana dashboards](#dashboards) work out of the box to visualize the performance of instrumented functions & SLOs
- 🚨 Generates Prometheus alerting rules using SLO best practices
from simple annotations in your code
- 🔍 Helps you to [identify commits](https://docs.autometrics.dev/typescript/adding-version-information) that introduced errors or increased latency
- 📊 [Grafana dashboards](https://github.com/autometrics-dev/autometrics-shared#dashboards) work out of the box and visualize the performance of instrumented functions & SLOs
- ⚡ Minimal runtime overhead

## How it works
## Advanced Features
- 🚨 Allows you to [define alerts](https://docs.autometrics.dev/typescript/adding-alerts-and-slos) using SLO best practices directly in your source code comments

The Autometrics library:

- Automatically instruments any wrapped function with OpenTelemetry metrics
- Uses a Prometheus Exporter to write metrics to a `/metrics` endpoint (by
default on port `:9464`) or pushes them to a specified gateway (if used in
browser)
- Uses a TypeScript plugin / VSCode extension to automatically add useful Prometheus queries in the doc comments for instrumented functions

## Quickstart

```shell
npm install --save autometrics
```

Use the library in your code:
## Example

```typescript
import { autometrics } from "autometrics";
```

> Note for VSCode users: Make sure you set your VSCode TypeScript server
> to be local to the project (where you have TypeScript installed in your
> `devDependencies`).
>
> In `.vscode/settings.json` set:
>
> ```json
> {
> "typescript.tsdk": "node_modules/typescript/lib"
> }
> ```
### For projects already using OpenTelemetry metrics
The default `autometrics` package bundles `@opentelemetry/sdk-metrics` and
`@opentelemetry/exporter-prometheus` dependencies. If you are already using
these in your codebase or want to use other custom metrics, use the following
installation option.
Install the wrappers:
```shell
npm install --save @autometrics/autometrics
```
Import and use the library in your code:
const createUserWithMetrics = autometrics(async function createUser(payload: User) {
// ...
});

```typescript
import { autometrics } from "@autometrics/autometrics"
createUserWithMetrics();
```

## Getting PromQL queries
![AutometricsTS demo](./assets/autometrics-ts-demo.gif)

In order to get PromQL query links in your IDE download the [Autometrics VSCode
extension](https://marketplace.visualstudio.com/items?itemName=Fiberplane.autometrics).
## Quickstart

If you're on any other IDE you can install and add the TypeScript plugin
directly:
1. **Install the library**

```bash
npm install --save-dev @autometrics/typescript-plugin
```

Add the language service plugin to the `tsconfig.json` file:

```json
{
"compilerOptions": {
"plugins": [
{
"name": "@autometrics/typescript-plugin",
"prometheusUrl": ""
}
]
}
}
```

## Dashboards

Autometrics provides [Grafana dashboards](https://github.com/autometrics-dev/autometrics-shared#dashboards) that will work for any project instrumented with the library.

## Identifying commits that introduce errors

Autometrics makes it easy to [spot versions and commits that introduce errors or latency](https://fiberplane.com/blog/autometrics-rs-0-4-spot-commits-that-introduce-errors-or-slow-down-your-application).

| Label | Run-Time Environment Variables | Default value |
|---|---|---|
| `version` | `AUTOMETRICS_VERSION` or `PACKAGE_VERSION` | `npm_package_version` (set by npm/yarn/pnpm by default) |
| `commit` | `AUTOMETRICS_COMMIT` or `COMMIT_SHA` | `""` |
| `branch` | `AUTOMETRICS_BRANCH` or `BRANCH_NAME` | `""` |

## Alerts / SLOs

Autometrics makes it easy to add Prometheus alerts using Service-Level Objectives (SLOs) to a function or group of functions.

This works using pre-defined [Prometheus alerting rules](https://github.com/autometrics-dev/autometrics-shared/blob/main/autometrics.rules.yml) (read more about alerting rules in general [here](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/)).
By default, most of the recording rules are dormant. They are enabled by specific metric labels that can be automatically attached by autometrics.

To use autometrics SLOs and alerts, create one or multiple [`Objective`s](https://github.com/autometrics-dev/autometrics-ts/blob/main/packages/autometrics-lib/src/objectives.ts) based on the function(s) success rate and/or latency, as shown below. The `Objective` can be passed as an argument to the `autometrics` wrapper function to include the given function in that objective.

```ts
import { autometrics, Objective, ObjectiveLatency, ObjectivePercentile } from "@autometrics/autometrics";

const API_SLO: Objective = {
name: 'api',
successRate: ObjectivePercentile.P99_9,
latency: [ObjectiveLatency.Ms250, ObjectivePercentile.P99],
};

const apiHandlerFn = autometrics({ objective: API_SLO }, function apiHandler(
// ...
));
npm install --save autometrics
# or
yarn add --save autometrics
# or
pnpm add --save autometrics
```

## Using wrappers and decorators in NodeJS
Use Autometrics wrappers to instrument the functions you want to track (e.g.:
request handlers or database calls).
### Wrapping plain-old functions
Wrappers are simple functions that wrap the original function declaration and
instrument it with metrics. They allow the language service plugin to add
additional information in the type docs.
Use function wrappers to wrap request handlers, database calls, or other
pieces of important business logic that you want to measure.
> **Note**: Wrapped functions must be named. Autometrics will throw an error if
> it can't access the name of the function.
Example:
2. **Instrument your code using the `autometrics` wrapper or `Autometrics` decorator**

```typescript
import { autometrics } from "autometrics";

const createUser = autometrics(async function createUser(payload: User) {
const createUserWithMetrics = autometrics(async function createUser(payload: User) {
// ...
});

const user = createUser();
createUserWithMetrics();
```

> **Note**: If you're using the `@autometrics/autometrics` package instead of
> `autometrics`, import the helper functions from there:
>
> ```typescript
> import { autometrics } from "@autometrics/autometrics";
> ```
### Decorating class methods
When using a decorator for a class method, it is wrapped in additional code that
instruments the method with OpenTelemetry metrics.
Here's a snippet from the example code:
```typescript
import { Controller, Get } from "@nestjs/common";
import { AppService } from "./app.service";
import { Autometrics } from "autometrics";

@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}

@Get()
class User {
@Autometrics()
getHello(): string {
return this.appService.getHello();
async createUser(payload: User) {
// ...
}
}
```

Alternatively, you can apply the same decorator to a class to instrument all of
its methods:
3. **Configure Prometheus to scrape the data**

```typescript
// ...
@Autometrics()
export class AppController {
// ...
@Get()
getHello(): string {
return this.appService.getHello();
}
}
```
By default the TypeScript library makes the metrics available on `<your_host>:9464/metrics`. Make sure your Prometheus is configured correctly to scrape it.

### Getting the generated queries
Here's a minimal sample Prometheus configuration you can use:

Hover over any Autometrics-instrumented function or class to see its augmented documentation.
Clicking on any of the links will go directly to the Prometheus
chart for that function.
![Autometrics demo](./assets/demo.png)
```yaml
scrape_configs:
- job_name: my-app
metrics_path: /metrics
static_configs:
- targets: ['localhost:9464']
# For a real deployment, you would want the scrape interval to be
# longer but for testing, you want the data to show up quickly
scrape_interval: 200ms
```
## Using wrappers in the browser
[See the docs](https://docs.autometrics.dev/configuring-prometheus/local) for more Prometheus configurations.
### Set up the push gateway
4. **Install the IDE extension**
In order for Prometheus to succesfully get your client-side app metrics, you
will need to push them to an aggregating push gateway [like this
one](https://github.com/zapier/prom-aggregation-gateway).
In order to get charts in VSCode, download the [Autometrics VSCode extension](https://marketplace.visualstudio.com/items?itemName=Fiberplane.autometrics).
Use the `init` function to configure the gateway URL that autometrics should push
data to. You can also set the push interval with the `pushInterval` property
(default is every 5000 miliseconds);
<details>
<summary>
If you're on any other IDE you can install and add the TypeScript plugin
directly:
</summary>
```typescript
init({ pushGateway: "<link_to_gateway>" });
```bash
npm install --save-dev @autometrics/typescript-plugin
```

### Use Autometrics wrapper with options
The same wrapper functions can be used in browser environments. Note that bundlers often change the names of functions and modules in production, which can impact the library.
To get around this issue, wrappers accept an options object as
their first argument, which explicitly assigns a function and module name.
Add the language service plugin to the `tsconfig.json` file:

```typescript
const myFunction = autometrics(
{
functionName: "myFunction",
moduleName: "Module",
},
async () => {
// ... myFunction body
```json
{
"compilerOptions": {
"plugins": [
{
"name": "@autometrics/typescript-plugin",
"prometheusUrl": ""
}
]
}
);
}
```

## Configuration
</details>

### Set your own Exporter
By default, autometrics exposes your metrics with OpenTelemetry's Prometheus
Exporter on port `:9464`, using the endpoint `/metrics`. You can configure it as you wish,
however, by using the `init` function.
Here is an example that sets the exporter to use port 7777:
```javascript
import { autometrics, init } from "@autometrics/autometrics";
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";

const exporter = new PrometheusExporter({ port: 7777 });
init({ exporter });
```
## [Documentation](https://docs.autometrics.dev/typescript/quickstart)

### Language service plugin
## [API Reference](./packages/lib/reference/README.md)

The language service plugin can be configured in the `tsconfig.json` file.
## Contributing

#### Options
Issues, feature suggestions, and pull requests are very welcome!

| key | description |
| --------------- | --------------------------------------------------------------- |
| `name` | always `@autometrics/typescript-plugin` |
| `prometheusUrl` | sets the base URL for PromQL queries. Default: `localhost:9090` |
If you are interested in getting involved:
- Join the conversation on [Discord](https://discord.gg/9eqGEs56UB)
- Ask questions and share ideas in the [Github Discussions](https://github.com/orgs/autometrics-dev/discussions)
- Take a look at the overall [Autometrics Project Roadmap](https://github.com/orgs/autometrics-dev/projects/1)
1 change: 1 addition & 0 deletions packages/typescript-plugin/src/astHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export function getNodeType(node: ts.Node, typechecker: ts.TypeChecker) {
// const funcWithMetrics = autometrics(originalFunc);
if (
ts.isVariableDeclaration(declaration?.valueDeclaration) &&
declaration?.valueDeclaration?.initializer &&
ts.isCallExpression(declaration?.valueDeclaration?.initializer)
) {
return "function";
Expand Down

0 comments on commit dc129ec

Please sign in to comment.