Traconix
Documentação Traconix Cloud

Exemplos de integração

Substitua BASE_URL e TRACO_TOKEN pelos valores do seu ambiente Traconix Cloud.

cURL (teste rápido)

curl -sS -X POST "https://app.traconix.com/api/v1/logs" \
  -H "Authorization: Bearer traco_SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "level": "info",
    "service": "api",
    "message": "Hello from curl",
    "environment": "production"
  }'

Node.js (fetch nativo)

const BASE_URL = process.env.TRACONIX_URL; // ex: https://app.traconix.com
const TOKEN = process.env.TRACONIX_TOKEN;  // traco_...

export async function sendLog(payload) {
  const res = await fetch(`${BASE_URL}/api/v1/logs`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
  });

  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    throw new Error(`Traconix ingest failed: ${res.status} ${JSON.stringify(err)}`);
  }

  return res.json(); // { ingested: 1 }
}

await sendLog({
  level: "info",
  service: "billing-api",
  message: "Invoice paid",
  environment: process.env.NODE_ENV === "production" ? "production" : "development",
  metadata: { invoiceId: "inv_99", amountCents: 9900 },
});

Node.js — fila assíncrona (recomendado)

const queue = [];
let flushing = false;

export function logToTraconix(entry) {
  queue.push(entry);
  if (!flushing) void flush();
}

async function flush() {
  flushing = true;
  while (queue.length) {
    const batch = queue.splice(0, 50);
    try {
      await fetch(`${process.env.TRACONIX_URL}/api/v1/logs`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.TRACONIX_TOKEN}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(batch),
      });
    } catch (e) {
      console.error("[traconix] ingest failed", e);
    }
  }
  flushing = false;
}

Pino (logger Node)

O Traconix aceita o mesmo formato de campos que você usaria com Pino (level, msg → use message, service, etc.). Use um transport customizado ou chame sendLog no hook hooks.logMethod.

import pino from "pino";

const base = { service: "api", environment: "production" };

const logger = pino({
  level: "info",
  base,
  hooks: {
    logMethod(inputArgs, method, level) {
      const [obj, msg] =
        typeof inputArgs[0] === "object"
          ? [inputArgs[0], inputArgs[1] ?? ""]
          : [{}, String(inputArgs[0])];

      void sendLog({
        level: level === 50 ? "error" : level >= 40 ? "warn" : level >= 30 ? "info" : "debug",
        service: base.service,
        message: String(msg),
        environment: base.environment,
        metadata: obj,
      }).catch(() => {});

      method.apply(this, inputArgs);
    },
  },
});

logger.info({ userId: "usr_1", orderId: "ord_9" }, "order created");

Python (requests)

import os
import requests

BASE = os.environ["TRACONIX_URL"]
TOKEN = os.environ["TRACONIX_TOKEN"]

def send_log(level, service, message, **metadata):
    r = requests.post(
        f"{BASE}/api/v1/logs",
        headers={
            "Authorization": f"Bearer {TOKEN}",
            "Content-Type": "application/json",
        },
        json={
            "level": level,
            "service": service,
            "message": message,
            "environment": os.getenv("APP_ENV", "production"),
            "metadata": metadata,
        },
        timeout=5,
    )
    r.raise_for_status()
    return r.json()

send_log("info", "api", "User signed in", userId="usr_42")

Go (net/http)

payload := `{"level":"info","service":"api","message":"started","environment":"production"}`
req, _ := http.NewRequest("POST", baseURL+"/api/v1/logs", strings.NewReader(payload))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)

Variáveis de ambiente sugeridas

Nunca commite TRACONIX_TOKEN no Git.

# Na sua aplicação (servidor, Docker, K8s secret)
TRACONIX_URL=https://app.traconix.com
TRACONIX_TOKEN=traco_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx