Parseable
Ingest dataAi agentsTemporal

TypeScript

Install and configure the @parseable/temporal plugin for Temporal TypeScript workers


The @parseable/temporal plugin is a Temporal middleware that ships workflow and activity execution events to Parseable. See the Temporal overview for the full schema, example queries, and shared caveats.

Prerequisites

  • Node.js 20+
  • A Temporal worker built on @temporalio/worker v1.13+ (plugin API based)
  • A reachable Parseable instance

Installation

npm install @parseable/temporal

Configuration

Install Temporal runtime telemetry once, before you create the Worker or Client. The Parseable plugin configuration stays inside Worker.create.

import { Runtime, Worker } from '@temporalio/worker';
import { ParseablePlugin } from '@parseable/temporal';

Runtime.install({
  telemetryOptions: {
    metrics: {
      prometheus: {
        bindAddress: '0.0.0.0:9464',
      },
    },
  },
});

const worker = await Worker.create({
  taskQueue: 'hello-world',
  workflowsPath: require.resolve('./workflows'),
  activities,
  // highlight-start
  plugins: [
    new ParseablePlugin({
      serviceName: 'temporal-worker',
      endpoint: process.env.PARSEABLE_URL, // e.g. https://parseable.example:8000
      auth: {
        username: process.env.PARSEABLE_USERNAME,
        password: process.env.PARSEABLE_PASSWORD,
      },
      // optional, defaults shown:
      logs: { stream: 'temporal-logs' },
      traces: { stream: 'temporal-traces' },
    }),
  ],
  // highlight-end
});

await worker.run();

ParseablePlugin sends workflow logs and traces to Parseable. The Runtime.install() block enables Temporal SDK metrics on the worker process and exposes them in Prometheus format at :9464/metrics. Scrape that endpoint with Prometheus and forward it to Parseable using Prometheus Remote Write.

Options

OptionTypeDefaultNotes
serviceNamestringrequiredBecomes the service.name resource attribute and service_name log field.
endpointstringrequired if logs/traces enabledParseable host base URL.
auth{ username, password }required if logs/traces enabledHTTP basic auth.
logsfalse | { stream?: string }{ stream: 'temporal-logs' }Set to false to disable log emission.
tracesfalse | { stream?: string }{ stream: 'temporal-traces' }Set to false to disable trace emission.

Metrics

Temporal TypeScript workers can expose SDK metrics from the worker runtime. These metrics are separate from the Parseable plugin logs and traces. They help you see worker level behavior such as activity execution, workflow task execution, polling, latency, and other SDK runtime signals.

The bindAddress in the example above exposes a Prometheus scrape endpoint on the worker host:

http://<worker-host>:9464/metrics

Prometheus can scrape this endpoint and remote write the samples to Parseable:

scrape_configs:
  - job_name: temporal-typescript-worker
    static_configs:
      - targets: ['temporal-worker:9464']

remote_write:
  - url: "https://<parseable-host>:8000/v1/prometheus/write"
    authorization:
      type: Bearer
      credentials: <parseable-api-key>
    headers:
      X-P-Stream: temporal-metrics

After Prometheus starts writing to Parseable, open the temporal-metrics dataset in the Metrics page. Temporal keeps the full SDK metrics reference in its SDK metrics documentation, which is useful when deciding which worker and workflow metrics to dashboard.

Custom domain events from workflow code

Workflows can emit replay-safe domain events via the workflowEvent helper. Each call lands as a log record with type: 'user_event', event_name, and an arbitrary serializable event_data payload.

import { workflowEvent } from '@parseable/temporal/workflow';
import { proxyActivities } from '@temporalio/workflow';

const { planActivity, runStep } = proxyActivities<typeof activities>({
  startToCloseTimeout: '1 minute',
});

export async function agentWorkflow(input: AgentInput): Promise<AgentResult> {
  workflowEvent('agent.started', { user_id: input.userId });

  const plan = await planActivity(input);
  workflowEvent('agent.plan.chosen', { steps: plan.steps.length });

  for (const step of plan.steps) {
    workflowEvent('agent.step.start', { tool: step.tool });
    await runStep(step);
  }

  workflowEvent('agent.completed', { total_steps: plan.steps.length });
  return { ok: true };
}

Events flow through the same sink as the built-in workflow lifecycle events, so they are deduplicated on replay.

Was this page helpful?

On this page