|
| 1 | +<?php |
| 2 | +/** |
| 3 | + * OTLP logs demo with Akari\log(). |
| 4 | + * |
| 5 | + * Shows: structured log records emitted from PHP and correlated to the current |
| 6 | + * trace. Each Akari\log() call attaches the request's trace_id and the active |
| 7 | + * span_id, so in Grafana you can jump from a log line straight to its trace |
| 8 | + * (and back). In this web request the active span is the request's root span, |
| 9 | + * so every log below correlates to that trace. |
| 10 | + * |
| 11 | + * Severity is a PSR-3 level string; the context array becomes log attributes. |
| 12 | + */ |
| 13 | + |
| 14 | +use function Akari\log; |
| 15 | + |
| 16 | +class Checkout |
| 17 | +{ |
| 18 | + public function process(string $orderId, int $amountCents): bool |
| 19 | + { |
| 20 | + log('info', 'checkout started', [ |
| 21 | + 'order_id' => $orderId, |
| 22 | + 'amount_cents' => $amountCents, |
| 23 | + 'currency' => 'EUR', |
| 24 | + ]); |
| 25 | + |
| 26 | + $attempt = 0; |
| 27 | + $captured = false; |
| 28 | + while ($attempt < 3 && !$captured) { |
| 29 | + $attempt++; |
| 30 | + // Pretend the first attempt is declined, then it succeeds. |
| 31 | + $captured = $attempt >= 2; |
| 32 | + |
| 33 | + if (!$captured) { |
| 34 | + log('warning', 'payment declined, retrying', [ |
| 35 | + 'order_id' => $orderId, |
| 36 | + 'attempt' => $attempt, |
| 37 | + 'gateway' => 'stripe', |
| 38 | + ]); |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + if ($captured) { |
| 43 | + log('info', 'payment captured', [ |
| 44 | + 'order_id' => $orderId, |
| 45 | + 'attempts' => $attempt, |
| 46 | + ]); |
| 47 | + } else { |
| 48 | + log('error', 'payment failed after retries', [ |
| 49 | + 'order_id' => $orderId, |
| 50 | + 'attempts' => $attempt, |
| 51 | + ]); |
| 52 | + } |
| 53 | + |
| 54 | + return $captured; |
| 55 | + } |
| 56 | +} |
| 57 | + |
| 58 | +$checkout = new Checkout(); |
| 59 | +$ok = $checkout->process('ORD-' . random_int(1000, 9999), 4999); |
| 60 | + |
| 61 | +// A final request-scope log line. |
| 62 | +log($ok ? 'notice' : 'error', 'checkout finished', ['success' => $ok]); |
| 63 | + |
| 64 | +echo "<h2>OTLP Logs Demo</h2>"; |
| 65 | +echo "<p>This request emitted structured log records via <code>Akari\\log()</code>:</p>"; |
| 66 | +echo "<ul>"; |
| 67 | +echo "<li><code>info</code> — checkout started (order + amount attributes)</li>"; |
| 68 | +echo "<li><code>warning</code> — payment declined, retrying (attempt 1)</li>"; |
| 69 | +echo "<li><code>info</code> — payment captured</li>"; |
| 70 | +echo "<li><code>" . ($ok ? 'notice' : 'error') . "</code> — checkout finished</li>"; |
| 71 | +echo "</ul>"; |
| 72 | +echo "<p>Each record carries the request's <code>trace_id</code> and the active " |
| 73 | + . "<code>span_id</code>, so logs and traces are linked.</p>"; |
| 74 | +echo "<p><em>Open <a href='http://localhost:3000'>Grafana</a> → Explore → " |
| 75 | + . "<strong>Loki</strong> datasource, query <code>{service_name=\"demo-php-app\"}</code>, " |
| 76 | + . "then click a log line's trace ID to jump to the trace in Tempo.</em></p>"; |
| 77 | + |
| 78 | +// For quick inspection without a backend, the in-memory OTLP logs JSON: |
| 79 | +echo "<details><summary>Raw OTLP logs JSON (debug)</summary><pre>"; |
| 80 | +echo htmlspecialchars(json_encode( |
| 81 | + json_decode(Akari\getLogsJson(), true), |
| 82 | + JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES |
| 83 | +)); |
| 84 | +echo "</pre></details>"; |
0 commit comments