Skip to content

Concepts

The data model every other page assumes. Read this once; the rest of the handbook is reference.


Data reaches Sondar three ways, and then one pipeline takes over:

  1. The agent — a lightweight collector installed on your machines. It runs collection tasks: each task is a pipeline of readers → transformers → senders. Readers pull data in (tail a log file, poll a database, scrape a Prometheus endpoint); transformers parse and enrich it; senders push it to Sondar (or elsewhere). See Log collection sources and Transformers.
  2. Listening collection — the Sondar server itself listens on a port (HTTP, TCP/UDP, FTP) and accepts data pushed to it by anything that cannot run an agent. See Listening collection.
  3. File upload — drop a file in through the UI for a quick look.

Whichever path it took, data ends up in an index as a stream of events.


An event is the fundamental unit: one log line, one metric sample, one trace span. Every event carries a set of built-in fields:

fieldmeaning
_rawthe original line, verbatim
_timethe event timestamp
_indexTimewhen it became searchable
hostthe reporting host
originsource path or collector
repothe index it lives in
sourcetypeits declared format

An accepted event is not searchable at once: an index makes new events searchable on its refresh interval, which is 10 seconds for default. Measured on a fresh install, an event sent to default turned up in a search 0.3 to 10.3 seconds after the write was accepted. A search run in that window answers “No events matched” — run it again.

Everything beyond these must be parsed out — Sondar does not guess structure at write time. That parsing is the job of transformers (in the agent) or field extraction (see below).


An index is where events live. Internally, and in some API payloads, it is called a repo — the two words mean the same thing. In SonQL queries index= is an alias for repo=.

An index has a name (permanent — lowercase letters, digits, underscores) and a retention policy (by age, by size, or both). Name by retention and access, not by service: app_logs_30d encodes what matters, checkout_service does not. Cold data can be archived to S3-compatible storage and still queried at higher latency. See Indexes.

A sourcetype is a named format declaration — it tells Sondar how to break a stream into events, extract the timestamp, and parse fields. The same index can hold several sourcetypes; a sourcetype is how you keep “nginx access logs” and “app JSON logs” distinct even in one index.


Full-text search works out of the box — a bare term matches the raw line. But to group, filter or chart on a field, it has to be extracted. There are two modes:

  • Search-time extraction — the rule runs when you query, parsing _raw on demand. No extra storage; slower queries.
  • Field acceleration (index-time) — the rule runs at write time and the fields are stored. Faster queries, but it takes storage, and events written before you turn acceleration on do not have the field.

The distinction matters when you change a rule later. See Indexes and field extraction for the full picture.


typewhat it iswhere it lands
Logstimestamped lines of textany index, via agent or listening collection
Metricsnumeric time seriesmetric indexes, via the agent’s telegraf readers or the metric system
Tracesspans of a request through your servicesthe APM surface, via OpenTelemetry (OTLP)
Eventsdiscrete alerts from other monitoring toolsan index per tool, raised as Sondar alerts; via the agent’s event listener

They share the search language and the alerting engine but have different surfaces and lifecycles. See Metrics, APM and Alerts from other tools.


An app is a packaged integration: a database, a middleware, a web server, or a whole monitoring surface. Installing an app from the catalog drops in its collection templates, dashboards, repos and alert prototypes together — this is the fast path to “I’m monitoring Postgres now.” See Database sources, Middleware and Web servers and load balancers.

SonQL is the query language for search — a pipeline of commands joined by |:

search2 repo="app_logs" ERROR
| stats count() as errors by service
| sort by errors desc

There are two engines, search (search1) and search2 (newer, used for sorting, pattern recognition and metric rules). A fresh install persists search2 as the global default, so that is what an unqualified query runs on — see Search for the exact rule and the one case that still resolves to search1. They are not quite the same language, so name the engine explicitly in anything you save. See Search and SonQL reference.


Access is role-based. Users are assigned roles; roles grant functions — search on this index, create alert rules, manage agents, and so on. Owners are assigned per object (an index, a dashboard, an alert rule) and can transfer or share them. See User settings.


Every port the platform and the agent use, in one place. Code samples across this handbook pick whichever one they need; this is the table to check a number against.

PortSideWhat it is
9200platformHTTP / the REST API and the web UI — http.port in sondar.yml. This is the endpoint for curl, the CLI, and the sondar sender. A deployment may publish it on a different host port; inside the container it is 9200. Each node also advertises its address with this port to the others, which use it to redirect a request to a particular node.
9300platformCluster transport (transport.tcp.port, allocated from 9300-9400). Node-to-node, never a client port — but not the only port nodes use: searches go between nodes on 9500 (below). Without transport TLS it does not authenticate: anything that can reach it can read, write and delete every index, with no login, permissions or data masking. The Helm chart turns transport TLS on by default; a Docker or tarball cluster does not, so allow it only between cluster members (see Securing the cluster ports).
9400 / 9600platformInternal services. Not for clients.
9500platformgRPC — external query and lookup (see External data) and the target of the sondardb consumer. Not the HTTP port. Also node-to-node: a search is sent to the nodes holding its data on this port, which is each node’s transport port + 200 — move the transport port and this one moves with it. External queries need a user’s token. With transport TLS on (below), every caller on this port — another node or an external-query client — must also present a certificate your CA signed. With it off, the node-to-node calls here take no credentials, so treat it like 9300.
4317platformOTLP/gRPC ingest — where traces arrive, authenticated with a collect token. See APM.
8091platformThe server-side HTTP collection listener. It binds only once you enable it, and the global setting ships with no port set — 8091 is the conventional choice and what the image documents. See Listening collection.
10007agentThe agent’s event listener (/event), where Datadog, Dynatrace, New Relic and Elastic alerts arrive. See Alerts from other tools.
4318agentThe agent’s OTLP HTTP trace receiver.
14317agentThe agent’s OTLP gRPC trace receiver — deliberately not 4317, so an agent can run on the same host as the platform without colliding with its OTLP ingest. On Kubernetes both agent receivers bind 0.0.0.0; otherwise 127.0.0.1.

Between the nodes of a cluster, open 9300 and 9500, and 9200 too. On Kubernetes the pods reach each other on every port already. On separate hosts or VMs, a firewall that allows only the transport (9300) lets the cluster form and accept writes, and then every search that needs another node’s data fails with Connection refused: measured 13 Oct 2026 on two nodes, with the search port unreachable until it was opened, after which they searched. 9200 was open in the working setup; that searches need it was not tested, but each node advertises it to the others for redirects.

Without transport TLS, 9300 and 9500 are not authenticated. Allow them only between cluster members. The Helm chart turns transport TLS on by default with certificates it generates; a cluster started any other way does not, and once it has more than one node it logs a warning and puts a message in the message center (the bell in the top bar) until TLS is on or the cluster is one node again. A client on the network that reaches 9300 speaks the cluster’s own protocol, and the node serves it as if it were another node: measured 18 Oct 2026 from a separate container with no credentials, it listed every index, read every document, created an index and deleted it. HTTP (9200) refuses those raw calls for every caller; 9300 has no such filter. On 9500, external queries are refused without a user’s token, but the services nodes call on each other (search tasks, trace and metric hand-off, cache invalidation) check no credentials without transport TLS: a cache invalidation and a trace hand-off from that same container were accepted.

So, on separate hosts or VMs, open 9300 to the other nodes’ addresses only, and 9500 to the other nodes and the hosts that run external queries — never to the internet. On Kubernetes every pod can reach every other pod’s ports unless a NetworkPolicy says otherwise: if other workloads share the cluster, add a policy that admits 9300 and 9500 only from Sondar’s own pods (and 9500 from your external-query clients). A single-node install needs neither port reachable from outside the host, except 9500 for external queries.

To make 9300 itself refuse strangers, turn on transport TLS with certificates from your own CA. Each node then requires the other side to present a certificate signed by that CA, and refuses the connection otherwise. Give every node a key and a certificate signed by one CA, and set, in sondar.yml or as environment variables:

sondar.security.transport.ssl.enabled: true
sondar.security.transport.ssl.key: certs/node.key # PKCS#8 PEM, relative to config/
sondar.security.transport.ssl.certificate: certs/node.crt
sondar.security.transport.ssl.certificate_authorities: certs/ca.crt # the CA that signed every node

Every node needs it, and all nodes must change together: a node with TLS on and one without cannot talk to each other. The certificate’s host name is not checked, only that your CA signed it, so a node’s address can change without reissuing it. A node with TLS on refuses to start unless certificate_authorities (or truststore.path) names your CA. Without one it would fall back to the public CAs, and verification_mode: none would trust anyone.

The same setting covers 9500. With it on, the gRPC port requires the same CA-signed certificate from every caller, and nodes present theirs to each other, so a caller without one is refused at the handshake. That includes external-query clients: the agent’s sondardb consumer and lookup_sondardb need enable_tls: true with tls_ca, tls_cert and tls_key from your CA (and tls_server_name naming the node’s certificate, or insecure_skip_verify), and a SondarDB external connection from another Sondar cannot reach a cluster with TLS on. With TLS off both ports serve anyone and each node logs a warning at boot, so firewall them either way.

On Kubernetes the chart does this for you. It generates a cluster CA and one node certificate into the Secret <release>-transport-tls on install, keeps it across upgrades, and mounts it on every pod; set sondardb.transportTls.existingSecret to use your own (keys ca.crt, tls.crt, tls.key), or sondardb.transportTls.enabled: false to turn it off. An external-query client outside the cluster needs a certificate from that CA: kubectl get secret <release>-transport-tls -o jsonpath='{.data.ca\.crt}' | base64 -d gives the CA, and the same for tls.crt and tls.key gives a certificate it accepts. All nodes change together, so turning it on for a release that ran without it is a full restart, not a rolling one.

OTLP/HTTP does not have its own port here. The platform accepts it on the ordinary HTTP port (9200 by default) at the specification’s paths — /v1/traces, /v1/logs, /v1/metrics. The spec’s default of 4318 belongs to the AGENT on a Sondar host, which is the trap in the row above: pointing an HTTP exporter at 4318 reaches the agent, not the platform.

The two OTLP gRPC numbers are the other pair that catches people: 4317 is the platform’s ingest, and 14317 is the agent’s receiver. If you are pointing an OpenTelemetry exporter at Sondar directly, you want 4317; if you are pointing it at a local agent that forwards, you want 14317.

Ports for the systems Sondar reads — Elasticsearch on 9200, etcd on 2379, Tomcat on 8080 — belong to those systems and are documented with each integration.


This handbook does not publish a benchmark number. Sondar has internal storage-efficiency measurements, and they are not repeated here because the harness that makes them re-runnable is not published yet. A number you cannot re-run on your own data is not evidence, and quoting one here would make this page the weakest thing in the handbook rather than the strongest.

What this page can do is tell you exactly what to measure and which knobs move it, so your evaluation produces numbers for your data.

The three things worth measuring

MeasureHowWhy it moves
Ingest throughput — MB/s per agentPoint one agent at a known corpus and watch the collection task’s own metrics in the Monitoring Console.Transformer count and complexity. A grok per event costs more than none.
Query latency — p95 of a stats count() over 24 h of one indexRun it from the search page against a populated index; the job records its own duration on Search jobs.Field acceleration, word-breaker settings, and whether the query hits accelerated fields or falls back to search-time extraction.
Storage per day — bytes on disk per GB ingested, at your retentionCompare the repo’s size in the Monitoring Console against what you sent.Retention and ILM, field acceleration (accelerated fields cost storage), and how much you dropped at the edge.

The knobs, in the order they matter

  1. Drop what you do not need, at the agent. The filter transformer is the only lever that reduces every downstream cost at once — noise dropped at the edge is not shipped, not indexed, not stored and not searched. Nothing else on this list beats deleting the data. See Transformers.
  2. Retention. Set per index, and the single largest storage lever. See Indexes and field extraction.
  3. Field acceleration. Trades storage and ingest cost for query speed. Accelerate the fields you filter and group by; leave the rest to search-time extraction.
  4. Word breakers. Decide what counts as a token, and therefore how large the full-text index is.
  5. Downsampling, for metrics — keep 5 m, 1 h or 1 d rollups instead of raw points beyond a horizon. See Metrics and resource groups.
  6. Archiving. Move cold data to S3 or a shared filesystem rather than keeping it on hot storage. See Data archiving.

Measure with steps 1 and 2 at their defaults first. Most evaluations that come out badly were configured to accelerate every field on an index that keeps everything for a year.