PHPackages                             shyim/akari - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. shyim/akari

ActivePhp-ext[Logging &amp; Monitoring](/categories/logging)

shyim/akari
===========

A high-performance PHP observability extension. Automatic OpenTelemetry tracing, sampling, and profiling - zero-config, near-zero overhead.

0.1.1(2d ago)101↑2900%MITCPHP &gt;=8.2,&lt;8.6CI failing

Since Jun 7Pushed 2d ago2 watchersCompare

[ Source](https://github.com/shyim/akari)[ Packagist](https://packagist.org/packages/shyim/akari)[ RSS](/packages/shyim-akari/feed)WikiDiscussions main Synced 2d ago

READMEChangelog (2)DependenciesVersions (3)Used By (0)

Akari — 灯
=========

[](#akari--灯)

 *A high-performance PHP APM extension.
Automatic distributed tracing — exported as OpenTelemetry.*

Warning

This project is still a work in progress and is not yet ready for production use. APIs, configuration, and internals may change at any time.

 [![Tests](https://github.com/shyim/akari/actions/workflows/tests.yml/badge.svg)](https://github.com/shyim/akari/actions/workflows/tests.yml) [![Docker](https://github.com/shyim/akari/actions/workflows/docker.yml/badge.svg)](https://github.com/shyim/akari/actions/workflows/docker.yml) [![Container](https://camo.githubusercontent.com/201dd2bea327f36ef8db000d6f0d0c48c57042853c2c843058492fe1b32a45e9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f6e7461696e65722d676863722e696f2d626c7565)](https://github.com/shyim/akari/pkgs/container/akari%2Fakari-forwarder)

---

Akari (灯, "light") is a PHP C extension that illuminates your application's behavior. It hooks into the Zend Engine via the official `zend_observer` API to capture database queries, HTTP requests, cache and messaging calls, framework internals, and exceptions — all exported as standard OpenTelemetry traces to any OTLP-compatible collector (Jaeger, Grafana Tempo, Honeycomb, etc.).

**Key design goals:**

- **Zero-config** for 90% of use cases — drop in, get traces
- **Near-zero overhead** — fire-and-forget UDP, frame deduplication, per-hook thresholds
- **No vendor lock-in** — standard OTLP protocol, use any collector

---

Architecture
------------

[](#architecture)

```
PHP-FPM / CLI                        Go Forwarder                    Collector
┌──────────────────┐  UDP/msgpack ┌─────────────────┐  OTLP/HTTP  ┌───────────┐
│                  │──sendto()──> │                 │──POST JSON> │  Jaeger   │
│  akari (Akari)   │  fire&forget │ akari-forwarder │             │  Tempo    │
│                  │  ~1μs        │                 │             │  etc.     │
└──────────────────┘              └─────────────────┘             └───────────┘

```

Spans are serialized as compact msgpack and sent via UDP to a local Go forwarder, which batches and forwards them to your OTLP collector. Log records emitted with `Akari\log()` travel the same UDP path and are forwarded to the collector's `/v1/logs` endpoint (spans go to `/v1/traces`).

---

Quick Start
-----------

[](#quick-start)

### Docker (recommended)

[](#docker-recommended)

The forwarder is available as a container image:

```
docker run -d --name akari-forwarder \
  -p 4319:4319/udp \
  -e OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318 \
  ghcr.io/shyim/akari/akari-forwarder:main
```

### Build from source

[](#build-from-source)

#### 1. Build the extension

[](#1-build-the-extension)

```
phpize
./configure --enable-akari
make -j$(nproc)
make install
```

> Add `--enable-akari-debug` to compile in the [debug introspection functions](#debug-introspection-debug-builds-only) (`getSpansJson`, etc.). This is for testing/debugging only — leave it off for production builds.

#### 2. Build the forwarder

[](#2-build-the-forwarder)

```
cd forwarder
go build -o akari-forwarder ./cmd/akari-forwarder
```

#### 3. Configure

[](#3-configure)

```
; php.ini
extension=akari.so
akari.enable=1
akari.service_name=my-app
```

#### 4. Start the forwarder

[](#4-start-the-forwarder)

```
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 ./akari-forwarder
```

Then restart PHP-FPM or run your CLI app. Traces will appear in your collector within seconds.

---

Instrumentation Coverage
------------------------

[](#instrumentation-coverage)

### Database &amp; Cache

[](#database--cache)

SystemWhat's tracedAttributes**PDO**`query`, `exec`, `prepare`, `beginTransaction`, `commit`, `rollback``db.system`, `db.name`, `db.statement`, `db.user`**SQLite3**`query`, `querySingle`, `exec`, `prepare`, `SQLite3Stmt::execute` (SQL recovered from `prepare`)`db.system=sqlite`, `db.statement`**MySQLi**OOP + procedural, `connect`, `prepare`, `execute`, transactions`db.system=mysql`, SQL statement**OCI8 / Oracle**`oci_parse`, `oci_execute`, `oci_connect`, `oci_commit`, `oci_rollback``db.system=oracle`**Redis / RedisCluster**150+ commands with key extraction (phpredis + Relay)`db.system=redis`, `db.statement=GET key`**Predis**`Client::executeCommand``db.system=redis`, command + key**Memcached / Memcache**All `get`/`set`/`delete`/`touch` etc.`db.system=memcached`, `SET key`**Elasticsearch**v7, v8, OpenSearch clients`db.system=elasticsearch`### HTTP &amp; RPC

[](#http--rpc)

SystemWhat's tracedAttributes**curl**`curl_exec`, `curl_multi_*`, `curl_setopt`, header injection`url.full`, `http.method`, `http.status_code`, `server.address`**HTTP streams**`fopen`, `file_get_contents` for `http://` URLsSame HTTP attributes as curl**gRPC**`Grpc\Call::__construct`, `startBatch``db.system=grpc`, method name**SOAP**`SoapClient::__doRequest``db.system=soap`, endpoint + action### Messaging

[](#messaging)

SystemWhat's tracedAttributes**AMQP / php-amqplib**`publish`, `consume`, `connect``messaging.system=rabbitmq`, exchange/queue, traceparent propagation**rdkafka**`Producer::produce`, `flush`, `poll`, transactions`db.system=kafka`, topic**Pheanstalk (Beanstalkd)**`dispatchCommand``db.system=beanstalkd`, command name### Frameworks

[](#frameworks)

FrameworkWhat's traced**Symfony**HttpKernel, EventDispatcher, HttpCache, Mailer, Messenger, Console**Laravel**Kernel, Queue worker, Events, Blade, Eloquent Builder**Shopware 6**Kernel, DAL (EntityRepository), Cache, Events, Storefront**Doctrine ORM**`EntityManager::flush`**Twig**Template render, block render, wrapper**GraphQL**`executeQuery`, Parser, Executor (webonyx/graphql-php)### Built-in PHP Functions

[](#built-in-php-functions)

Functions that can introduce latency are traced with configurable thresholds:

CategoryFunctionsThreshold**PCRE / Regex**`preg_match`, `preg_replace`, etc.1ms (only slow patterns traced)**Filesystem**`fopen`, `fread`, `fwrite`, `copy`, `rename`, `mkdir`, `stat`, etc. (30+)1ms**Password**`password_hash` (always), `password_verify`1ms**APCu**`apcu_fetch`, `apcu_store`, `apcu_delete`, etc.0.5ms**Session**`session_start`, `session_write_close`1ms**DNS**`gethostbyname`, `dns_get_record`, `checkdnsrr`, `getmxrr`Always**Shell**`exec`, `shell_exec`, `system`, `proc_open`, `popen`Always**Mail**`mail`, `mb_send_mail`Always**Sleep**`sleep`, `usleep`, `time_nanosleep`Always### Engine-Level

[](#engine-level)

HookPurposeINI Gate**Exception hook**Catches ALL exceptions at Zend Engine level, marks spans as ERRORAlways on**Compile file**Profiles `zend_compile_file` time per file`akari.trace_compile`**GC cycles**Profiles `gc_collect_cycles` duration`akari.trace_gc`**Stack trace capture**Captures full PHP backtrace onto spans on demandAPI---

INI Settings
------------

[](#ini-settings)

SettingDefaultDescription`akari.enable``0`Enable tracing`akari.service_name`*(empty)*OTel service name. When unset, falls back to the `OTEL_SERVICE_NAME` env var, then to `php``akari.max_depth``64`Max call stack depth (1–256, clamped)`akari.min_duration_ms``0`Drop spans shorter than this (global threshold)`akari.event_dispatch_min_duration_ms``1`Drop fast Symfony/Shopware event dispatch spans while preserving other instrumentation`akari.udp_host``127.0.0.1`Forwarder UDP host`akari.udp_port``4319`Forwarder UDP port`akari.trace_compile``0`Profile file compilation time`akari.trace_gc``0`Profile GC collect cycles time`akari.trace_cli``1`Auto-create a root span for CLI runs, named after the command (e.g. `php console asset:install`, using the script basename). The full command line (PHP executable + arguments) is recorded as the `process.command_line` attribute. Disable to skip the entry span unless `markAsWebTransaction()` is called`akari.flush_threshold``4096`Completed spans buffered before a mid-request flushAkari only creates spans for the function calls covered by its built-in instrumentation hooks (databases, HTTP clients, caches, messaging, frameworks) plus the per-request root span. There is no "trace every function" or sampling profiler mode — instrumentation is targeted, APM-style.

### Recommended Configurations

[](#recommended-configurations)

**Production (minimum overhead):**

```
akari.enable=1
akari.service_name=app-prod
akari.min_duration_ms=1      ; drop sub-millisecond spans
```

**Development (more detail):**

```
akari.enable=1
akari.service_name=app-dev
akari.trace_compile=1        ; flag slow file compilation
akari.trace_gc=1             ; flag slow GC cycles
```

---

PHP Userland API
----------------

[](#php-userland-api)

```
use function Akari\{
    enable, disable, createSpan,
    setTransactionName, getTransactionName, setServiceName,
    addTag, removeTag, setCustomVariable,
    logException, log, generateDistributedTracingHeaders,
    markAsWebTransaction, markAsCliTransaction
};

// Manual control
enable();
createSpan('payment-processing');
setTransactionName('POST /checkout');
addTag('customer_id', '42');
logException($e);

// OTLP logs — PSR-3 style. Each record carries the active trace_id and the
// current (or root) span_id for correlation, and is forwarded to /v1/logs.
log('warning', 'payment retry', ['attempt' => 2, 'gateway' => 'stripe']);

// W3C traceparent header for manual propagation
$headers = generateDistributedTracingHeaders();
// → ['traceparent' => '00-abc123...-def456...-01']

disable();
```

### Debug introspection (debug builds only)

[](#debug-introspection-debug-builds-only)

These functions are compiled in **only** when the extension is built with `--enable-akari-debug`. They are used by the test suite and for local debugging, and are absent from production builds:

```
use function Akari\{
    isProfiling, getSpanCount, getFrameCount, getTags,
    getSpansJson, getLogsJson
};

echo getSpanCount();    // number of spans this request
echo getSpansJson();    // OTLP traces JSON for debugging
echo getLogsJson();     // OTLP logs JSON for debugging
```

---

Forwarder Configuration
-----------------------

[](#forwarder-configuration)

Env VariableDefaultDescription`OTEL_EXPORTER_OTLP_ENDPOINT``http://localhost:4318`Collector endpoint`OTEL_FORWARDER_LISTEN``127.0.0.1:4319`UDP listen address`OTEL_FORWARDER_BUFFER_SIZE``16384`Max queued payloads`OTEL_FORWARDER_BATCH_SIZE``64`Payloads per flush`OTEL_FORWARDER_FLUSH_INTERVAL``100ms`Max batching window---

Production Readiness
--------------------

[](#production-readiness)

AreaStatus**Memory safety**ASAN-verified, no leaks, bounded allocations**Overhead when off**Zero — `observer_init` returns `{NULL, NULL}`**Exception tracking**Engine-level hook catches all exceptions, even caught ones**Extensibility conflicts**Uses official `zend_observer` API — compatible with Xdebug, OPcache**Cross-platform**macOS (kqueue) + Linux (timer\_create / SIGEV\_THREAD\_ID)**Thread safety (ZTS)**Full ZTS support via `ZEND_MODULE_GLOBALS`**Span limit**256K spans max per request (overflow → warning + drop)**Frame limit**64K deduplicated frames max**Stack depth**Clamped to 256, defaults to 64**SQL normalization**Query fingerprinting for grouping in dashboards---

Span Examples
-------------

[](#span-examples)

### Database

[](#database)

```
CLIENT PDO::exec
  db.system=mysql
  db.name=mydb
  db.statement=INSERT INTO users VALUES (?, ?)

```

### HTTP

[](#http)

```
CLIENT curl_exec
  http.request.method=GET
  url.full=https://api.example.com/users
  server.address=api.example.com
  http.response.status_code=200

```

### Cache

[](#cache)

```
CLIENT Redis::get
  db.system=redis
  db.statement=GET session:abc123

```

### Messaging

[](#messaging-1)

```
PRODUCER AMQPExchange::publish
  messaging.system=rabbitmq
  messaging.destination.name=orders

```

### Exceptions

[](#exceptions)

```
INTERNAL handleException
  status: ERROR
  events:
    exception.type=RuntimeException
    exception.message=Something went wrong

```

---

Project Structure
-----------------

[](#project-structure)

```
src/
├── profiler.h / profiler.c       # Core state + lifecycle
├── profiler_internal.h           # Shared internal declarations
├── profiler_span.c               # Frame dedup, span management
├── observer.c                    # zend_observer begin/end callbacks
├── hook_registry.c/h             # Modular hook registration system
├── hook_pdo.c                    # PDO instrumentation
├── hook_sqlite3.c                # SQLite3 (ext-sqlite3) instrumentation
├── hook_curl.c                   # curl instrumentation
├── hook_redis.c                  # Redis / RedisCluster / Relay
├── hook_mysqli.c                 # MySQLi (OO + procedural)
├── hook_oci8.c                   # Oracle OCI8
├── hook_memcached.c              # Memcached + Memcache
├── hook_elasticsearch.c          # Elasticsearch v7/v8 + OpenSearch
├── hook_predis.c                 # Predis (pure PHP Redis)
├── hook_grpc.c                   # gRPC
├── hook_rdkafka.c                # rdkafka
├── hook_soap.c                   # SOAP
├── hook_pheanstalk.c             # Pheanstalk / Beanstalkd
├── hook_graphql.c                # webonyx/graphql-php
├── hook_amqp.c                   # AMQP + php-amqplib
├── hook_php_streams.c            # HTTP stream wrappers
├── hook_pcre.c                   # PCRE regex functions
├── hook_io.c                     # Filesystem, password, APCu, DNS, shell, mail, sleep
├── hook_framework.c              # Symfony/Laravel route detection
├── hook_symfony.c                # Symfony components
├── hook_laravel.c                # Laravel components
├── hook_shopware.c               # Shopware 6 DAL + kernel
├── hook_doctrine.c               # Doctrine ORM
├── hook_twig.c                   # Twig templates
├── hook_error.c                  # Framework error handlers
├── hook_engine.c                 # Engine-level hooks (compile, GC, exceptions)
├── hook_root_span.c              # HTTP root span + W3C traceparent
├── php_akari.c             # Module entry, INI, userland API
├── otlp_export.c                 # OTLP JSON serialization
├── udp_export.c                  # UDP/msgpack export
├── sql_normalize.c               # SQL normalization + truncation
└── msgpack_write.h               # Header-only msgpack encoder
forwarder/
├── cmd/akari-forwarder/           # Go entry point
└── internal/                     # Receiver, buffer, transform, forwarder
tests/
└── *.phpt                        # 78 PHPT integration tests

```

---

Testing
-------

[](#testing)

```
make test                          # Run all 78 PHPT tests
make test TESTS=tests/010*         # Run specific tests
cd forwarder && go test ./...      # Run Go forwarder tests
```

CI runs automatically on every push and PR via GitHub Actions:

- **[Tests](https://github.com/shyim/akari/actions/workflows/tests.yml)** — PHP 8.2/8.3/8.4/8.5 matrix
- **[Docker](https://github.com/shyim/akari/actions/workflows/docker.yml)** — builds + pushes forwarder image

---

Requirements
------------

[](#requirements)

- PHP 8.2+
- macOS or Linux
- Go 1.26+ (for the forwarder)

---

License
-------

[](#license)

MIT

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance99

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

2d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7c45ef9077b73fce78afbfab2fa27e611a453dd77de003e2785ac84105d02bef?d=identicon)[shyim](/maintainers/shyim)

---

Top Contributors

[![shyim](https://avatars.githubusercontent.com/u/6224096?v=4)](https://github.com/shyim "shyim (22 commits)")

---

Tags

apmcgoobservabilityopentelemetryotlpphpphp-extensionprofilertracing

### Embed Badge

![Health badge](/badges/shyim-akari/health.svg)

```
[![Health](https://phpackages.com/badges/shyim-akari/health.svg)](https://phpackages.com/packages/shyim-akari)
```

###  Alternatives

[psr/log

Common interface for logging libraries

10.4k1.2B10.8k](/packages/psr-log)[open-telemetry/api

API for OpenTelemetry PHP.

1938.5M259](/packages/open-telemetry-api)[open-telemetry/sdk

SDK for OpenTelemetry PHP.

2326.5M315](/packages/open-telemetry-sdk)[illuminated/console-logger

Logging and Notifications for Laravel Console Commands.

8676.7k](/packages/illuminated-console-logger)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
