Implementasi sistem logging komprehensif untuk AI Agent PHP: mencatat request, response, tool calls, error, dan mode debug untuk memudahkan pemeliharaan aplikasi.
Daftar Isi
- Definisi: Apa itu Sistem Logging pada AI Agent PHP?
- TL;DR (Ringkasan Cepat)
- Standar PSR-3, Monolog vs File Logging & Praktik Sanitasi API Key:
- Membuat Custom Logger Class untuk AI Agent PHP
- Mengintegrasikan Logger ke AI Agent PHP
- FAQ: Pertanyaan Seputar Sistem Logging AI Agent PHP
- 1. Mengapa sistem logging AI Agent harus menggunakan format JSON Lines (JSONL)?
- 2. Kapan sebaiknya menggunakan Monolog dibandingkan Custom Logger Class?
- 3. Bagaimana cara mencegah kebocoran API Key pada file log server?
Terakhir diperbarui:
Definisi: Apa itu Sistem Logging pada AI Agent PHP?
Direct Answer:Sistem Logging AI Agent PHP adalah mekanisme pencatatan terstruktur (berbasis standar PSR-3 dan JSON Line) yang mendokumentasikan setiap siklus hidup agen — meliputi prompt pengguna, konsumsi token LLM, pemanggilan fungsi eksternal (tool calls), hingga pengecualian error runtime — dengan sanitasi token rahasia secara otomatis guna memudahkan monitoring dan audit keamanan produksi.
Dengan logging yang disiplin, developer dapat merekonstruksi jejak penalaran agen (*reasoning trace*) saat model menghasilkan jawaban halusinasi atau mengalami kegagalan koneksi jaringan.
TL;DR (Ringkasan Cepat)
- Nyawa Debugging AI: Logging yang baik adalah fondasi utama memantau konsumsi token, latensi jaringan, dan jejak keputusan otonom model.
- Metrik Kunci yang Wajib Dicatat: Timestamp ISO 8601, level log, Session ID, usage token (prompt + completion), nama tool yang dipanggil, dan stack trace error.
- Format JSON Lines (JSONL): Tulis log satu baris per objek JSON (
JSON_UNESCAPED_UNICODE) agar mudah diproses parser Elasticsearch, Datadog, atau grep Linux. - Sanitasi Kredensial & API Key: Selalu samarkan (*masking*) token OpenAI/Bearer key pada payload sebelum ditulis ke disk (misal:
sk-...***). - Rotasi File Harian: Terapkan pembagian nama file per hari (
agent-YYYY-MM-DD.log) untuk mencegah ukuran file tumbuh tidak terbatas.

Standar PSR-3, Monolog vs File Logging & Praktik Sanitasi API Key:
1. Standar PSR-3 & Komparasi Monolog vs Custom File Logging: Standar Psr\Log\LoggerInterface mendefinisikan 8 level log terstandarisasi (emergency, alert, critical, error, warning, notice, info, debug). Untuk proyek berskala enterprise dengan kebutuhan routing log ke Slack, Sentry, atau AWS CloudWatch, library monolog/monolog adalah standar de facto. Namun, untuk agen AI mandiri (*standalone agent*) atau CLI microservice, Custom Logger Class berbasis native PHP menawarkan performa tinggi, nol dependensi eksternal, dan jejak memori yang sangat minim.
2. Sanitasi & Redaksi Kredensial Sensitif: Respons dari OpenAI atau payload webhook REST API sering kali memuat kunci rahasia (seperti sk-proj-..., kata sandi database, atau Bearer token). Logger yang aman wajib menerapkan regex interceptor untuk menyamarkan nilai sensitif tersebut menjadi format yang aman (contoh: sk-proj-****masked****) sebelum string ditulis ke disk.
Membuat Custom Logger Class untuk AI Agent PHP
Berikut adalah implementasi class Logger yang kompatibel dengan standar level log modern, mendukung penulisan atomic JSON Lines (FILE_APPEND | LOCK_EX), penyamaran token sensitif, dan output konsol berwana:
<?php
namespace App\Logger;
class Logger
{
private string $logDir;
private string $level;
private bool $echoToConsole;
private static array $levels = [
'debug' => 0,
'info' => 1,
'warning' => 2,
'error' => 3,
];
public function __construct(
string $logDir = './logs',
string $level = 'info',
bool $echoToConsole = false
) {
$this->logDir = rtrim($logDir, '/');
$this->level = strtolower($level);
$this->echoToConsole = $echoToConsole;
if (!is_dir($this->logDir)) {
mkdir($this->logDir, 0755, true);
}
}
public function debug(string $message, array $context = []): void
{
$this->log('debug', $message, $context);
}
public function info(string $message, array $context = []): void
{
$this->log('info', $message, $context);
}
public function warning(string $message, array $context = []): void
{
$this->log('warning', $message, $context);
}
public function error(string $message, array $context = []): void
{
$this->log('error', $message, $context);
}
private function log(string $level, string $message, array $context = []): void
{
if ((self::$levels[$level] ?? 0) < (self::$levels[$this->level] ?? 0)) {
return; // Lewati jika severity level di bawah ambang batas konfigurasi
}
// Sanitasi kredensial rahasia pada context sebelum logging
$sanitizedContext = $this->sanitizeContext($context);
// Format nama file log harian (Rotasi Log Otomatis)
$fileName = sprintf('%s/agent-%s.log', $this->logDir, date('Y-m-d'));
$entry = json_encode([
'timestamp' => date('c'), // ISO 8601
'level' => strtoupper($level),
'message' => $message,
'context' => $sanitizedContext,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
file_put_contents($fileName, $entry, FILE_APPEND | LOCK_EX);
if ($this->echoToConsole) {
$icon = match ($level) {
'debug' => '🔍',
'info' => 'ℹ️',
'warning' => '⚠️',
'error' => '❌',
default => '📝',
};
$ctxStr = !empty($sanitizedContext) ? ' ' . json_encode($sanitizedContext) : '';
echo "{$icon} [" . strtoupper($level) . "] {$message}{$ctxStr}\n";
}
}
/**
* Menyamarkan kredensial, API Key, dan token Bearer rahasia.
*/
private function sanitizeContext(array $context): array
{
array_walk_recursive($context, function (&$value, $key) {
if (is_string($value)) {
// Redaksi token OpenAI sk-...
$value = preg_replace('/sk-[a-zA-Z0-9_-]{20,}/i', 'sk-****[REDACTED_API_KEY]****', $value);
// Redaksi Bearer tokens
$value = preg_replace('/Bearer\s+[a-zA-Z0-9_\-\.]{20,}/i', 'Bearer ****[REDACTED_TOKEN]****', $value);
// Redaksi kata kunci password atau secret
if (preg_match('/(password|secret|api_key|token|auth)/i', (string)$key) && strlen($value) > 8) {
$value = substr($value, 0, 3) . '****' . substr($value, -3);
}
}
});
return $context;
}
}Mengintegrasikan Logger ke AI Agent PHP
Untuk menghasilkan jejak eksekusi yang komprehensif, pasang pemanggilan logger pada setiap titik kritis siklus eksekusi agen:
<?php
// Cuplikan integrasi pada method MultiToolsAgent::run()
namespace App\Agent;
use App\Logger\Logger;
class MultiToolsAgent
{
private Logger $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
public function run(string $task): string
{
$sessionId = bin2hex(random_bytes(8));
// 1. Catat Awal Sesi Task
$this->logger->info('AI Agent task dimulai', [
'session_id' => $sessionId,
'task_query' => $task,
]);
for ($iteration = 1; $iteration <= $this->maxIterations; $iteration++) {
try {
// Request ke OpenAI API
$startReq = microtime(true);
$response = $this->client->chat($this->messages, $toolDefs);
$duration = round((microtime(true) - $startReq) * 1000, 2);
$usage = $response['usage'] ?? [];
$this->logger->info('Respon OpenAI diterima', [
'session_id' => $sessionId,
'iteration' => $iteration,
'latency_ms' => $duration,
'prompt_tokens' => $usage['prompt_tokens'] ?? 0,
'completion_tok' => $usage['completion_tokens'] ?? 0,
'total_tokens' => $usage['total_tokens'] ?? 0,
]);
$message = $response['choices'][0]['message'] ?? [];
// 2. Catat Setiap Eksekusi Tool Call
if (!empty($message['tool_calls'])) {
foreach ($message['tool_calls'] as $toolCall) {
$toolName = $toolCall['function']['name'] ?? '';
$args = $toolCall['function']['arguments'] ?? '';
$this->logger->debug('Eksekusi tool call', [
'session_id' => $sessionId,
'tool' => $toolName,
'arguments' => json_decode($args, true) ?? $args,
]);
$toolResult = $this->mcpClient->executeToolCall($toolCall);
$this->messages[] = $toolResult;
}
continue;
}
// 3. Catat Jawaban Akhir Sukses
$this->logger->info('AI Agent task selesai sukses', [
'session_id' => $sessionId,
'total_iterations' => $iteration,
]);
return $message['content'] ?? '';
} catch (\Throwable $e) {
// 4. Catat Exception Error Lengkap
$this->logger->error('Kegagalan eksekusi AI Agent', [
'session_id' => $sessionId,
'error_msg' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString(),
]);
throw $e;
}
}
return 'Batas iterasi maksimum tercapai.';
}
}FAQ: Pertanyaan Seputar Sistem Logging AI Agent PHP
1. Mengapa sistem logging AI Agent harus menggunakan format JSON Lines (JSONL)?
Ringkasan Jawaban:Format JSON Lines menulis setiap catatan log sebagai satu baris objek JSON independen, sehingga mempermudah proses agregasi log, pencarian otomatis oleh Elasticsearch/Logstash, dan parsing cepat via script Python/PHP.
Berbeda dari teks bebas, JSON Lines mempertahankan tipe data asli (angka token, array argumen, dan timestamp ISO).
2. Kapan sebaiknya menggunakan Monolog dibandingkan Custom Logger Class?
Ringkasan Jawaban:Gunakan library Monolog jika aplikasi Anda membutuhkan pengiriman log ke banyak saluran eksternal secara bersamaan (seperti Slack, Papertrail, New Relic, atau email alert).Gunakan Custom Logger Class sederhana jika Anda menginginkan arsitektur ringan, kecepatan I/O maksimal, dan tanpa dependensi Composer tambahan.
3. Bagaimana cara mencegah kebocoran API Key pada file log server?
Ringkasan Jawaban:Terapkan fungsi sanitasi kontekstual berbasis Regular Expression yang menyamarkan pola token (sepertisk-[a-zA-Z0-9]{20,}) menjadisk-****[REDACTED]****sebelum fungsi penulisan file dijalankan.
Selain itu, pastikan folder logs/ dilindungi oleh file .htaccess (Deny from all) agar tidak dapat diakses langsung melalui browser publik.
Rusmawan Abdullah Sani
Lead Software Engineer & System Architect
Praktisi pengembangan backend PHP modern, arsitektur AI Agent, microservices, dan otomasi server Linux. Terhubung melalui profil LinkedIn.