PageSourceSearch

https://docs.rspamd.com/assets/js/32ed5934.8f9eb456.js

js rspamd.com collected 2026-10-02 02:29:58 UTC 45,750 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkrspamd_docs=self.webpackChunkrspamd_docs||[]).push([[3968],{28453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>d});var s=t(96540);const l={},i=s.createContext(l);function r(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:r(e.components),s.createElement(i.Provider,{value:n},e.children)}},98561:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>r,metadata:()=>s,toc:()=>o});const s=JSON.parse('{"id":"configuration/logging","title":"Logging settings","description":"Introduction","source":"@site/docs/configuration/logging.md","sourceDirName":"configuration","slug":"/configuration/logging","permalink":"/configuration/logging","draft":false,"unlisted":false,"editUrl":"https://github.com/rspamd/docs.rspamd.com/edit/master/docs/configuration/logging.md","tags":[],"version":"current","frontMatter":{"title":"Logging settings"},"sidebar":"docs","previous":{"title":"Actions and scores","permalink":"/configuration/metrics"},"next":{"title":"Common options","permalink":"/configuration/options"}}');var l=t(74848),i=t(28453);const r={title:"Logging settings"},d="Rspamd logging settings",c={},o=[{value:"Introduction",id:"introduction",level:2},{value:"Unique ID",id:"unique-id",level:2},{value:"Configuration parameters",id:"configuration-parameters",level:2},{value:"JSON logging format",id:"json-logging-format",level:3},{value:"Defined debug modules",id:"defined-debug-modules",level:3},{value:"Log tag configuration",id:"log-tag-configuration",level:3},{value:"Log tag propagation in proxy mode",id:"log-tag-propagation-in-proxy-mode",level:3},{value:"Log-Tag HTTP header",id:"log-tag-http-header",level:4},{value:"Error log buffer",id:"error-log-buffer",level:3},{value:"Configuration example",id:"configuration-example",level:3},{value:"Log format",id:"log-format",level:2},{value:"Log variables",id:"log-variables",level:3}];function x(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.header,{children:(0,l.jsx)(n.h1,{id:"rspamd-logging-settings",children:"Rspamd logging settings"})}),"\n",(0,l.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,l.jsxs)(n.p,{children:["Rspamd offers various logging options. Firstly, there are three supported types of log output: ",(0,l.jsx)(n.code,{children:"console"})," logging, which outputs log messages to the console; ",(0,l.jsx)(n.code,{children:"file"})," logging, which directs log messages to a file; and logging via the ",(0,l.jsx)(n.code,{children:"syslog"})," daemon. Additionally, it is possible to limit logging to a specific level:"]}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,l.jsxs)(n.table,{children:[(0,l.jsx)(n.thead,{children:(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Level"}),(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Description"})]})}),(0,l.jsxs)(n.tbody,{children:[(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"error"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"log only critical errors"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"warning"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"log errors and warnings"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"notice"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"log only important notices + scan messages results"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"info"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"log all non-debug messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"silent"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["log at ",(0,l.jsx)(n.code,{children:"info"})," level on start and then reduce to ",(0,l.jsx)(n.code,{children:"notice"})," level when forking worker processes"]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"debug"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"log all including debug messages (huge amount of logging)"})]})]})]}),"\n",(0,l.jsxs)(n.p,{children:["You have the option to enable debug messages for specific IP addresses, which can be benef
1icial for testing purposes. Each logging type has specific mandatory parameters: log facility for syslog (refer to the ",(0,l.jsx)(n.code,{children:"syslog(3)"})," man page for facility details), and log file for file logging. File logging can also be buffered for improved performance. In order to reduce logging noise, Rspamd detects consecutive matching log messages and replaces them with the total number of repeated occurrences."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:"#81123(fuzzy): May 11 19:41:54 rspamd file_log_function: Last message repeated 155 times\n#81123(fuzzy): May 11 19:41:54 rspamd process_write_command: fuzzy hash was successfully added\n"})}),"\n",(0,l.jsx)(n.h2,{id:"unique-id",children:"Unique ID"}),"\n",(0,l.jsxs)(n.p,{children:["Starting from version 1.0, Rspamd logs include a unique ID for each logging message, enabling efficient search for relevant messages. Additionally, there is now a ",(0,l.jsx)(n.code,{children:"module"})," definition that specifies the module associated with the log message, such as ",(0,l.jsx)(n.code,{children:"task"})," or ",(0,l.jsx)(n.code,{children:"cfg"})," modules. Here is a brief example to illustrate how it works: let's consider an incoming task for a specific message. In the logs, you would observe something similar to the following entry:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:"2015-09-02 16:41:59 #45015(normal) <ed2abb>; task; accept_socket: accepted connection from ::1 port 52895\n2015-09-02 16:41:59 #45015(normal) <ed2abb>; task; rspamd_message_parse: loaded message; id: <[email protected]>; queue-id: <undef>\n"})}),"\n",(0,l.jsxs)(n.p,{children:["In this case, the tag ",(0,l.jsx)(n.code,{children:"ed2abb"})," is assigned to the task, and all subsequent processing related to that task will bear the same tag. This tagging feature is not limited to the ",(0,l.jsx)(n.code,{children:"task"})," module alone; it is also enabled in other modules like ",(0,l.jsx)(n.code,{children:"spf"})," or ",(0,l.jsx)(n.code,{children:"lua"}),". For certain modules like ",(0,l.jsx)(n.code,{children:"cfg"}),", the tag is generated statically using a specific characteristic, such as the checksum of the configuration file."]}),"\n",(0,l.jsx)(n.h2,{id:"configuration-parameters",children:"Configuration parameters"}),"\n",(0,l.jsxs)(n.p,{children:["Here is a summary of the logging parameters, each of which can be redefined or defined in the ",(0,l.jsx)(n.code,{children:"local.d/logging.inc"})," file:"]}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,l.jsxs)(n.table,{children:[(0,l.jsx)(n.thead,{children:(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Parameter"}),(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Description"})]})}),(0,l.jsxs)(n.tbody,{children:[(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"type"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Defines logging type (file, console or syslog). For some types mandatory attributes may be required."})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"filename"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Path to log file for file logging (required for ",(0,l.jsx)(n.strong,{children:"file"})," type)"]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"facility"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Logging facility for ",(0,l.jsx)(n.strong,{children:"syslog"})," type (required if this type is used)"]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"level"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Defines logging level (error, warning, notice, info, silent, or debug)."})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"log_buffered"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Flag that controls whether logging is buffered."})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"log_buf_size"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"For file and console logging defines buffer size that will be used for logging output."})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"log_urls"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Flag that defines whether all URLs in message should be logged. Useful for testing. Default: ",(0,l.jsx)(n.code,{children:"false"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"log_re_cache"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Output regular expressions statistics after each message. Default: ",(0,l.jsx)(n.code,{children:"true"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"debug_ip"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"List that contains IP addresses for which debugging should be turned on. Can be specified as a map."})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"color"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Turn on coloring for log messages (console logging only). Default: ",(0,l.jsx)(n.code,{children:"false"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"systemd"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["If ",(0,l.jsx)(n.code,{children:"true"})," timestamps aren't prepended to log messages. Default: ",(0,l.jsx)(n.code,{children:"false"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"debug_modules"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"A list of modules that are enabled for debugging."})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"log_usec"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Log microseconds (e.g. ",(0,l.jsx)(n.code,{children:"11:43:16.68071"}),"). Default: ",(0,l.jsx)(n.code,{children:"false"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"log_severity"})," (2.8+)"]}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Log severity explicitly (e.g. ",(0,l.jsx)(n.code,{children:"[info]"})," or ",(0,l.jsx)(n.code,{children:"[error]"}),"). Default: ",(0,l.jsx)(n.code,{children:"false"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"log_json"})," (3.8+)"]}
1),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["If ",(0,l.jsx)(n.code,{children:"true"})," logs are emitted in JSON format (implies ",(0,l.jsx)(n.code,{children:"log_severity=true"})," and ",(0,l.jsx)(n.code,{children:"systemd=false"}),"). Default: ",(0,l.jsx)(n.code,{children:"false"}),". Works with all log types including syslog."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"encryption_key"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Public key used to encrypt sensitive information in logs. Uses NaCl cryptobox encryption."})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"error_elts"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Size of circular buffer for storing last errors. Default: ",(0,l.jsx)(n.code,{children:"10"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"error_maxlen"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Maximum size of each element in error log buffer. Default: ",(0,l.jsx)(n.code,{children:"1000"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"task_max_elts"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Maximum number of elements in task logging output. Default: ",(0,l.jsx)(n.code,{children:"7"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"max_tag_len"})," (3.10+)"]}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Maximum length of log tag displayed in log messages. Can be 1-32. Default: ",(0,l.jsx)(n.code,{children:"6"}),"."]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"}
1,children:[(0,l.jsx)(n.code,{children:"tag_strip_policy"})," (3.10+)"]}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["Policy for stripping long log tags: ",(0,l.jsx)(n.code,{children:"right"})," (cut right part), ",(0,l.jsx)(n.code,{children:"left"})," (keep last characters), ",(0,l.jsx)(n.code,{children:"middle"})," (keep start and end). Default: ",(0,l.jsx)(n.code,{children:"right"}),"."]})]})]})]}),"\n",(0,l.jsx)(n.h3,{id:"json-logging-format",children:"JSON logging format"}),"\n",(0,l.jsxs)(n.p,{children:["When ",(0,l.jsx)(n.code,{children:"log_json"})," is enabled (version 3.8+), log messages are emitted in JSON format. This works with all logging types including file, console, and syslog. Each log entry contains the following fields:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-json",children:'{\n  "ts": 1699123456.789,\n  "pid": 12345,\n  "severity": "info",\n  "worker_type": "normal",\n  "id": "abc123",\n  "module": "task",\n  "function": "process_message",\n  "message": "Message processed successfully"\n}\n'})}),"\n",(0,l.jsx)(n.p,{children:"The JSON output is useful for log aggregation systems like Elasticsearch, Loki, or Splunk. Special characters in messages are properly escaped."}),"\n",(0,l.jsx)(n.h3,{id:"defined-debug-modules",children:"Defined debug modules"}),"\n",(0,l.jsx)(n.p,{children:"Here is a list of C debug modules defined in Rspamd:"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,l.jsxs)(n.table,{children:[(0,l.jsx)(n.thead,{children:(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Module"}),(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Description"})]})}),(0,l.jsxs)(n.tbody,{children:[(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"archive"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"messages from archive processing"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"bayes"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"messages from Bayes classifier"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"chartable"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"messages from chartable plugin"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"composites"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"debug composite symbols"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"config"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"configuration messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"control"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"control interface messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"controller"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"controller worker messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"css"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"CSS parsing messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"dkim"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"messages from DKIM module"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"events"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"async events/session messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"expression"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"expression parsing and evaluation"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"fuzzy_check"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"fuzzy check plugin messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"fuzzy_redis"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"fuzzy Redis backend messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"fuzzy_sqlite"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"fuzzy SQLite backend messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"fuzzy_storage"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"fuzzy storage worker messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"html"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"HTML parsing messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"http_context"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"HTTP context messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"hyperscan"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Hyperscan/Vectorscan engine messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"images"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"image processing messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"langdet"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"language detector messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"lua_redis"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Lua Redis module messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"lua_tcp"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Lua TCP module messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"lua_threads"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Lua thread pool messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"lua_udp"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Lua UDP module messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"luacl"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Lua classifier messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"map"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"messages from maps in Rspamd"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"metric"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"scan result/metric messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"milter"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"milter interface messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"mime"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"MIME parsing messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"monitored"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"monitored objects messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"protocol"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"protocol processing messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"proxy"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"proxy worker messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"radix"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"radix tree messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"re_cache"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"regular expressions cache messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"redis_pool"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Redis connection pool messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"rrd"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"RRD (round-robin database) messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"spf"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"SPF module messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"ssl"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"SSL/TLS messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"stat_http"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"HTTP statistics backend messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"stat_redis"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Redis statistics backend messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"symcache"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"}
1,children:"symbols cache messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"task"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"task processing messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"tokenizer"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"tokenizer messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"upstream"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"upstream selection messages"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"xmlrpc"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"XML-RPC messages"})]})]})]}),"\n",(0,l.jsxs)(n.p,{children:["Any Lua module can also be added to ",(0,l.jsx)(n.code,{children:"debug_modules"})," as they use similar naming semantics. For example, you can use ",(0,l.jsx)(n.code,{children:"dkim_signing"}),", ",(0,l.jsx)(n.code,{children:"multimap"}),", ",(0,l.jsx)(n.code,{children:"rbl"}),", ",(0,l.jsx)(n.code,{children:"arc"}),", or ",(0,l.jsx)(n.code,{children:"spf"})," to debug the corresponding Lua modules."]}),"\n",(0,l.jsx)(n.h3,{id:"log-tag-configuration",children:"Log tag configuration"}),"\n",(0,l.jsxs)(n.p,{children:["Starting from version 3.10, Rspamd allows customization of log tag display. The log tag is the unique identifier shown in angle brackets (e.g., ",(0,l.jsx)(n.code,{children:"<abc123>"}),") that helps trace related log messages for a specific task or operation."]}),"\n",(0,l.jsxs)(n.p,{children:["By default, log tags are truncated to 6 characters. You can increase this up to 32 characters using ",(0,l.jsx)(n.code,{children:"max_tag_len"}),". When a tag exceeds the maximum length, it is stripped according to ",(0,l.jsx)(n.code,{children:"tag_str
1ip_policy"}),":"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.code,{children:"right"})," (default): Keeps the beginning of the tag (e.g., ",(0,l.jsx)(n.code,{children:"abcdef..."})," \u2192 ",(0,l.jsx)(n.code,{children:"abcdef"}),")"]}),"\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.code,{children:"left"}),": Keeps the end of the tag (e.g., ",(0,l.jsx)(n.code,{children:"...uvwxyz"})," \u2192 ",(0,l.jsx)(n.code,{children:"uvwxyz"}),")"]}),"\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.code,{children:"middle"}),": Keeps both start and end (e.g., ",(0,l.jsx)(n.code,{children:"abc...xyz"}),")"]}),"\n"]}),"\n",(0,l.jsx)(n.h3,{id:"log-tag-propagation-in-proxy-mode",children:"Log tag propagation in proxy mode"}),"\n",(0,l.jsx)(n.p,{children:"When running Rspamd in proxy mode (especially with milter protocol), the log tag can be propagated from the MTA through the entire processing chain. This enables correlation of log messages across different components using the same identifier (typically the MTA's Queue-ID)."}),"\n",(0,l.jsx)(n.h4,{id:"log-tag-http-header",children:"Log-Tag HTTP header"}),"\n",(0,l.jsxs)(n.p,{children:["Rspamd supports the ",(0,l.jsx)(n.code,{children:"Log-Tag"})," HTTP header that allows clients to specify a custom log tag for the task. When this header is present, Rspamd uses its value as the log tag instead of generating a random one. This is particularly useful for:"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:"Correlating Rspamd logs with MTA logs using the same Queue-ID"}),"\n",(0,l.jsx)(n.li,{children:"Tracing messages through multiple systems"}),"\n",(0,l.jsx)(n.li,{children:"Custom integrations that need consistent identifiers"}),"\n"]}),"\n",(0,l.jsx)(n.p,{children:"Example usage with curl:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-bash",children:'curl --data-binary @message.eml \\\n  -H "Log-Tag: POSTFIX_QUEUE_ID_123" \\\n  http://localhost:11333/checkv2\n'})}),"\n",(0,l.jsxs)(n.p,{children:["The ",(0,l.jsx)(n.code,{children:"rspamd_proxy"})," worker supports the ",(0,l.jsx)(n.code,{children:"log_tag_type"})," option that controls how log tags are passed to backend workers:"]}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,l.jsxs)(n.table,{children:[(0,l.jsx)(n.thead,{children:(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Value"}),(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Description"})]})}),(0,l.jsxs)(n.tbody,{children:[(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"session"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Use proxy session's internal tag (default)"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"queue_id"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Use Queue-ID from the client (MTA) if available"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"none"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"Don't pass log tag to backend"})]})]})]}),"\n",(0,l.jsx)(n.p,{children:"Here's an ASCII diagram showing log tag flow in milter proxy mode:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:'\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                              POSTFIX MTA                                    \u2502\n\u2502                         Queue-ID: ABC123DEF                                 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                                    \u2502\n                                    \u2502 milter protocol\n                                    \u2502 sends {i} macro = "ABC123DEF"\n                                    \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                           RSPAMD PROXY                                      \u2502\n\u2502                         (milter = true)                                     \u2502\n\u2502                                                                             \u2502\n\u2502  1. Receives Queue-ID via milter macro {i}                                  \u2502\n\u2502  2. Creates HTTP request to backend                                         \u2502\n\u2502  3. Adds header based on log_tag_type:                                      \u2502\n\u2502     - session:  Log-Tag: <proxy_session_uid>                                \u2502\n\u2502     - queue_id: Log-Tag: ABC123DEF         \u25c4\u2500\u2500 uses MTA\'s Queue-ID          \u2502\n\u2502     - none:     (no Log-Tag header)                                         \u2502\n\u2502                                                                             \u2502\n\u2502  Proxy logs: <xyz789>  (own session tag)                                    \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                                    \u2502\n                                    \u2502 HTTP protocol\n                                    \u2502 Queue-ID: ABC123DEF\n                                    \u2502 Log-Tag: ABC123DEF (if log_tag_type = queue_id)\n                                    \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                          RSPAMD WORKER                                      \u2502\n\u2502                                                                             \u2502\n\u2502  Receives Log-Tag header \u2192 uses as task log tag                             \u2502\n\u2502  Worker logs: <ABC123D> (truncated to max_tag_len)                          \u2502\n\u2502                                                                             \u2502\n\u2502  Now MTA logs and Rspamd logs share the same identifier!                    \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n'})}),"\n",(0,l.jsx)(n.p,{children:"Configuration example for proxy worker:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:'worker "rspamd_proxy" {\n    bind_socket = "localhost:11332";\n    milter = true;\n    \n    upstream "local" {\n        self_scan = true;\n        # Use MTA\'s Queue-ID for log correlation\n        log_tag_type = "queue_id";\n    }\n}\n'})}),"\n",(0,l.jsx)(n.p,{children:"With this configuration, you can correlate Postfix mail.log entries with Rspamd log entries using the same Queue-ID:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:"# Postfix mail.log\nNov 25 10:15:30 mail postfix/smtpd[1234]: ABC123DEF: client=example.com[1.2.3.4]\nNov 25 10:15:31 mail postfix/cleanup[1235
1]: ABC123DEF: message-id=<[email protected]>\n\n# Rspamd log (with max_tag_len = 8)\nNov 25 10:15:31 #5678(normal) <ABC123DE>; task; ... message processed\n"})}),"\n",(0,l.jsx)(n.h3,{id:"error-log-buffer",children:"Error log buffer"}),"\n",(0,l.jsxs)(n.p,{children:["Rspamd maintains a circular buffer of recent error messages that can be accessed via the controller's ",(0,l.jsx)(n.code,{children:"/errors"})," endpoint. This is useful for monitoring and debugging without parsing log files. Configure it with:"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.code,{children:"error_elts"}),": Number of error entries to keep (default: 10)"]}),"\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.code,{children:"error_maxlen"}),": Maximum length of each error message (default: 1000)"]}),"\n"]}),"\n",(0,l.jsx)(n.h3,{id:"configuration-example",children:"Configuration example"}),"\n",(0,l.jsx)(n.p,{children:"Here is a comprehensive example of logging configuration:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:'logging {\n    type = "file";\n    filename = "/var/log/rspamd/rspamd.log";\n    level = "info";\n    \n    # Enable severity and microseconds for detailed logging\n    log_severity = true;\n    log_usec = true;\n    \n    # Buffer settings for performance\n    log_buffered = true;\n    log_buf_size = 32768;\n    \n    # Error buffer for /errors endpoint\n    error_elts = 100;\n    error_maxlen = 2000;\n    \n    # Extended log tag (useful for high-volume environments)\n    max_tag_len = 12;\n    tag_strip_policy = "middle";\n    \n    # Debug specific modules\n    debug_modules = ["dkim", "spf", "dkim_signing"];\n    \n    # Debug only for specific IPs\n    debug_ip = "192.168.1.0/24";\n}\n'})}),"\n",(0,l.jsx)(n.p,{children:"For JSON logging to a log aggregation system:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:'logging {\n    type = "file";\n    filename = "/var/log/rspamd/rspamd.json";\n    level = "info";\n    log_json = true;\n}\n'})}),"\n",(0,l.jsx)(n.h2,{id:"log-format",children:"Log format"}),"\n",(0,l.jsx)(n.p,{children:"Rspamd supports a custom log format for writing message information to the log. This feature has been supported since version 1.1. The format string for the custom log format is as follows:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{children:"log_format =<<EOD\nid: <$mid>,$if_qid{ qid: <$>,}$if_ip{ ip: $,}$if_user{ user: $,}$if_smtp_from{ from: <$>,}\n(default: $is_spam ($action): [$scores] [$symbols]),\nlen: $len, time: $time_real real,\n$time_virtual virtual, dns req: $dns_req\nEOD\n"})}),"\n",(0,l.jsxs)(n.p,{children:["Newlines are replaced with spaces in the custom log format. The log format line can include both text and variables. Each variable can have an optional ",(0,l.jsx)(n.code,{children:"if_"})," prefix, which will log the variable only if it is triggered. Additionally, each variable can have an optional body value where ",(0,l.jsx)(n.code,{children:"$"})," is replaced with the variable's value. The ",(0,l.jsx)(n.code,{children:"$"})," placeholder can be repeated multiple times in the body. For example, ",(0,l.jsx)(n.code,{children:"$if_var{$$$$}"})," will be replaced with the variable's name repeated four times."]}),"\n",(0,l.jsx)(n.h3,{id:"log-variables",children:"Log variables"}),"\n",(0,l.jsx)(n.p,{children:"Rspamd supports the following log variables:"}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,l.jsxs)(n.table,{children:[(0,l.jsx)(n.thead,{children:(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Variable"}),(0,l.jsx)(n.th,{style:{textAlign:"left"},children:"Description"})]})}),(0,l.jsxs)(n.tbody,{children:[(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"action"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"default metric action"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"digest"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"cryptographic digest of a message's content (stripped to 16 bytes or 32 hex symbols)"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"dns_req"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"number of DNS requests"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"filename"})," (from 1.8.0)"]}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"name of file if HTTP agent (e.g. rspamc) passes it"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"forced_action"})," (from 1.8.2)"]}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["forced action if form ",(0,l.jsx)(n.code,{children:'<action> "<message>"; score=<score> (set by <module>)'})]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"groups"})," (from 2.0)"]}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"symbols groups list for a task"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"ip"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"from IP"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"is_spam"})}),(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:["a one-letter rating of spammyness: ",(0,l.jsx)(n.code,{children:"T"})," for spam, ",(0,l.jsx)(n.code,{children:"F"})," for ham and ",(0,l.jsx)(n.code,{children:"S"})," for skipped messages"]})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"len"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"length of message"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"lua"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"custom Lua script (see below)"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"mid"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"message ID"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"mime_from"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"MIME from"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"mime_rcpt"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"MIME rcpt - the first recipient"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"mime_rcpts"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"MIME rcpts - all recipients"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"public_groups"})," (from 2.0)"]}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"public groups only (similar to groups but more restricted)"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"qid"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"queue ID"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"scores"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"summary of scores"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"settings_id"})," (from 2.0)"]}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"settings id for a message"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"smtp_from"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"envelope from (or MIME from if SMTP from is absent)"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"smtp_rcpt"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"envelope rcpt (or MIME from if SMTP from is absent) - the first recipient"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"smtp_rcpts"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"envelope rcpts - all recipients"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"symbols_params"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"list of all symbols and their options"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"symbols_scores_params"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"list of all symbols, their scores and options"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"symbols_scores"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"list of all symbols and their scores"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"symbols"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"list of all symbols"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"time_real"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"real time of task processing"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsxs)(n.td,{style:{textAlign:"left"},children:[(0,l.jsx)(n.code,{children:"time_virtual"})," (till 2.0)"]}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"CPU time of task processing"})]}),(0,l.jsxs)(n.tr,{children:[(0,l.jsx)(n.td,{style:{textAlign:"left"},children:(0,l.jsx)(n.code,{children:"user"})}),(0,l.jsx)(n.td,{style:{textAlign:"left"},children:"authenticated user"})]})]})]}),"\n",(0,l.jsx)(n.p,{children:"Custom logging scripts could look like the following:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-lua",children:"$lua{\n  return function(task) \n    return 'text parts: ' .. tostring(#task:get_text_parts()) \n  end\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"this script will log number of text part in messages."})]})}function a(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,l.jsx)(n,{...e,children:(0,l.jsx)(x,{...e})}):x(e)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.