Zuplo
Data & Security

Hydrolix / Akamai Traffic Peak Plugin

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

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:

TypeScriptmodules/zuplo.runtime.ts
import { ZuploRequest, HydrolixRequestLoggerPlugin, HydrolixDefaultEntry, environment, } from "@zuplo/runtime"; import { environment, HydrolixRequestLoggerPlugin, HydrolixDefaultEntry, defaultGenerateHydrolixEntry, } from "@zuplo/runtime"; export function runtimeInit(runtime: RuntimeExtensions) { 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, }), ); }

Note, the token (HYDROLIX_TOKEN above) is a Streaming Auth Token.

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

TypeScriptmodules/zuplo.runtime.ts
import { ZuploRequest, HydrolixRequestLoggerPlugin, environment, } from "@zuplo/runtime"; // 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; } export function runtimeInit(runtime: RuntimeExtensions) { 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"), }), }), ); }

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.

Last modified on