> ## Documentation Index
> Fetch the complete documentation index at: https://docs.logbrew.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js ve Express'te Winston ve Pino ile loglama

> Node.js ve Express'te Winston logger veya Pino logger kurun, log seviyelerini seçin, iz kimlikli yapılandırılmış logları LogBrew'e gönderin.

LogBrew, geliştiriciler ve kodlama asistanları için bir gözlemlenebilirlik
platformudur. Cömert bir ücretsiz planı vardır ve kart gerektirmez.

Bu rehber Node.js'te Winston ve Pino ile loglamayı kurar, bir Express logger
ekler ve her logu istek iziyle birlikte LogBrew'e gönderir. Her örnek Node.js
22, Winston 3.19, Pino 10.4, Express 5.3, `@logbrew/sdk` 0.1.40, `@logbrew/node`
0.1.24 ve `@logbrew/express` 0.1.10 ile çalıştırıldı. Her çıktı bloğu gerçek
çıktıyı gösterir.

## Winston veya Pino seçin

İki kütüphane de yapılandırılmış JSON logları yazar. Uygulamanızın zaten
kullandığı kütüphaneyle devam edin. LogBrew kurulumu her kütüphane için
farklıdır.

| | Winston | Pino |
| - | - | - |
| Varsayılan çıktı | Formatı siz seçersiniz, örneğin `winston.format.json()`. | Her kayıt için 1 JSON satırı. |
| Mesaj argümanı | `logger.info("message", { fields })` | `logger.info({ fields }, "message")` |
| Hedefler | Uygulama sürecindeki transport'lar. | Ayrı bir worker thread'deki transport'lar. |
| Alt logger'lar | `logger.child({ fields })` | `logger.child({ fields })` |
| Gizleme | Kendi formatınız. | Yerleşik `redact` seçeneği. |
| LogBrew kurulumu | `createLogBrewWinstonTransport()` fonksiyonunu `transports` listesine ekleyin. | `installLogBrewPinoInstrumentation()` fonksiyonunu bir kez çağırın. |

## Bir LogBrew projesi hazırlayın

**1. Bir proje anahtarı oluşturun**

[CLI](https://docs.logbrew.co/tr/guides/cli.md) ile giriş yapın. Bir proje oluşturun. Projenin alım
anahtarını (ingest key) yalnızca sahibinin okuyabildiği bir dosyada
saklayın.

```bash theme={null}
install -d -m 700 "$HOME/.logbrew"
logbrew projects create checkout-api \
  --runtime node \
  --environment development \
  --ingest-key-file "$HOME/.logbrew/checkout-api.ingest" \
  --json
```

CLI anahtarı ekrana yazdırmaz. Canlı ortamda platformunuzun gizli anahtar
yöneticisini kullanın.

**2. Paketleri kurun**

Paketler Node.js 18.19 veya üstünü gerektirir. Winston'ı, Pino'yu veya
ikisini birden kurun.

```bash theme={null}
npm install @logbrew/sdk @logbrew/node @logbrew/express express winston pino
```

**3. Anahtarı ve dağıtım bilgilerini ayarlayın**

```bash theme={null}
export LOGBREW_SERVER_API_KEY="$(tr -d '\r\n' < "$HOME/.logbrew/checkout-api.ingest")"
export LOGBREW_ENVIRONMENT="development"
export LOGBREW_RELEASE="checkout-api@1.0.0"
```

`createLogBrewNodeClient()` anahtarı `LOGBREW_SERVER_API_KEY` değişkeninden
okur. Hizmet adı `package.json` içindeki `name` değeridir. Farklı bir ad
kullanmak için `LOGBREW_SERVICE_NAME` değişkenini ayarlayın. Örnekler ES
modüllerini kullanır, bu yüzden `package.json` içinde `"type": "module"`
ayarlayın.

## Node.js log seviyeleri

Her kütüphanenin kendi seviye adları ve sayıları vardır. LogBrew 4 seviye saklar
ve asıl seviyeyi meta veride tutar.

| LogBrew seviyesi | Winston seviyesi (öncelik) | Pino seviyesi (sayı) |
| - | - | - |
| `info` | `info` (2), `http` (3), `verbose` (4), `debug` (5), `silly` (6) | `info` (30), `debug` (20), `trace` (10) |
| `warning` | `warn` (1) | `warn` (40) |
| `error` | `error` (0) | `error` (50) |
| `critical` | Tanımlarsanız `fatal` veya `critical` | `fatal` (60) |

Winston'da düşük sayı daha ciddi bir seviyeyi gösterir. Pino'da yüksek sayı daha
ciddi bir seviyeyi gösterir. Canlı ortamda `info` ayarlayın. `debug` seviyesini
yalnızca kısa bir tanı için ayarlayın.

## Winston logger

Bu dosyayı `winston-app.js` olarak kaydedin. İlk format, logger seviyesinin
altındaki kayıtları hiçbir transport almadan önce atar. LogBrew transport'u
logger'ın yazdığı her kaydı alır, bu yüzden bu filtreye ihtiyaç duyar.

```js theme={null}
import winston from "winston";
import { createLogBrewWinstonTransport } from "@logbrew/sdk";
import { createLogBrewNodeClient } from "@logbrew/node";

const client = createLogBrewNodeClient();

const logger = winston.createLogger({
  level: "info",
  format: winston.format.combine(
    winston.format((info) => (logger.isLevelEnabled(info.level) ? info : false))(),
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: { component: "checkout" },
  transports: [
    new winston.transports.Console(),
    createLogBrewWinstonTransport({ client })
  ]
});

logger.debug("cart loaded");
logger.info("order created", { orderId: "ord_1001", totalCents: 4200 });
logger.warn("payment retry", { attempt: 2 });
logger.error(new Error("card declined"));

await client.shutdown();
```

`node winston-app.js` komutunu çalıştırın. Konsol `info` veya üstündeki her
kayıt için 1 JSON satırı alır. Yığın izi burada kısaltıldı.

```text theme={null}
{"component":"checkout","level":"info","message":"order created","orderId":"ord_1001","timestamp":"2026-11-07T14:19:53.863Z","totalCents":4200}
{"attempt":2,"component":"checkout","level":"warn","message":"payment retry","timestamp":"2026-11-07T14:19:53.864Z"}
{"component":"checkout","level":"error","message":"card declined","stack":"Error: card declined\n    at file:///srv/app/winston-app.js:25:14\n ...","timestamp":"2026-11-07T14:19:53.864Z"}
```

LogBrew aynı 3 kaydı alır. Alanlar `context.*` meta verisi olur.

| `message` | `level` | `metadata` |
| - | - | - |
| `order created` | `info` | `winstonLevel` `info`, `context.component` `checkout`, `context.orderId` `ord_1001`, `context.totalCents` 4200 |
| `payment retry` | `warning` | `winstonLevel` `warn`, `context.component` `checkout`, `context.attempt` 2 |
| `card declined` | `error` | `winstonLevel` `error`, `context.component` `checkout`, `errorName` `Error`, `errorMessage` `card declined` |

Transport hatanın adını ve mesajını gönderir, yığın izini göndermez. Yığın izini
göndermek için `createLogBrewWinstonTransport()` içinde
`includeErrorStack: true` ayarlayın. Her mesaj bir sonraki sorunda önceki adım
(breadcrumbs) olur. Bunu durdurmak için `breadcrumbs: false` ayarlayın.

## Pino logger

Bu dosyayı `pino-app.js` olarak kaydedin. `installLogBrewPinoInstrumentation()`
fonksiyonunu ilk logdan önce bir kez çağırın. Fonksiyon tamamlanan her Pino
kaydını okur. Pino yine kendi hedefine yazar.

```js theme={null}
import pino from "pino";
import {
  createLogBrewNodeClient,
  installLogBrewPinoInstrumentation
} from "@logbrew/node";

const client = createLogBrewNodeClient();
installLogBrewPinoInstrumentation({ client });

const logger = pino({
  level: "info",
  redact: ["password", "token", "req.headers.authorization"]
});
const orderLogger = logger.child({ component: "checkout" });

orderLogger.debug("cart loaded");
orderLogger.info({ orderId: "ord_1001", totalCents: 4200 }, "order created");
orderLogger.warn({ attempt: 2, token: "tok_example" }, "payment retry");
orderLogger.error(new Error("card declined"), "payment failed");

await client.shutdown();
```

`node pino-app.js` komutunu çalıştırın. Ana makine adı ve yığın izi burada
kısaltıldı.

```text theme={null}
{"level":30,"time":1794061059490,"pid":13985,"hostname":"app-host","component":"checkout","orderId":"ord_1001","totalCents":4200,"msg":"order created"}
{"level":40,"time":1794061059493,"pid":13985,"hostname":"app-host","component":"checkout","attempt":2,"token":"[Redacted]","msg":"payment retry"}
{"level":50,"time":1794061059494,"pid":13985,"hostname":"app-host","component":"checkout","err":{"type":"Error","message":"card declined","stack":"Error: card declined\n ..."},"msg":"payment failed"}
```

LogBrew 3 kayıt alır. Pino `debug` kaydını LogBrew görmeden önce atar.

| `message` | `level` | `metadata` |
| - | - | - |
| `order created` | `info` | `pinoLevel` `info`, `pinoLevelNumber` 30, `context.component` `checkout`, `context.orderId` `ord_1001`, `context.totalCents` 4200 |
| `payment retry` | `warning` | `pinoLevel` `warn`, `pinoLevelNumber` 40, `context.component` `checkout`, `context.attempt` 2 |
| `payment failed` | `error` | `pinoLevel` `error`, `pinoLevelNumber` 50, `context.component` `checkout`, `errorName` `Error`, `errorMessage` `card declined` |

`token` alanı LogBrew'de yer almaz. LogBrew kimlik bilgisi, çerez, gövde, sorgu,
URL ve yığın izi alanlarını atar. Pino `redact` yollarınızı ikinci bir denetim
olarak korur. `pid`, `hostname` ve `time` Pino varsayılanlarıdır, bu yüzden
LogBrew onları kopyalamaz.

Otomatik yakalama 9.x serisinde Pino 9.11 veya üstünü ya da Pino 10.1 veya
üstünü gerektirir. Eski Pino sürümleri için `@logbrew/sdk` paketindeki
`createLogBrewPinoDestination()` fonksiyonunu Pino hedefi olarak kullanın.

Geliştirmede Pino çıktısını okumak için çıktıyı `pino-pretty` aracına gönderin.

```bash theme={null}
node pino-app.js | npx pino-pretty
```

## Express logger

`logbrewMiddleware()` her istek için 1 istek span'i oluşturur.
`logbrewErrorHandler()` hataları sorun olarak bildirir. Bir istek içindeki Pino
logu o isteğin iz kimliğini ve span kimliğini alır. Bu dosyayı `express-app.js`
olarak kaydedin.

```js theme={null}
import express from "express";
import pino from "pino";
import { logbrewErrorHandler, logbrewMiddleware } from "@logbrew/express";
import {
  createLogBrewNodeClient,
  installLogBrewPinoInstrumentation
} from "@logbrew/node";

const client = createLogBrewNodeClient();
installLogBrewPinoInstrumentation({ client });
const logger = pino({ level: "info" });

const app = express();
app.use(logbrewMiddleware());

app.get("/orders/:orderId", (req, res) => {
  logger.info({ orderId: req.params.orderId }, "order loaded");
  res.json({ ok: true });
});

app.get("/fail", () => {
  throw new Error("inventory service timeout");
});

app.use(logbrewErrorHandler());
app.use((err, req, res, next) => {
  logger.error(err, "request failed");
  res.status(500).json({ error: "internal" });
});

const server = app.listen(3000, () => logger.info("listening on 3000"));

process.on("SIGTERM", () => {
  server.close(async () => {
    await client.shutdown();
    process.exit(0);
  });
});
```

Uygulamayı başlatın. Ardından ikinci bir terminalden 2 istek gönderin.

```bash theme={null}
curl -s http://127.0.0.1:3000/orders/ord_1001
curl -s http://127.0.0.1:3000/fail
```

LogBrew bu olayları alır. Her isteğin logu ve span'i aynı iz kimliğine sahiptir.

| Olay | Ad veya mesaj | İz |
| - | - | - |
| span | `GET /orders/:orderId`, durum `ok` | `4f18970f494d633c2164588fee9c692a` |
| log | `order loaded` | `4f18970f494d633c2164588fee9c692a` |
| sorun | `GET /fail failed`, mesaj `inventory service timeout` | `d273e106d73ce6c5a5955e5a8c74d2d0` |
| span | `GET /fail`, durum `error` | `d273e106d73ce6c5a5955e5a8c74d2d0` |
| log | `request failed` | `d273e106d73ce6c5a5955e5a8c74d2d0` |

Span adı somut yolu değil, route şablonunu kullanır. `listening on 3000` logunun
izi yoktur, çünkü bu log bir isteğin dışında yazılır.

Middleware kendi istek istemcilerini oluştursun. Süreç genelindeki `client`
nesnesini `logbrewMiddleware()` veya `logbrewErrorHandler()` fonksiyonuna
vermeyin. Middleware her yanıttan sonra kendi istek istemcisini kapatır.

### Winston loglarına izi ekleyin

Winston için transport'a etkin izi verin.

```js theme={null}
import { createLogBrewWinstonTransport } from "@logbrew/sdk";
import { createLogBrewNodeClient, getActiveLogBrewTrace } from "@logbrew/node";

const client = createLogBrewNodeClient();
const logbrewTransport = createLogBrewWinstonTransport({
  client,
  traceProvider: getActiveLogBrewTrace
});
```

`logbrewTransport` nesnesini logger'ın `transports` listesine ekleyin. Böylece
bir Express isteği içindeki Winston logu isteğin iz kimliğini ve span kimliğini
taşır.

## Logları geri okuyun

```bash theme={null}
logbrew read logs --service checkout-api --since 1h --json
logbrew read logs --severity error --search "request failed" --since 1h --json
logbrew read logs --trace "<trace_id>" --since 1h --json
```

Son komut 1 isteğin tüm loglarını okur. `<trace_id>` değerini bir izden veya bir
sorundan kopyalayın. CI'dan veya bir kodlama asistanından okumak için proje
okuma anahtarı (read key) kullanın. [Kurulumunuzu
doğrulayın](https://docs.logbrew.co/tr/guides/verify-setup.md) sayfasına bakın.

## Log kaybetmeden kapatın

İstemci kuyruktaki olayları ilk olaydan 1 saniye sonra veya 50 olayda gönderir.
Olay döngüsü boşaldığında istemci kalan olayları en fazla 2 saniye boyunca
gönderir. `process.exit()` ve sinyaller bu adımı atlar. Çıkmadan önce
`await client.shutdown()` çağırın. Express örneğindeki `SIGTERM` handler'ı bunu
yapar.

## Sorunları giderin

| Belirti | Neden | Çözüm |
| - | - | - |
| `createLogBrewNodeClient requires serverApiKey, apiKey, LOGBREW_SERVER_API_KEY, or LOGBREW_API_KEY` | Anahtar bu kabukta ayarlı değil. | `export` adımını yeniden çalıştırın. |
| `debug` seviyesindeki Winston logları LogBrew'de görünüyor ama konsolda görünmüyor | LogBrew transport'u logger seviyesini uygulamıyor. | Winston örneğindeki seviye filtresi formatını ekleyin. |
| Pino logları LogBrew'de görünmüyor | Pino sürümünde tracing channel yok veya loglar `installLogBrewPinoInstrumentation()` çağrısından önce yazıldı. | Pino 9.11 veya üstünü ya da 10.1 veya üstünü kullanın. Yakalamayı ilk logdan önce kurun. |
| Loglar ilk istekten sonra duruyor ve `client.shutdown()`, `client is already shut down` hatası fırlatıyor | Süreç genelindeki istemci Express middleware'ine verildi. | `client` seçeneğini `logbrewMiddleware()` ve `logbrewErrorHandler()` çağrılarından kaldırın. |
| Dağıtımdan sonra son loglar eksik | Süreç teslimden önce çıktı. | `SIGTERM` handler'ında `await client.shutdown()` çağırın. |

Log alanlarını seçmek için [Yapılandırılmış
loglama](https://docs.logbrew.co/tr/concepts/structured-logging.md) sayfasına bakın. Diğer framework'ler
için [SDK entegrasyonu](https://docs.logbrew.co/tr/guides/sdk-ingestion.md) rehberine bakın.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.