# Loki Logging Plugin

The Loki Log plugin enables pushing logs to your Loki server.

<EnterpriseFeature name="Custom logging" />

## Setup

To add the Loki logging plugin to your Zuplo project, add the following code to
your `zuplo.runtime.ts` file.

```ts title="modules/zuplo.runtime.ts"
import {
  RuntimeExtensions,
  LokiLoggingPlugin,
  environment,
} from "@zuplo/runtime";

export function runtimeInit(runtime: RuntimeExtensions) {
  runtime.addPlugin(
    new LokiLoggingPlugin({
      // This is the URL of your Loki server
      url: "https://logs-prod-us-central1.grafana.net/loki/api/v1/push",
      username: "my-username",
      job: "my-api",
      password: environment.LOKI_PASSWORD,
      version: 2,
      fields: {
        field1: "value1",
        field2: "value2",
      },
    }),
  );
}
```

## Configuration Options

The `LokiLoggingPlugin` constructor accepts an options object with the following
properties:

- `url` - (required) The URL of the Loki server (for example,
  `https://logs-prod-us-central1.grafana.net/loki/api/v1/push`)
- `username` - (required) Username for authentication
- `password` - (required) Password for authentication
- `version` - (optional) The version of the Loki transport to use. Version 2
  includes tracing information in log values
- `job` - (optional) Job name to include in the log stream. Defaults to "zuplo"
- `fields` - (optional) Custom fields to include in each log entry. Can contain
  string, number, or boolean values

### Custom Fields

Any custom fields you want to include in the log entry can be added to the
`fields` property. These values will be appended to every log entry.

### Version Configuration

Setting the `version` option to `2` changes the log stream to not include the
`requestId` value in the stream, but rather include it as a log value with other
tracing information.

## Default Fields

Every log entry will have a timestamp and structured data. The structure varies
based on the version configuration.

### Stream Labels (all versions)

- `job` - The name of the log stream job. Defaults to "zuplo"
- `level` - The log level (for example, `ERROR`, `INFO`, `DEBUG`, `WARN`)
- `environmentType` - Where the Zuplo API is running. Values are `edge`,
  `working-copy`, or `local`
- `environmentStage` - The deployment stage: `working-copy`, `preview`, or
  `production`

### Log Fields (version 2+)

When using version 2 or later, the following fields are included in the log
values:

- `requestId` - The UUID of the request (the value of the `zp-rid` header)
- `atomicCounter` - An atomic counter used to order logs with identical
  timestamps
- `rayId` - The network provider identifier (for example, Cloudflare Ray ID) of
  the request

:::note

Log trace fields are only included in the log values when the `version` option
is set to `2` or later. In version 1, `requestId` is included as a stream label.

:::

## Log Format

The shape of the logs sent from Zuplo will be in the following format. If using
version 2, tracing info (`requestId`, etc.) will be included in the log values.

```json
{
  "streams": [
    {
      "stream": {
        "job": "zuplo",
        "level": "debug",
        "environmentType": "local",
        "environmentStage": "local"
      },
      "values": [
        [
          "1712254635666000000",
          "Request received '/hello-world'",
          {
            "requestId": "9b9cd3fd-b0fa-455f-b894-4a5c2c9d131b",
            "rayId": "1235567",
            "atomicCounter": 123435346
          }
        ],
        [
          "1712254635666000000",
          "{\"method\":\"GET\",\"url\":\"/hello-world\",\"hostname\":\"localhost\",\"route\":\"/hello-world\"}",
          {
            "requestId": "9b9cd3fd-b0fa-455f-b894-4a5c2c9d131b",
            "rayId": "1235567",
            "atomicCounter": 123435347
          }
        ]
      ]
    }
  ]
}
```
