Data & Security

Hydrolix / Akamai Traffic Peak Plugin

This plugin pushes request/response logs to Hydrolix AKA Akamai Traffic Peak.

Enterprise Feature

Custom logging is available as an add-on as part of an enterprise plan. If you would like to purchase this feature, please contact us at sales@zuplo.com or reach out to your account manager.

Most enterprise features can be used in a trial mode for a limited time. Feel free to use enterprise features for development and testing purposes.

Setup

You can define the fields created in the JSON object by creating a custom type in TypeScript and a function to extract the field data from the Response, ZuploRequest, and ZuploContext.

The plugin is configured in the Runtime Extensions file zuplo.runtime.ts:

This logger includes a default type and function that logs the following fields:

  • deploymentName <string> - The name of the deployment.
  • timestamp <string> - The time the log was created.
  • requestId <string> - The UUID of the request (the value of the zp-rid header).
  • routePath <string> - The path of the route.
  • operationId <string | undefined> - The operation ID.
  • url <string | undefined> - The URL of the request.
  • statusCode <number | undefined> - The status code of the response.
  • durationMs <number | undefined> - The duration of the request in milliseconds.
  • method <string> - The HTTP method of the request.
  • userSub <string | undefined> - The user sub.
  • instanceId <string | undefined> - The instance ID.
  • colo <string | undefined> - The colo (datacenter) of the request.
  • city <string | undefined> - The city the request origin.
  • country <string | undefined> - The country the request origin.
  • continent <string | undefined> - The continent the request origin.
  • latitude <string | undefined> - The latitude of the request origin.
  • longitude <string | undefined> - The longitude of the request origin.
  • postalCode <string | undefined> - The postal code of the request origin.
  • metroCode <string | undefined> - The metro code of the request origin.
  • region <string | undefined> - The region of the request origin.
  • regionCode <string | undefined> - The region code of the request origin.
  • timezone <string | undefined> - The timezone of the request origin.
  • asn <string | undefined> - The ASN of the request origin.
  • asOrganization <string | undefined> - The AS organization of the request origin.
  • clientIP <string | undefined> - The client IP of the requestor.
  • zuploUserAgent <string | undefined> - The Zuplo user agent.

To use this default setup add the following code to your zuplo.runtime.ts file:

modules/zuplo.runtime.ts
import {
  environment,
  HydrolixRequestLoggerPlugin,
  HydrolixDefaultEntry,
  defaultGenerateHydrolixEntry,
} from "@zuplo/runtime";

runtime.addPlugin(
  new HydrolixRequestLoggerPlugin<HydrolixDefaultEntry>({
    hostname: "your-hydrolix-hostname.com",
    username: "your-hydrolix-username",
    password: environment.HYDROLIX_PASSWORD,
    token: environment.HYDROLIX_TOKEN,
    table: "your-table.name",
    transform: "your-transform-name",
    generateLogEntry: defaultGenerateHydrolixEntry,
  }),
);
ts

If you want to customize the data written to Hydrolix, you can define the fields and entry generation function yourself as follows:

modules/zuplo.runtime.ts
// The interface that describes the rows
// in the output
interface LogEntry {
  timestamp: string;
  method: string;
  url: string;
  status: number;
  statusText: string;
  sub: string | null;
  contentLength: string | null;
}

runtime.addPlugin(
  new HydrolixRequestLoggerPlugin<LogEntry>({
    hostname: "your-hydrolix-hostname.com",
    username: "your-hydrolix-username",
    password: environment.HYDROLIX_PASSWORD,
    token: environment.HYDROLIX_TOKEN,
    table: "your-table.name",
    transform: "your-transform-name",
    batchPeriodSeconds: 0.1,
    generateLogEntry: (response: Response, request: ZuploRequest) => ({
      // You can customize the log entry here by adding new fields
      timestamp: new Date().toISOString(),
      url: request.url,
      method: request.method,
      status: response.status,
      statusText: response.statusText,
      sub: request.user?.sub ?? null,
      contentLength: request.headers.get("content-length"),
    }),
  }),
);
ts

Entries will be batched and sent as an array, they will be sent every batchPeriodSeconds. If not specified the will be dispatched very frequently (~every 10ms) to avoid data loss. Note that batchPeriodSeconds can be specified as a fraction, e.g. 0.1 for every 100ms.