---
title: "Cara Baca dan Filter Logs Real-time di Helipod"
url: "https://helipod.io/blog/logs-realtime-di-helipod"
date: "2026-05-11"
updated: "2026-05-11"
author: "Tim Helipod"
tags: ["logs", "debugging", "monitoring", "helipod", "observability", "production"]
excerpt: "Cara baca dan filter logs real-time di Helipod: filter per pod, search keyword, baca access log, dan debugging aplikasi production dari browser."
---

# Cara Baca dan Filter Logs Real-time di Helipod

Ketika ada masalah di production, hal pertama yang kamu buka adalah logs. Logs adalah rekaman jejak setiap yang terjadi di aplikasimu, request yang masuk, error yang terjadi, query yang dijalankan, sampai output dari kode kamu sendiri.

Helipod menyediakan log viewer real-time langsung dari dashboard browser, tidak perlu SSH ke server, tidak perlu install tool tambahan, tidak perlu setup log aggregation sendiri.

## Dua Jenis Logs di Helipod

### 1. Build Logs

Tersedia di **tab Deployments** → klik deployment → **Build logs**.

Build logs menampilkan output dari proses build Docker image:
- Clone repository
- Install dependencies (`npm ci`, `pip install`, `composer install`)
- Build step (`next build`, `nest build`, `collectstatic`)
- Push image ke registry

**Kapan dibuka:** Saat deployment gagal dan kamu perlu tahu di step mana error-nya terjadi.

### 2. App Logs

Tersedia di **tab Deployments** → klik deployment → **App logs**, atau di halaman **Logs** global (sidebar kiri).

App logs menampilkan stdout dan stderr dari container yang sedang berjalan, semua yang di-print oleh aplikasimu, termasuk:
- Access log (request HTTP yang masuk)
- Error dan exception
- `console.log()` di Node.js
- `print()` di Python
- `Log::info()` di Laravel
- Output dari cron job atau background worker

**Kapan dibuka:** Debugging masalah runtime, error yang terjadi saat aplikasi berjalan normal.

## Halaman Logs Global

Klik ikon **Logs** di sidebar kiri dashboard (ikon list/terminal) untuk membuka halaman Logs yang menampilkan log dari semua pod dalam project sekaligus.

### Anatomi Halaman Logs

**Timeline bar** di bagian atas menampilkan distribusi log entries per waktu, berguna untuk melihat kapan ada spike error (blok merah) vs log normal (blok hijau/biru).

**Filter pod**: dropdown "All pods (N)" untuk melihat semua log, atau pilih pod spesifik. Sangat berguna di project multi-service untuk isolasi log per service.

**Search bar**: ketik keyword untuk filter log secara real-time. Shortcut keyboard: tekan `/` untuk langsung focus ke search bar.

**Time range selector**: pilih rentang waktu log yang ingin ditampilkan (default: 1 hour).

**Download**: export log sebagai file untuk analisis offline.

### Kolom Tabel Logs

| Kolom | Keterangan |
|-------|-----------|
| **Time (WIB)** | Timestamp dalam Waktu Indonesia Barat |
| **Pod** | Nama service yang generate log |
| **Deploy** | Commit hash deployment yang sedang berjalan |
| **Replica** | ID replica spesifik (jika ada multiple replicas) |
| **Data** | Isi log entry |

### Warna Log

- **Putih/abu-abu**: log normal (INFO, access log, output biasa)
- **Merah**: error log: langsung mencolok tanpa perlu scroll

## Cara Baca Access Log

Access log adalah log HTTP request yang masuk ke aplikasimu. Format standar nginx:

```
10.42.4.44 - [27/Apr/2026:08:11:44 +0000] "GET / HTTP/1.1" 200 60638 "-" "Uptime-Kuma/1.23.17" "10.42.5.0"
```

Breakdown setiap field:

| Field | Nilai | Artinya |
|-------|-------|---------|
| IP Client | `10.42.4.44` | IP pengirim request (internal jika via load balancer) |
| Timestamp | `27/Apr/2026:08:11:44` | Waktu request diterima |
| Method & Path | `GET / HTTP/1.1` | HTTP method, path, protokol |
| Status Code | `200` | HTTP response code |
| Response Size | `60638` | Ukuran response dalam bytes |
| Referer | `-` | Halaman asal request |
| User-Agent | `Uptime-Kuma/1.23.17` | Browser/tool yang membuat request |

### HTTP Status Code yang Perlu Diperhatikan

| Code | Arti | Tindakan |
|------|------|---------|
| `200` | OK | Normal |
| `301/302` | Redirect | Normal, cek jika redirect loop |
| `400` | Bad Request | Error di request client |
| `401` | Unauthorized | Auth gagal |
| `403` | Forbidden | Permission denied |
| `404` | Not Found | File/route tidak ada |
| `500` | Internal Server Error | Error di aplikasi, investigasi! |
| `502` | Bad Gateway | Container tidak respond, restart? |
| `503` | Service Unavailable | Container down atau overload |
| `504` | Gateway Timeout | Request terlalu lama diproses |

## Pattern Log yang Normal vs Perlu Perhatian

### Normal, Tidak Perlu Khawatir

**404 dari scanner/bot:**
```
"GET /robots.txt HTTP/1.1" 404
"GET /wp-admin/admin-ajax.php HTTP/1.1" 404
"GET /.env HTTP/1.1" 404
"GET /phpMyAdmin/ HTTP/1.1" 404
```
Scanner internet secara otomatis mencoba URL umum untuk mencari vulnerability. 404 untuk path ini adalah normal, artinya kamu tidak punya file yang mereka cari.

**Health check:**
```
"GET / HTTP/1.1" 200 60638 "-" "Uptime-Kuma/1.23.17"
"GET /health HTTP/1.1" 200 - "-" "kube-probe/1.27"
```
Log health check dari monitoring tool atau Kubernetes, sepenuhnya normal.

**Static assets:**
```
"GET /assets/app.js HTTP/1.1" 200 45231
"GET /favicon.ico HTTP/1.1" 200 1150
```
Normal, bisa diabaikan.

### Perlu Perhatian, Investigasi

**500 Internal Server Error:**
```
[error] "POST /api/checkout HTTP/1.1" 500
```
Ada exception di kode, buka App logs untuk detail traceback.

**502 Bad Gateway, berulang:**
```
"GET / HTTP/1.1" 502
"GET / HTTP/1.1" 502
"GET / HTTP/1.1" 502
```
Container tidak bisa diakses, cek tab Metrics untuk Restarts, buka App logs untuk error.

**504 Gateway Timeout:**
```
"POST /api/process HTTP/1.1" 504
```
Request terlalu lama. Kemungkinan: query database lambat, external API timeout, atau infinite loop.

**Spike 4xx/5xx tiba-tiba:**
Jika sebelumnya semua 200 lalu tiba-tiba banyak 5xx setelah deploy baru, kemungkinan bug di deployment terbaru. Cek App logs dan pertimbangkan rollback.

## Cara Filter dan Search Logs

### Filter per Pod

Untuk project dengan beberapa service (Laravel, PostgreSQL, Redis, Worker), filter logs per pod untuk fokus ke service yang bermasalah:

1. Klik dropdown "All pods (N)"
2. Pilih pod yang ingin dilihat
3. Log langsung ter-filter

### Search Keyword

Ketik di search bar untuk filter log yang mengandung keyword:

```
# Cari semua error
error

# Cari request ke endpoint tertentu
/api/users

# Cari user ID tertentu
user_id=12345

# Cari HTTP status tertentu
" 500 "

# Cari exception tertentu
TypeError

# Cari IP tertentu
10.42.4.44
```

### Filter by Time Range

Klik time range selector (default "1 hour") untuk melihat log dari periode tertentu:
- **1 hour**: debugging masalah baru
- **6 hours**: investigasi masalah yang terjadi beberapa jam lalu
- **1 day**: analisis pattern harian

Log history tersedia sesuai plan:
- Free: log terbatas
- Mekanik: **7 hari** log history
- Pilot: **30 hari** log history
- Enterprise: **90 hari** log history

## App Logs per Framework

### Laravel

```bash
# Log di aplikasi
Log::info('User logged in', ['user_id' => $user->id]);
Log::error('Payment failed', ['order_id' => $order->id, 'error' => $e->getMessage()]);
Log::warning('Rate limit exceeded', ['ip' => $request->ip()]);
```

Laravel secara default menulis ke `storage/logs/laravel.log`. Di Helipod (container), log diarahkan ke stdout agar muncul di log viewer. Tambahkan di `config/logging.php`:

```php
'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['single', 'stderr'], // tambah stderr
        'ignore_exceptions' => false,
    ],
    'stderr' => [
        'driver' => 'monolog',
        'level' => env('LOG_LEVEL', 'debug'),
        'handler' => StreamHandler::class,
        'formatter' => env('LOG_STDERR_FORMATTER'),
        'with' => [
            'stream' => 'php://stderr',
        ],
    ],
],
```

Atau lebih simpel, set di `.env`:
```env
LOG_CHANNEL=stderr
LOG_LEVEL=warning  # hanya warning ke atas yang di-log di production
```

### Django

```python
import logging

logger = logging.getLogger(__name__)

# Di views.py
def checkout(request):
    try:
        # proses checkout
        logger.info(f"Checkout success for user {request.user.id}")
    except Exception as e:
        logger.error(f"Checkout failed: {e}", exc_info=True)
        return JsonResponse({'error': str(e)}, status=500)
```

Konfigurasi logging Django untuk stdout:

```python
# settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
    },
    'root': {
        'handlers': ['console'],
        'level': 'WARNING',  # production: WARNING ke atas
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'WARNING'),
            'propagate': False,
        },
        'myapp': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': False,
        },
    },
}
```

### FastAPI / Flask

```python
import logging
import sys

# Setup logging ke stdout
logging.basicConfig(
    stream=sys.stdout,
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

logger = logging.getLogger(__name__)

# Di route handler
@app.post("/api/checkout")
async def checkout(data: CheckoutSchema):
    logger.info(f"Checkout initiated for user {data.user_id}")
    try:
        result = await process_checkout(data)
        logger.info(f"Checkout success: {result.order_id}")
        return result
    except Exception as e:
        logger.error(f"Checkout failed: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))
```

### NestJS

```typescript
import { Logger } from '@nestjs/common';

@Injectable()
export class CheckoutService {
  private readonly logger = new Logger(CheckoutService.name);
  
  async processCheckout(dto: CheckoutDto) {
    this.logger.log(`Processing checkout for user ${dto.userId}`);
    
    try {
      const result = await this.paymentService.charge(dto);
      this.logger.log(`Checkout success: order ${result.orderId}`);
      return result;
    } catch (error) {
      this.logger.error(`Checkout failed: ${error.message}`, error.stack);
      throw new InternalServerErrorException('Checkout failed');
    }
  }
}
```

NestJS secara default sudah output ke stdout, langsung muncul di log viewer Helipod.

### Next.js

```typescript
// Di server-side code (API routes, Server Components)
console.log('User authenticated:', userId);
console.error('Database query failed:', error);

// Atau gunakan library logging seperti pino
import pino from 'pino';
const logger = pino({ level: process.env.LOG_LEVEL || 'info' });
logger.info({ userId }, 'User authenticated');
logger.error({ error }, 'Database query failed');
```

> **Client-side logs** (browser console) tidak muncul di Helipod logs, hanya server-side output yang ter-capture.

## Structured Logging untuk Log yang Lebih Berguna

Log dalam format JSON (structured logging) jauh lebih mudah di-search dan di-parse:

**Node.js dengan pino:**
```typescript
// src/logger.ts
import pino from 'pino';

export const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  formatters: {
    level: (label) => ({ level: label }),
  },
  timestamp: pino.stdTimeFunctions.isoTime,
});
```

Output di logs Helipod:
```json
{"level":"info","time":"2026-05-11T10:23:45.123Z","userId":123,"msg":"User logged in"}
{"level":"error","time":"2026-05-11T10:24:01.456Z","orderId":"ORD-456","error":"Payment gateway timeout","msg":"Checkout failed"}
```

**Python dengan structlog:**
```python
import structlog

logger = structlog.get_logger()

logger.info("checkout_initiated", user_id=123, amount=150000)
logger.error("checkout_failed", user_id=123, error=str(e), order_id="ORD-456")
```

Output:
```json
{"event": "checkout_initiated", "user_id": 123, "amount": 150000, "level": "info", "timestamp": "2026-05-11T10:23:45.123Z"}
```

Dengan structured logging, search di Helipod logs menjadi sangat powerful:
- Search `user_id=123` → semua aktivitas user 123
- Search `"level":"error"` → semua error
- Search `checkout_failed` → semua kegagalan checkout

## Strategi Debugging dengan Logs

### Alur Debugging Umum

```
1. Buka halaman Logs global
2. Filter time range ke saat masalah terjadi
3. Search "error" atau " 5" (untuk 5xx)
4. Identifikasi pattern: error di service mana? Berapa sering?
5. Filter ke pod yang bermasalah
6. Baca konteks di sekitar error (log sebelum dan sesudahnya)
7. Jika butuh lebih detail → buka Terminal → debug langsung
```

### Investigasi Insiden

Saat ada laporan dari user bahwa fitur X tidak bisa dipakai:

```
1. Tanya user: kapan persis error terjadi?
2. Buka Logs → set time range ke waktu tersebut
3. Search endpoint yang berkaitan: "/api/checkout"
4. Cari baris yang berwarna merah (error)
5. Baca error message dan traceback
6. Identifikasi root cause (database? external API? bug kode?)
7. Fix dan deploy
8. Verifikasi di Logs bahwa error tidak muncul lagi
```

### Monitoring Setelah Deploy

Setiap kali deploy baru, buka Logs dengan time range "15 min" dan pantau:
- Apakah ada error baru yang tidak ada sebelumnya?
- Apakah response time (dari log) masih normal?
- Apakah ada 5xx yang meningkat?

## Tips Penggunaan Logs yang Efektif

**1. Log di level yang tepat:**
- `DEBUG`: detail untuk development, disable di production
- `INFO`: event penting (user login, order created)
- `WARNING`: sesuatu yang tidak biasa tapi tidak crash
- `ERROR`: error yang perlu investigasi
- `CRITICAL`: aplikasi tidak bisa berjalan

**2. Include context di setiap log:**
```python
# Kurang berguna:
logger.error("Payment failed")

# Jauh lebih berguna:
logger.error("Payment failed", extra={
    'user_id': user.id,
    'order_id': order.id,
    'amount': order.total,
    'gateway': 'midtrans',
    'error_code': e.code,
})
```

**3. Jangan log data sensitif:**
```python
# JANGAN INI
logger.info(f"User login: email={email}, password={password}")

# Lakukan ini
logger.info(f"User login: email={email}")
```

**4. Log request ID untuk tracing:**
Tambahkan unique request ID di setiap log entry agar mudah trace satu request dari awal sampai akhir.

**5. Set LOG_LEVEL via environment variable:**
```env
LOG_LEVEL=warning  # production: warning ke atas saja
```
Jangan log `DEBUG` di production, terlalu banyak noise dan bisa mengekspos informasi sensitif.

## Kesimpulan

Log viewer di Helipod menghilangkan kebutuhan setup ELK stack, Datadog, atau tool log aggregation mahal untuk mendapatkan visibility ke aplikasi production. Filter per pod, search keyword, warna error yang mencolok, semua tersedia dari browser.

Yang terpenting: pastikan aplikasimu output log ke stdout (bukan hanya ke file), dan gunakan level logging yang tepat agar signal tidak tenggelam dalam noise.

Ingin tahu cara debug langsung ke dalam container? Baca [Terminal Live di Helipod](/blog/terminal-live-di-helipod).

Ingin monitoring CPU dan memory? Baca [Monitor Metrics di Helipod](/blog/monitoring-metrics-helipod).

Punya pertanyaan? Hubungi kami di [support@helipod.io](mailto:support@helipod.io) atau bergabung ke komunitas di [hangar.helipod.io](https://hangar.helipod.io).
