Data Model
Event, ProtocolData, HttpData and uploads — Sentry's central contract
Data Model
The Event
is modular by design: fields common to every origin live at the
top level; protocol specifics live in the
ProtocolData
enum. Heuristics, rules and the scorer pattern-match on the accessor
helpers and return early for variants they don't handle — no pipeline stage
may assume an event is HTTP.
Event (top level)
| Field | Type | Description |
|---|---|---|
id | Uuid | Stable unique event id |
timestamp | DateTime<Utc> | Observation time (ingest time, not log time) |
source | SourceKind | Nginx, HttpProxy, Tcp, CloudflareLogs, Syslog, EdgeTls, Synthetic |
transport | Transport | Tcp, Udp, Quic, Internal |
direction | Direction | Inbound or Outbound |
client_ip | IpAddr | Client IP, always canonical (IPv4-mapped becomes plain IPv4) |
client_port / server_port | Option<u16> | Source port and observed listening port |
geo | Option<GeoInfo> | Country/subdivision/city/lat/lon (MaxMindDB, filled by the ingestor) |
asn | Option<u32> | Autonomous system number of the client IP |
reputation | Option<ReputationInfo> | Tier + matching feed (F3.7, filled by the ingestor) |
bot | Option<BotStatus> | rDNS crawler-verification outcome (F7.7, filled by the pipeline) |
bytes_in / bytes_out | Option<u64> | Bytes received/sent |
duration_ms | Option<u64> | Request/response duration when known |
raw | Option<String> | Original record (log line, syslog message) for audit |
protocol | ProtocolData | Protocol-specific payload |
A source produces a thin
RawEvent;
the ingestor promotes it to Event and fills geo/ASN/reputation.
ProtocolData (protocol enum)
| Variant | Payload | Description |
|---|---|---|
Http(HttpData) | HttpData | HTTP/1.x or HTTP/2 request observation (nginx, proxy syslog, inline edge) |
Tcp(TcpData) | TcpData | Non-HTTP TCP stream observation: flags, reassembled payload, stream_id, stage, SYN fingerprint (window:options:MSS:wscale) and syn_count (burst aggregation, F5) |
Udp(UdpData) | UdpData | UDP datagram; dns_query when it looks like DNS |
TlsHandshake(TlsData) | TlsData | ClientHello: sni, ja3, ja4, cipher, version, alpn (F8) |
Syslog(SyslogData) | SyslogData | RFC 5424 message (RFC 3164 fallback): facility, severity, hostname, app-name, message |
Raw(RawData) | RawData | Fallback for protocols without a dedicated variant |
HttpData (key fields)
| Field | Description |
|---|---|
method | Option<HttpMethod> — typed enum (Get, Post, …, Other) |
scheme / host | http/https and the Host header value |
path / query / fragment | Path without query, raw query string, fragment |
status | Response status code when observed (inline edge and proxy fill it) |
user_agent / referer | Identification headers |
headers | Every header captured by the source (http_* log_format tokens become kebab-case keys, enabling header.X DSL rules) |
body | Request body bytes when the source is inline (bounded by body_capture_kb) |
cookies | Parsed cookies (populated by the edge) |
uploads | Option<Vec<UploadInfo>> — uploaded file metadata (F10); content never persists |
upstream_time_ms | $upstream_response_time (F12, first value of lists) |
UploadInfo / UploadKind (F10)
UploadInfo
carries field_name, filename, content_type, size and kind.
UploadKind
classifies by magic bytes (the client declaration is only a hint):
Text, Image (PNG/JPEG/GIF/WebP/BMP), Archive (ZIP/gzip/bzip2),
Executable (MZ/ELF/Mach-O/shebang), Pdf, Unknown.
Accessor helpers
impl Event {
pub fn http(&self) -> Option<&HttpData>
pub fn tcp(&self) -> Option<&TcpData>
pub fn tls(&self) -> Option<&TlsData>
pub fn syslog(&self) -> Option<&SyslogData>
pub fn protocol_kind(&self) -> ProtocolKind
}DSL rules use protocol_kind() for protocol conditions
(ProtocolKind:
Http, Http3, Tcp, Udp, Tls, Other).
Golden rule: adding a new protocol
- Add a variant to
ProtocolData. - Add a helper on
impl Event(e.g.pub fn my_proto(&self) -> Option<&MyData>). - Update
protocol_kind(). - Never add loose fields to the
Eventtop level — put them in the enum.
Old consumers keep compiling (they simply ignore the new variant) and the same pipeline serves nginx today and TCP/TLS tomorrow.
Encoding normalization (heuristics)
Heuristics (SQLi, XSS, path traversal, etc.) run over the
URL-decoded form of path/query (heuristics::http_text), so encoded
payloads (%27 = ', + or %20 = space) cannot bypass detection. When
writing new heuristics, always use http_text(http) instead of reading
http.path / http.query directly.