Skip to content
AniLink

Observability

Four hooks report request lifecycle events. They are configured per provider slot and never leak between providers.

Hook contracts

HookFiresPayload
onRequestStartImmediately before each attempt is sent{ url, method, attempt }
onResponseAfter each attempt completes, success or failure{ url, method, attempt, durationMs }
onErrorWhen an attempt fails, before each retry wait, and once more when retries are exhausted(error: AniLinkError, context) with context = { url, method, attempt, code, status?, nextDelayMs? }
onRetryWhen a failed attempt is going to be retriedSame shape as onError with nextDelayMs set

attempt is 1-based. durationMs is the elapsed wall-clock time of the attempt, making onResponse the natural point for latency metrics.

Firing order

onError fires for every failed attempt. onRetry fires only when another attempt will follow.

Usage

typescript
import { AniLink } from "anilink-api-wrapper";

const aniLink = new AniLink("token", {
    onRequestStart: ({ url, attempt }) => {
        console.log("start", attempt, url);
    },
    onResponse: ({ url, durationMs }) => {
        console.log(url, `${durationMs}ms`);
    },
    onError: (error, { attempt, code }) => {
        console.error("attempt", attempt, "failed", code, error.message);
    },
    onRetry: (_error, { attempt, nextDelayMs }) => {
        console.log("retrying after", nextDelayMs, "ms; next attempt", attempt);
    },
});

Hook isolation

Hooks belong to the provider slot where they are declared. A hook registered for AniList never observes MAL traffic and vice versa:

typescript
const aniLink = new AniLink({
    anilist: { authToken: "t", onResponse: ({ durationMs }) => metrics.record(durationMs) },
    mal: { accessToken: "m" }, // no hooks — MAL traffic is unobserved
});

Next steps

AniLink — typed AniList & MyAnimeList client for TypeScript.