Skip to content

WordPress Signals Reference

The plugin emits raw signals — single-occurrence observations. No aggregation, deduplication, or alerting happens in the plugin itself. All intelligence lives in the Logystera processor.

Bounded signal volume. Per-request caps prevent runaway emission. Each signal type has a fixed maximum per request, with a global cap of 200 events. The plugin never becomes an unbounded source of data regardless of what happens on the site.

Controlled cardinality. The plugin sends raw payloads, but the Logystera processor decides which fields become metrics labels. You cannot accidentally create runaway metrics — every label is explicitly declared in the platform's metric definitions.

!!! info "Glossary" Time series database (TSDB): A database optimized for storing values that change over time (e.g. "requests per minute"). Each data point is a timestamp + value. Logystera uses VictoriaMetrics as its TSDB.

**Cardinality:** The number of unique label combinations on a metric. Example: a metric with label `hook` tracking 11 hooks = cardinality 11. If you added `user_id` (thousands) × `hook` (11) × `path` (unlimited), cardinality explodes to millions — slow queries, high memory, high cost. The plugin avoids this by design: the processor controls which fields become labels.

Event schema

Every signal sent to the gateway has exactly four top-level keys:

{
  "event_type": "auth.attempt",
  "timestamp": 1706000000,
  "labels": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "site": { "url": "https://example.com/", "blog": 1 },
    "req": { "method": "POST", "uri": "/wp-login.php", "ua": "Mozilla/5.0..." },
    "actor": { "user_id": 0, "ip": "1.2.3.4" }
  },
  "payload": { ... }
}

Labels (always present)

Field Type Description
labels.request_id string UUID v4. Correlates all events from the same PHP request.
labels.site.url string Site home URL.
labels.site.blog int Blog ID. Always 1 on single-site installs.
labels.req.method string HTTP verb: GET, POST, etc.
labels.req.uri string Full URI with sensitive query params redacted to [redacted].
labels.req.ua string User agent string.
labels.actor.user_id int WordPress user ID. 0 = logged-out visitor.
labels.actor.ip string Client IP. Optionally anonymized — see Configuration.

Signals

wp.environment

Emitted every flush cycle (every 15 minutes) as a snapshot. Includes a changed flag indicating whether the environment actually changed since the last emit. Leads all other signals in the batch so the processor always has current environment context.

{
  "wp_version": "6.7.1",
  "php_version": "8.2.18",
  "plugin_count": 2,
  "plugins": ["akismet/akismet.php", "logystera/logystera.php"],
  "theme": "twentytwentyfour",
  "theme_version": "1.2",
  "multisite": false,
  "changed": false,
  "debug_mode": false,
  "object_cache": true,
  "disk_free_gb": 42.7,
  "memory_limit_mb": 256,
  "wp_memory_limit_mb": 256,
  "server_software": "nginx/1.24.0",
  "php_sapi": "fpm-fcgi",
  "hosting": {
    "provider": "siteground",
    "confidence": 85,
    "all_scores": { "siteground": 85, "kinsta": 0, "aws": 10, "unknown": 5 }
  }
}
Field Type Description
debug_mode bool true if WP_DEBUG is enabled.
object_cache bool true if an external object cache (Redis/Memcached) is active (wp_using_ext_object_cache()).
disk_free_gb float Free disk space on the ABSPATH partition in GB.
memory_limit_mb int Effective PHP memory limit in MB (ini_get('memory_limit')). The actual cap enforced by the host. -1 means unlimited.
wp_memory_limit_mb int Memory limit WordPress requested via WP_MEMORY_LIMIT. If lower than memory_limit_mb, the host is capping below what WP wants.
server_software string Value of $_SERVER['SERVER_SOFTWARE'] (e.g. "nginx/1.24.0").
php_sapi string PHP SAPI name (e.g. "fpm-fcgi", "apache2handler").
hosting.provider string Detected hosting provider (e.g. "siteground", "kinsta", "aws", "unknown"). Cached for 24 hours.
hosting.confidence int Detection confidence, 0–100.
hosting.all_scores object All candidate providers with their scores.

When memory_limit_mb < wp_memory_limit_mb, the host is restricting PHP below WordPress's requested limit — this correlates with memory_near_limit signals firing more frequently.

The hosting object is determined using 5 signal layers: PHP constants, active plugins, rDNS/hostname patterns, response headers (loopback request), and path patterns. The result is cached as a WordPress transient for 24 hours to avoid repeated loopback requests.

Hook flag: environment_signals (default: ON)

Rate limit: 1 per flush cycle.


wp.search

Emitted on frontend search requests. Hooked on parse_query, fires only for the main query when is_search() is true.

{
  "query": "wordpress security",
  "query_len": 20
}
Field Type Description
query string Sanitized search term, truncated to 200 characters.
query_len int Character length of the search term.

Hook flag: search_signals (default: ON)

Rate limit: 10 per request.


http.request

Emitted once per request at shutdown. Captures transport-level data and performance.

{
  "path": "/wp-admin/plugins.php",
  "query": "?plugin_status=active",
  "status": 200,
  "is_admin": true,
  "is_ajax": false,
  "is_cron": false,
  "is_rest": false,
  "fingerprint": "GET /wp-admin/plugins.php",
  "execution_time_ms": 312,
  "peak_memory_mb": 18.4,
  "referer_host": "google.com",
  "referer_type": "search"
}

ajax_action is included when $_REQUEST['action'] is set. rest_route is included on REST requests. referer_host and referer_type are only present when an HTTP Referer header is present; referer_type is always "direct" when there is no referer.

Field Type Description
referer_host string Lowercase hostname of the HTTP Referer, stripped of www. prefix. Only present when a referer header exists.
referer_type string Classified traffic source. One of: search, social, internal, external, direct (no referer).

Search engines classified as search: Google, Bing, Yahoo, DuckDuckGo, Baidu, Yandex.
Domains classified as social: Facebook, Instagram, Twitter/X, LinkedIn, Pinterest, Reddit, YouTube, TikTok.
internal means the referer host matches the site's own domain. All other referers are external.

Rate limit: 1 per request.


auth.attempt

Emitted on every login attempt — both success and failure.

{
  "success": false,
  "username_hash": "a1b2c3d4...",
  "username_len": 5
}

Usernames are always HMAC-SHA256 hashed. The raw username is never transmitted.

Rate limit: 50 per request.


auth.logout

Emitted when a user logs out.

{
  "user_id": 42
}

Rate limit: 5 per request.


rest.request

Emitted on every REST API response. Complements http.request with semantic route data.

{
  "route": "/wp/v2/posts",
  "method": "GET",
  "status": 200,
  "namespace": "wp/v2"
}

REST calls emit both http.request and rest.request. They are correlated via labels.request_id. Do not double-count traffic — use http.request for volume metrics.

Rate limit: 20 per request.


php.warning

Emitted for each PHP warning, notice, or deprecated error.

{
  "message": "Undefined variable: foo",
  "file": "/var/www/html/wp-content/plugins/my-plugin/class.php",
  "line": 42,
  "severity": "E_WARNING",
  "fingerprint": "a1b2c3...",
  "source": "plugin"
}

source is one of: plugin, theme, core, unknown.

Backtrace function arguments are always stripped before transmission.

Rate limit: 50 per request.


php.fatal

Emitted when a PHP fatal error is detected at shutdown.

{
  "type": "E_ERROR",
  "message": "Call to undefined function foo()",
  "file": "/var/www/html/wp-content/plugins/my-plugin/class.php",
  "line": 88,
  "fingerprint": "b2c3d4...",
  "source": "plugin"
}

Rate limit: 3 per request.


cron.run

Emitted once when WordPress processes a cron batch (DOING_CRON).

{
  "execution_time_ms": 1420,
  "peak_memory_mb": 22.1,
  "had_error": true,
  "error_type": "E_WARNING",
  "error_message": "...",
  "error_file": "...",
  "error_line": 33
}

had_error and error fields are only present when a PHP error occurred during the cron run.

Rate limit: 1 per request.


wp.cron

Emitted from logystera_cron_tick (every 5 minutes) and via the WordPress missed_schedule action.

type: health_check

Full queue snapshot emitted every tick regardless of queue state.

{
  "type": "health_check",
  "total": 14,
  "overdue": 0,
  "overdue_ratio": 0.0,
  "max_delay_sec": 0,
  "avg_delay_sec": 0,
  "overdue_hooks": []
}

overdue_hooks lists the hook names of overdue jobs (up to 10).

type: missed_schedule

Emitted when a scheduled post fails to publish at its scheduled time.

{
  "type": "missed_schedule",
  "post_id": 4521,
  "post_type": "post",
  "scheduled": "2026-03-04 22:00:00",
  "delay_sec": 3612
}

Hook flag: cron_signals (default: ON)

Rate limit: 20 per request.


perf.hook_timing

Emitted at shutdown on 10% of requests. Records hooks that took longer than 50ms, up to 20 per request.

{
  "hooks": [
    { "hook": "the_content", "ms": 134.2, "source": "woocommerce" },
    { "hook": "wp_head", "ms": 87.5, "source": "theme:flavor" }
  ],
  "count": 2,
  "total_ms": 221.7
}

Each slow hook includes a source field identifying the plugin or theme with the most callbacks on that hook (heuristic for likely cause). Format: "woocommerce" for plugins, "theme:astra" for themes. Omitted when the source is WordPress core or unresolvable.

Tracked hooks: init, wp_loaded, template_redirect, wp_head, wp_footer, the_content, wp_enqueue_scripts, admin_init, admin_menu, rest_api_init, woocommerce_init.

Hook flag: hook_timing (default: OFF — performance impact)

Rate limit: 1 per request.


wp.integrity

Emitted when wp-config.php or .htaccess hash changes since the last hourly check.

{
  "type": "file_changed",
  "file": "wp-config",
  "old_hash": "a1b2c3d4...",
  "new_hash": "e5f6a7b8..."
}

file is one of: wp-config, htaccess.

Hook flag: integrity_signals (default: ON)

Rate limit: 5 per request.


wp.state_change

Emitted on plugin/theme/core lifecycle events.

{
  "type": "plugin_activated",
  "name": "akismet/akismet.php"
}

type values: plugin_activated, plugin_deactivated, theme_switched, core_updated, plugin_updated, theme_updated, translation_updated.

Rate limit: 10 per request.


upload_blocked

Emitted when WordPress blocks a file upload due to dangerous extension.

{
  "filename": "shell.php",
  "ext": "php",
  "size": 1024,
  "mime": "application/x-httpd-php"
}

Rate limit: 10 per request.


memory_near_limit

Emitted at shutdown when peak PHP memory usage exceeds 90% of WP_MEMORY_LIMIT.

{
  "peak_mb": 118.2,
  "limit_mb": 128,
  "percent": 92
}

Rate limit: 1 per request.


Database error signals

Emitted at shutdown when $wpdb->last_error is non-empty. Classified into subtypes:

Signal Trigger condition
db_error Generic database error
db_deadlock Deadlock detected
db_lock_timeout Lock wait timeout
db_connection_failed Cannot connect to MySQL
db_connection_limit Too many connections
db_table_crashed Table crash detected
db_disk_full Disk full error
db_access_denied Access denied

All database signals share the same payload shape:

{
  "error": "Table 'wp_options' is marked as crashed",
  "query_hash": "a1b2c3..."
}

Raw SQL is never included. Only query_hash (SHA-1) is transmitted.

Rate limit: 10 per request (shared across all db_* types).


Data privacy

Field Treatment
Usernames HMAC-SHA256 hashed only. Raw value never transmitted.
SQL queries Never emitted. SHA-1 hash only.
URL query strings Preserved, but sensitive params redacted to [redacted].
IP addresses Optionally anonymized. See Configuration.
PHP backtraces Function arguments stripped. File, line, function only.
Headers Authorization, Cookie, Set-Cookie never captured.

Sensitive query param names that are always redacted: token, secret, password, passwd, key, api_key, apikey, access_token, refresh_token, nonce, _wpnonce, session, jwt, code, auth.

Global rate limits

Scope Limit
Total events per request 200 (hard cap)
Pending event buffer 10,000 (events dropped when full)