You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

logger.c 35KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "config.h"
  17. #include "logger.h"
  18. #include "rspamd.h"
  19. #include "map.h"
  20. #include "map_helpers.h"
  21. #include "ottery.h"
  22. #include "unix-std.h"
  23. #ifdef HAVE_SYSLOG_H
  24. #include <syslog.h>
  25. #endif
  26. /* How much message should be repeated before it is count to be repeated one */
  27. #define REPEATS_MIN 3
  28. #define REPEATS_MAX 300
  29. #define LOG_ID 6
  30. #define LOGBUF_LEN 8192
  31. struct rspamd_log_module {
  32. gchar *mname;
  33. guint id;
  34. };
  35. struct rspamd_log_modules {
  36. guchar *bitset;
  37. guint bitset_len; /* Number of BITS used in bitset */
  38. guint bitset_allocated; /* Size of bitset allocated in BYTES */
  39. GHashTable *modules;
  40. };
  41. struct rspamd_logger_error_elt {
  42. gint completed;
  43. GQuark ptype;
  44. pid_t pid;
  45. gdouble ts;
  46. gchar id[LOG_ID + 1];
  47. gchar module[9];
  48. gchar message[];
  49. };
  50. struct rspamd_logger_error_log {
  51. struct rspamd_logger_error_elt *elts;
  52. rspamd_mempool_t *pool;
  53. guint32 max_elts;
  54. guint32 elt_len;
  55. /* Avoid false cache sharing */
  56. guchar __padding[64 - sizeof(gpointer) * 2 - sizeof(guint64)];
  57. guint cur_row;
  58. };
  59. /**
  60. * Static structure that store logging parameters
  61. * It is NOT shared between processes and is created by main process
  62. */
  63. struct rspamd_logger_s {
  64. rspamd_log_func_t log_func;
  65. enum rspamd_log_type log_type;
  66. gint log_facility;
  67. gint log_level;
  68. gchar *log_file;
  69. gboolean log_buffered;
  70. gboolean log_silent_workers;
  71. guint32 log_buf_size;
  72. struct rspamd_logger_error_log *errlog;
  73. struct rspamd_cryptobox_pubkey *pk;
  74. struct rspamd_cryptobox_keypair *keypair;
  75. struct {
  76. guint32 size;
  77. guint32 used;
  78. u_char *buf;
  79. } io_buf;
  80. gint fd;
  81. guint flags;
  82. gboolean is_buffered;
  83. gboolean enabled;
  84. gboolean is_debug;
  85. gboolean throttling;
  86. gboolean no_lock;
  87. gboolean opened;
  88. time_t throttling_time;
  89. enum rspamd_log_type type;
  90. pid_t pid;
  91. guint32 repeats;
  92. GQuark process_type;
  93. struct rspamd_radix_map_helper *debug_ip;
  94. guint64 last_line_cksum;
  95. gchar *saved_message;
  96. gchar *saved_function;
  97. gchar *saved_module;
  98. gchar *saved_id;
  99. rspamd_mempool_mutex_t *mtx;
  100. guint saved_loglevel;
  101. guint64 log_cnt[4];
  102. };
  103. static const gchar lf_chr = '\n';
  104. static rspamd_logger_t *default_logger = NULL;
  105. static struct rspamd_log_modules *log_modules = NULL;
  106. static void syslog_log_function (const gchar *module,
  107. const gchar *id, const gchar *function,
  108. gint log_level, const gchar *message,
  109. gpointer arg);
  110. static void file_log_function (const gchar *module,
  111. const gchar *id, const gchar *function,
  112. gint log_level, const gchar *message,
  113. gpointer arg);
  114. guint rspamd_task_log_id = (guint)-1;
  115. RSPAMD_CONSTRUCTOR(rspamd_task_log_init)
  116. {
  117. rspamd_task_log_id = rspamd_logger_add_debug_module("task");
  118. }
  119. /**
  120. * Calculate checksum for log line (used for repeating logic)
  121. */
  122. static inline guint64
  123. rspamd_log_calculate_cksum (const gchar *message, size_t mlen)
  124. {
  125. return rspamd_cryptobox_fast_hash (message, mlen, rspamd_hash_seed ());
  126. }
  127. /*
  128. * Write a line to log file (unbuffered)
  129. */
  130. static void
  131. direct_write_log_line (rspamd_logger_t *rspamd_log,
  132. void *data,
  133. gsize count,
  134. gboolean is_iov,
  135. gint level_flags)
  136. {
  137. gchar errmsg[128];
  138. struct iovec *iov;
  139. const gchar *line;
  140. glong r;
  141. gint fd;
  142. if (rspamd_log->type == RSPAMD_LOG_CONSOLE) {
  143. if (rspamd_log->flags & RSPAMD_LOG_FLAG_RSPAMADM) {
  144. fd = STDOUT_FILENO;
  145. if (level_flags & G_LOG_LEVEL_CRITICAL) {
  146. fd = STDERR_FILENO;
  147. }
  148. }
  149. else {
  150. fd = STDERR_FILENO;
  151. }
  152. }
  153. else {
  154. fd = rspamd_log->fd;
  155. }
  156. if (!rspamd_log->no_lock) {
  157. #ifndef DISABLE_PTHREAD_MUTEX
  158. if (rspamd_log->mtx) {
  159. rspamd_mempool_lock_mutex (rspamd_log->mtx);
  160. }
  161. else {
  162. rspamd_file_lock (fd, FALSE);
  163. }
  164. #else
  165. rspamd_file_lock (fd, FALSE);
  166. #endif
  167. }
  168. if (is_iov) {
  169. iov = (struct iovec *) data;
  170. r = writev (fd, iov, count);
  171. }
  172. else {
  173. line = (const gchar *) data;
  174. r = write (fd, line, count);
  175. }
  176. if (!rspamd_log->no_lock) {
  177. #ifndef DISABLE_PTHREAD_MUTEX
  178. if (rspamd_log->mtx) {
  179. rspamd_mempool_unlock_mutex (rspamd_log->mtx);
  180. }
  181. else {
  182. rspamd_file_unlock (fd, FALSE);
  183. }
  184. #else
  185. rspamd_file_unlock (fd, FALSE);
  186. #endif
  187. }
  188. if (r == -1) {
  189. /* We cannot write message to file, so we need to detect error and make decision */
  190. if (errno == EINTR) {
  191. /* Try again */
  192. direct_write_log_line (rspamd_log, data, count, is_iov, level_flags);
  193. return;
  194. }
  195. r = rspamd_snprintf (errmsg,
  196. sizeof (errmsg),
  197. "direct_write_log_line: cannot write log line: %s",
  198. strerror (errno));
  199. if (errno == EFAULT || errno == EINVAL || errno == EFBIG ||
  200. errno == ENOSPC) {
  201. /* Rare case */
  202. rspamd_log->throttling = TRUE;
  203. rspamd_log->throttling_time = time (NULL);
  204. }
  205. else if (errno == EPIPE || errno == EBADF) {
  206. /* We write to some pipe and it disappears, disable logging or we has opened bad file descriptor */
  207. rspamd_log->enabled = FALSE;
  208. }
  209. }
  210. else if (rspamd_log->throttling) {
  211. rspamd_log->throttling = FALSE;
  212. }
  213. }
  214. static void
  215. rspamd_escape_log_string (gchar *str)
  216. {
  217. guchar *p = (guchar *) str;
  218. while (*p) {
  219. if ((*p & 0x80) || !g_ascii_isprint (*p)) {
  220. *p = '?';
  221. }
  222. else if (*p == '\n' || *p == '\r') {
  223. *p = ' ';
  224. }
  225. p++;
  226. }
  227. }
  228. /* Logging utility functions */
  229. gint
  230. rspamd_log_open_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid)
  231. {
  232. if (!rspamd_log->opened) {
  233. switch (rspamd_log->log_type) {
  234. case RSPAMD_LOG_CONSOLE:
  235. /* Do nothing with console */
  236. rspamd_log->fd = -1;
  237. break;
  238. case RSPAMD_LOG_SYSLOG:
  239. #ifdef HAVE_SYSLOG_H
  240. openlog ("rspamd", LOG_NDELAY | LOG_PID,
  241. rspamd_log->log_facility);
  242. #endif
  243. break;
  244. case RSPAMD_LOG_FILE:
  245. rspamd_log->fd = open (rspamd_log->log_file,
  246. O_CREAT | O_WRONLY | O_APPEND,
  247. S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
  248. if (rspamd_log->fd == -1) {
  249. fprintf (stderr,
  250. "open_log: cannot open desired log file: %s, %s\n",
  251. rspamd_log->log_file, strerror (errno));
  252. return -1;
  253. }
  254. if (fchown (rspamd_log->fd, uid, gid) == -1) {
  255. fprintf (stderr,
  256. "open_log: cannot chown desired log file: %s, %s\n",
  257. rspamd_log->log_file, strerror (errno));
  258. close (rspamd_log->fd);
  259. return -1;
  260. }
  261. break;
  262. default:
  263. return -1;
  264. }
  265. rspamd_log->opened = TRUE;
  266. rspamd_log->enabled = TRUE;
  267. }
  268. return 0;
  269. }
  270. void
  271. rspamd_log_close_priv (rspamd_logger_t *rspamd_log, gboolean termination, uid_t uid, gid_t gid)
  272. {
  273. gchar tmpbuf[256];
  274. rspamd_log_flush (rspamd_log);
  275. if (rspamd_log->opened) {
  276. switch (rspamd_log->type) {
  277. case RSPAMD_LOG_CONSOLE:
  278. /* Do nothing special */
  279. break;
  280. case RSPAMD_LOG_SYSLOG:
  281. #ifdef HAVE_SYSLOG_H
  282. closelog ();
  283. #endif
  284. break;
  285. case RSPAMD_LOG_FILE:
  286. if (rspamd_log->repeats > REPEATS_MIN) {
  287. rspamd_snprintf (tmpbuf,
  288. sizeof (tmpbuf),
  289. "Last message repeated %ud times",
  290. rspamd_log->repeats);
  291. rspamd_log->repeats = 0;
  292. if (rspamd_log->saved_message) {
  293. file_log_function (rspamd_log->saved_module,
  294. rspamd_log->saved_id,
  295. rspamd_log->saved_function,
  296. rspamd_log->saved_loglevel | RSPAMD_LOG_FORCED,
  297. rspamd_log->saved_message,
  298. rspamd_log);
  299. g_free (rspamd_log->saved_message);
  300. g_free (rspamd_log->saved_function);
  301. g_free (rspamd_log->saved_module);
  302. g_free (rspamd_log->saved_id);
  303. rspamd_log->saved_message = NULL;
  304. rspamd_log->saved_function = NULL;
  305. rspamd_log->saved_module = NULL;
  306. rspamd_log->saved_id = NULL;
  307. }
  308. /* It is safe to use temporary buffer here as it is not static */
  309. file_log_function (NULL, NULL,
  310. G_STRFUNC,
  311. rspamd_log->saved_loglevel | RSPAMD_LOG_FORCED,
  312. tmpbuf,
  313. rspamd_log);
  314. }
  315. if (rspamd_log->fd != -1) {
  316. if (fsync (rspamd_log->fd) == -1) {
  317. msg_err ("error syncing log file: %s", strerror (errno));
  318. }
  319. close (rspamd_log->fd);
  320. }
  321. break;
  322. }
  323. rspamd_log->enabled = FALSE;
  324. rspamd_log->opened = FALSE;
  325. }
  326. if (termination && rspamd_log->log_file) {
  327. g_free (rspamd_log->log_file);
  328. rspamd_log->log_file = NULL;
  329. }
  330. }
  331. gint
  332. rspamd_log_reopen_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid)
  333. {
  334. rspamd_log_close_priv (rspamd_log, FALSE, uid, gid);
  335. if (rspamd_log_open_priv (rspamd_log, uid, gid) == 0) {
  336. msg_info ("log file reopened");
  337. return 0;
  338. }
  339. return -1;
  340. }
  341. /**
  342. * Open log file or initialize other structures
  343. */
  344. gint
  345. rspamd_log_open (rspamd_logger_t *logger)
  346. {
  347. return rspamd_log_open_priv (logger, -1, -1);
  348. }
  349. /**
  350. * Close log file or destroy other structures
  351. */
  352. void
  353. rspamd_log_close (rspamd_logger_t *logger, gboolean termination)
  354. {
  355. rspamd_log_close_priv (logger, termination, -1, -1);
  356. }
  357. /**
  358. * Close and open log again
  359. */
  360. gint
  361. rspamd_log_reopen (rspamd_logger_t *logger)
  362. {
  363. return rspamd_log_reopen_priv (logger, -1, -1);
  364. }
  365. /*
  366. * Setup logger
  367. */
  368. void
  369. rspamd_set_logger (struct rspamd_config *cfg,
  370. GQuark ptype,
  371. rspamd_logger_t **plogger,
  372. rspamd_mempool_t *pool)
  373. {
  374. rspamd_logger_t *logger;
  375. if (plogger == NULL || *plogger == NULL) {
  376. logger = g_malloc0 (sizeof (rspamd_logger_t));
  377. if (cfg->log_error_elts > 0 && pool) {
  378. logger->errlog = rspamd_mempool_alloc0_shared (pool,
  379. sizeof (*logger->errlog));
  380. logger->errlog->pool = pool;
  381. logger->errlog->max_elts = cfg->log_error_elts;
  382. logger->errlog->elt_len = cfg->log_error_elt_maxlen;
  383. logger->errlog->elts = rspamd_mempool_alloc0_shared (pool,
  384. sizeof (struct rspamd_logger_error_elt) * cfg->log_error_elts +
  385. cfg->log_error_elt_maxlen * cfg->log_error_elts);
  386. }
  387. if (pool) {
  388. logger->mtx = rspamd_mempool_get_mutex (pool);
  389. }
  390. if (plogger) {
  391. *plogger = logger;
  392. }
  393. }
  394. else {
  395. logger = *plogger;
  396. }
  397. logger->type = cfg->log_type;
  398. logger->pid = getpid ();
  399. logger->process_type = ptype;
  400. switch (cfg->log_type) {
  401. case RSPAMD_LOG_CONSOLE:
  402. logger->log_func = file_log_function;
  403. logger->fd = -1;
  404. break;
  405. case RSPAMD_LOG_SYSLOG:
  406. logger->log_func = syslog_log_function;
  407. break;
  408. case RSPAMD_LOG_FILE:
  409. logger->log_func = file_log_function;
  410. break;
  411. }
  412. logger->log_type = cfg->log_type;
  413. logger->log_facility = cfg->log_facility;
  414. logger->log_level = cfg->log_level;
  415. logger->log_buffered = cfg->log_buffered;
  416. logger->log_silent_workers = cfg->log_silent_workers;
  417. logger->log_buf_size = cfg->log_buf_size;
  418. if (logger->log_file) {
  419. g_free (logger->log_file);
  420. logger->log_file = NULL;
  421. }
  422. if (cfg->log_file) {
  423. logger->log_file = g_strdup (cfg->log_file);
  424. }
  425. logger->flags = cfg->log_flags;
  426. /* Set up buffer */
  427. if (cfg->log_buffered) {
  428. if (cfg->log_buf_size != 0) {
  429. logger->io_buf.size = cfg->log_buf_size;
  430. }
  431. else {
  432. logger->io_buf.size = LOGBUF_LEN;
  433. }
  434. logger->is_buffered = TRUE;
  435. logger->io_buf.buf = g_malloc (logger->io_buf.size);
  436. }
  437. /* Set up conditional logging */
  438. if (cfg->debug_ip_map != NULL) {
  439. /* Try to add it as map first of all */
  440. if (logger->debug_ip) {
  441. rspamd_map_helper_destroy_radix (logger->debug_ip);
  442. }
  443. logger->debug_ip = NULL;
  444. rspamd_config_radix_from_ucl (cfg,
  445. cfg->debug_ip_map,
  446. "IP addresses for which debug logs are enabled",
  447. &logger->debug_ip, NULL);
  448. }
  449. else if (logger->debug_ip) {
  450. rspamd_map_helper_destroy_radix (logger->debug_ip);
  451. logger->debug_ip = NULL;
  452. }
  453. if (logger->pk) {
  454. rspamd_pubkey_unref (logger->pk);
  455. }
  456. logger->pk = NULL;
  457. if (logger->keypair) {
  458. rspamd_keypair_unref (logger->keypair);
  459. }
  460. logger->keypair = NULL;
  461. if (cfg->log_encryption_key) {
  462. logger->pk = rspamd_pubkey_ref (cfg->log_encryption_key);
  463. logger->keypair = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
  464. RSPAMD_CRYPTOBOX_MODE_25519);
  465. rspamd_pubkey_calculate_nm (logger->pk, logger->keypair);
  466. }
  467. default_logger = logger;
  468. }
  469. /**
  470. * Used after fork() for updating structure params
  471. */
  472. void
  473. rspamd_log_update_pid (GQuark ptype, rspamd_logger_t *rspamd_log)
  474. {
  475. rspamd_log->pid = getpid ();
  476. rspamd_log->process_type = ptype;
  477. /* We also need to clear all messages pending */
  478. if (rspamd_log->repeats > 0) {
  479. rspamd_log->repeats = 0;
  480. if (rspamd_log->saved_message) {
  481. g_free (rspamd_log->saved_message);
  482. g_free (rspamd_log->saved_function);
  483. g_free (rspamd_log->saved_module);
  484. g_free (rspamd_log->saved_id);
  485. rspamd_log->saved_message = NULL;
  486. rspamd_log->saved_function = NULL;
  487. rspamd_log->saved_module = NULL;
  488. rspamd_log->saved_id = NULL;
  489. }
  490. }
  491. }
  492. /**
  493. * Flush logging buffer
  494. */
  495. void
  496. rspamd_log_flush (rspamd_logger_t *rspamd_log)
  497. {
  498. if (rspamd_log->is_buffered &&
  499. (rspamd_log->type == RSPAMD_LOG_CONSOLE ||
  500. rspamd_log->type == RSPAMD_LOG_FILE)) {
  501. direct_write_log_line (rspamd_log,
  502. rspamd_log->io_buf.buf,
  503. rspamd_log->io_buf.used,
  504. FALSE, rspamd_log->log_level);
  505. rspamd_log->io_buf.used = 0;
  506. }
  507. }
  508. static inline gboolean
  509. rspamd_logger_need_log (rspamd_logger_t *rspamd_log, GLogLevelFlags log_level,
  510. guint module_id)
  511. {
  512. g_assert (rspamd_log != NULL);
  513. if ((log_level & RSPAMD_LOG_FORCED) ||
  514. (log_level & (RSPAMD_LOG_LEVEL_MASK & G_LOG_LEVEL_MASK)) <= rspamd_log->log_level) {
  515. return TRUE;
  516. }
  517. if (module_id != (guint)-1 && isset (log_modules->bitset, module_id)) {
  518. return TRUE;
  519. }
  520. return FALSE;
  521. }
  522. static gchar *
  523. rspamd_log_encrypt_message (const gchar *begin, const gchar *end,
  524. rspamd_logger_t *rspamd_log)
  525. {
  526. guchar *out;
  527. gchar *b64;
  528. guchar *p, *nonce, *mac;
  529. const guchar *comp;
  530. guint len, inlen;
  531. g_assert (end > begin);
  532. /* base64 (pubkey | nonce | message) */
  533. inlen = rspamd_cryptobox_nonce_bytes (RSPAMD_CRYPTOBOX_MODE_25519) +
  534. rspamd_cryptobox_pk_bytes (RSPAMD_CRYPTOBOX_MODE_25519) +
  535. rspamd_cryptobox_mac_bytes (RSPAMD_CRYPTOBOX_MODE_25519) +
  536. (end - begin);
  537. out = g_malloc (inlen);
  538. p = out;
  539. comp = rspamd_pubkey_get_pk (rspamd_log->pk, &len);
  540. memcpy (p, comp, len);
  541. p += len;
  542. ottery_rand_bytes (p, rspamd_cryptobox_nonce_bytes (RSPAMD_CRYPTOBOX_MODE_25519));
  543. nonce = p;
  544. p += rspamd_cryptobox_nonce_bytes (RSPAMD_CRYPTOBOX_MODE_25519);
  545. mac = p;
  546. p += rspamd_cryptobox_mac_bytes (RSPAMD_CRYPTOBOX_MODE_25519);
  547. memcpy (p, begin, end - begin);
  548. comp = rspamd_pubkey_get_nm (rspamd_log->pk, rspamd_log->keypair);
  549. g_assert (comp != NULL);
  550. rspamd_cryptobox_encrypt_nm_inplace (p, end - begin, nonce, comp, mac,
  551. RSPAMD_CRYPTOBOX_MODE_25519);
  552. b64 = rspamd_encode_base64 (out, inlen, 0, NULL);
  553. g_free (out);
  554. return b64;
  555. }
  556. static void
  557. rspamd_log_write_ringbuffer (rspamd_logger_t *rspamd_log,
  558. const gchar *module, const gchar *id,
  559. const gchar *data, glong len)
  560. {
  561. guint32 row_num;
  562. struct rspamd_logger_error_log *elog;
  563. struct rspamd_logger_error_elt *elt;
  564. if (!rspamd_log->errlog) {
  565. return;
  566. }
  567. elog = rspamd_log->errlog;
  568. g_atomic_int_compare_and_exchange (&elog->cur_row, elog->max_elts, 0);
  569. #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30))
  570. row_num = g_atomic_int_add (&elog->cur_row, 1);
  571. #else
  572. row_num = g_atomic_int_exchange_and_add (&elog->cur_row, 1);
  573. #endif
  574. if (row_num < elog->max_elts) {
  575. elt = (struct rspamd_logger_error_elt *)(((guchar *)elog->elts) +
  576. (sizeof (*elt) + elog->elt_len) * row_num);
  577. g_atomic_int_set (&elt->completed, 0);
  578. }
  579. else {
  580. /* Race condition */
  581. elog->cur_row = 0;
  582. return;
  583. }
  584. elt->pid = rspamd_log->pid;
  585. elt->ptype = rspamd_log->process_type;
  586. elt->ts = rspamd_get_calendar_ticks ();
  587. if (id) {
  588. rspamd_strlcpy (elt->id, id, sizeof (elt->id));
  589. }
  590. else {
  591. rspamd_strlcpy (elt->id, "", sizeof (elt->id));
  592. }
  593. if (module) {
  594. rspamd_strlcpy (elt->module, module, sizeof (elt->module));
  595. }
  596. else {
  597. rspamd_strlcpy (elt->module, "", sizeof (elt->module));
  598. }
  599. rspamd_strlcpy (elt->message, data, MIN (len + 1, elog->elt_len));
  600. g_atomic_int_set (&elt->completed, 1);
  601. }
  602. void
  603. rspamd_common_logv (rspamd_logger_t *rspamd_log, gint level_flags,
  604. const gchar *module, const gchar *id, const gchar *function,
  605. const gchar *fmt, va_list args)
  606. {
  607. gchar logbuf[RSPAMD_LOGBUF_SIZE], *end;
  608. gint level = level_flags & (RSPAMD_LOG_LEVEL_MASK & G_LOG_LEVEL_MASK), mod_id;
  609. if (G_UNLIKELY (rspamd_log == NULL)) {
  610. rspamd_log = default_logger;
  611. }
  612. if (G_UNLIKELY (rspamd_log == NULL)) {
  613. /* Just fprintf message to stderr */
  614. if (level >= G_LOG_LEVEL_INFO) {
  615. rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, args);
  616. fprintf (stderr, "%s\n", logbuf);
  617. }
  618. }
  619. else {
  620. if (level == G_LOG_LEVEL_DEBUG) {
  621. mod_id = rspamd_logger_add_debug_module (module);
  622. }
  623. else {
  624. mod_id = -1;
  625. }
  626. if (rspamd_logger_need_log (rspamd_log, level_flags, mod_id)) {
  627. end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, args);
  628. if ((level_flags & RSPAMD_LOG_ENCRYPTED) && rspamd_log->pk) {
  629. gchar *encrypted;
  630. encrypted = rspamd_log_encrypt_message (logbuf, end, rspamd_log);
  631. rspamd_log->log_func (module, id,
  632. function,
  633. level_flags,
  634. encrypted,
  635. rspamd_log);
  636. g_free (encrypted);
  637. }
  638. else {
  639. rspamd_log->log_func (module, id,
  640. function,
  641. level_flags,
  642. logbuf,
  643. rspamd_log);
  644. }
  645. switch (level) {
  646. case G_LOG_LEVEL_CRITICAL:
  647. rspamd_log->log_cnt[0] ++;
  648. rspamd_log_write_ringbuffer (rspamd_log, module, id, logbuf,
  649. end - logbuf);
  650. break;
  651. case G_LOG_LEVEL_WARNING:
  652. rspamd_log->log_cnt[1]++;
  653. break;
  654. case G_LOG_LEVEL_INFO:
  655. rspamd_log->log_cnt[2]++;
  656. break;
  657. case G_LOG_LEVEL_DEBUG:
  658. rspamd_log->log_cnt[3]++;
  659. break;
  660. default:
  661. break;
  662. }
  663. }
  664. }
  665. }
  666. /**
  667. * This log functions select real logger and write message if level is less or equal to configured log level
  668. */
  669. void
  670. rspamd_common_log_function (rspamd_logger_t *rspamd_log,
  671. gint level_flags,
  672. const gchar *module, const gchar *id,
  673. const gchar *function,
  674. const gchar *fmt,
  675. ...)
  676. {
  677. va_list vp;
  678. va_start (vp, fmt);
  679. rspamd_common_logv (rspamd_log, level_flags, module, id, function, fmt, vp);
  680. va_end (vp);
  681. }
  682. void
  683. rspamd_default_logv (gint level_flags, const gchar *module, const gchar *id,
  684. const gchar *function,
  685. const gchar *fmt, va_list args)
  686. {
  687. rspamd_common_logv (NULL, level_flags, module, id, function, fmt, args);
  688. }
  689. void
  690. rspamd_default_log_function (gint level_flags,
  691. const gchar *module, const gchar *id,
  692. const gchar *function, const gchar *fmt, ...)
  693. {
  694. va_list vp;
  695. va_start (vp, fmt);
  696. rspamd_default_logv (level_flags, module, id, function, fmt, vp);
  697. va_end (vp);
  698. }
  699. /**
  700. * Fill buffer with message (limits must be checked BEFORE this call)
  701. */
  702. static void
  703. fill_buffer (rspamd_logger_t *rspamd_log, const struct iovec *iov, gint iovcnt)
  704. {
  705. gint i;
  706. for (i = 0; i < iovcnt; i++) {
  707. memcpy (rspamd_log->io_buf.buf + rspamd_log->io_buf.used,
  708. iov[i].iov_base,
  709. iov[i].iov_len);
  710. rspamd_log->io_buf.used += iov[i].iov_len;
  711. }
  712. }
  713. /*
  714. * Write message to buffer or to file (using direct_write_log_line function)
  715. */
  716. static void
  717. file_log_helper (rspamd_logger_t *rspamd_log,
  718. const struct iovec *iov,
  719. guint iovcnt,
  720. gint level_flags)
  721. {
  722. size_t len = 0;
  723. guint i;
  724. if (!rspamd_log->is_buffered) {
  725. /* Write string directly */
  726. direct_write_log_line (rspamd_log, (void *) iov, iovcnt, TRUE, level_flags);
  727. }
  728. else {
  729. /* Calculate total length */
  730. for (i = 0; i < iovcnt; i++) {
  731. len += iov[i].iov_len;
  732. }
  733. /* Fill buffer */
  734. if (rspamd_log->io_buf.size < len) {
  735. /* Buffer is too small to hold this string, so write it directly */
  736. rspamd_log_flush (rspamd_log);
  737. direct_write_log_line (rspamd_log, (void *) iov, iovcnt, TRUE, level_flags);
  738. }
  739. else if (rspamd_log->io_buf.used + len >= rspamd_log->io_buf.size) {
  740. /* Buffer is full, try to write it directly */
  741. rspamd_log_flush (rspamd_log);
  742. fill_buffer (rspamd_log, iov, iovcnt);
  743. }
  744. else {
  745. /* Copy incoming string to buffer */
  746. fill_buffer (rspamd_log, iov, iovcnt);
  747. }
  748. }
  749. }
  750. /**
  751. * Syslog interface for logging
  752. */
  753. static void
  754. syslog_log_function (const gchar *module, const gchar *id,
  755. const gchar *function,
  756. gint level_flags,
  757. const gchar *message,
  758. gpointer arg)
  759. {
  760. rspamd_logger_t *rspamd_log = arg;
  761. #ifdef HAVE_SYSLOG_H
  762. struct {
  763. GLogLevelFlags glib_level;
  764. gint syslog_level;
  765. } levels_match[] = {
  766. {G_LOG_LEVEL_DEBUG, LOG_DEBUG},
  767. {G_LOG_LEVEL_INFO, LOG_INFO},
  768. {G_LOG_LEVEL_WARNING, LOG_WARNING},
  769. {G_LOG_LEVEL_CRITICAL, LOG_ERR}
  770. };
  771. unsigned i;
  772. gint syslog_level;
  773. if (!(level_flags & RSPAMD_LOG_FORCED) && !rspamd_log->enabled) {
  774. return;
  775. }
  776. /* Detect level */
  777. syslog_level = LOG_DEBUG;
  778. for (i = 0; i < G_N_ELEMENTS (levels_match); i ++) {
  779. if (level_flags & levels_match[i].glib_level) {
  780. syslog_level = levels_match[i].syslog_level;
  781. break;
  782. }
  783. }
  784. syslog (syslog_level, "<%.*s>; %s; %s: %s",
  785. LOG_ID, id != NULL ? id : "",
  786. module != NULL ? module : "",
  787. function != NULL ? function : "",
  788. message);
  789. #endif
  790. }
  791. static inline void
  792. log_time (gdouble now, rspamd_logger_t *rspamd_log, gchar *timebuf,
  793. size_t len)
  794. {
  795. time_t sec = (time_t)now;
  796. gsize r;
  797. struct tm tms;
  798. rspamd_localtime (sec, &tms);
  799. r = strftime (timebuf, len, "%F %H:%M:%S", &tms);
  800. if (rspamd_log->flags & RSPAMD_LOG_FLAG_USEC) {
  801. gchar usec_buf[16];
  802. rspamd_snprintf (usec_buf, sizeof (usec_buf), "%.5f",
  803. now - (gdouble)sec);
  804. rspamd_snprintf (timebuf + r, len - r,
  805. "%s", usec_buf + 1);
  806. }
  807. }
  808. /**
  809. * Main file interface for logging
  810. */
  811. static void
  812. file_log_function (const gchar *module, const gchar *id,
  813. const gchar *function,
  814. gint level_flags,
  815. const gchar *message,
  816. gpointer arg)
  817. {
  818. static gchar timebuf[64], modulebuf[64];
  819. gchar tmpbuf[256];
  820. gchar *m;
  821. gdouble now;
  822. struct iovec iov[6];
  823. gulong r = 0, mr = 0;
  824. guint64 cksum;
  825. size_t mlen, mremain;
  826. const gchar *cptype = NULL;
  827. gboolean got_time = FALSE;
  828. rspamd_logger_t *rspamd_log = arg;
  829. if (!(level_flags & RSPAMD_LOG_FORCED) && !rspamd_log->enabled) {
  830. return;
  831. }
  832. /* Check throttling due to write errors */
  833. if (!(level_flags & RSPAMD_LOG_FORCED) && rspamd_log->throttling) {
  834. now = rspamd_get_calendar_ticks ();
  835. if (rspamd_log->throttling_time != now) {
  836. rspamd_log->throttling_time = now;
  837. got_time = TRUE;
  838. }
  839. else {
  840. /* Do not try to write to file too often while throttling */
  841. return;
  842. }
  843. }
  844. if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_RSPAMADM)) {
  845. /* Check repeats */
  846. mlen = strlen (message);
  847. cksum = rspamd_log_calculate_cksum (message, mlen);
  848. if (cksum == rspamd_log->last_line_cksum) {
  849. rspamd_log->repeats++;
  850. if (rspamd_log->repeats > REPEATS_MIN && rspamd_log->repeats <
  851. REPEATS_MAX) {
  852. /* Do not log anything */
  853. if (rspamd_log->saved_message == NULL) {
  854. rspamd_log->saved_message = g_strdup (message);
  855. rspamd_log->saved_function = g_strdup (function);
  856. if (module) {
  857. rspamd_log->saved_module = g_strdup (module);
  858. }
  859. if (id) {
  860. rspamd_log->saved_id = g_strdup (id);
  861. }
  862. rspamd_log->saved_loglevel = level_flags;
  863. }
  864. return;
  865. }
  866. else if (rspamd_log->repeats > REPEATS_MAX) {
  867. rspamd_snprintf (tmpbuf,
  868. sizeof (tmpbuf),
  869. "Last message repeated %ud times",
  870. rspamd_log->repeats);
  871. rspamd_log->repeats = 0;
  872. /* It is safe to use temporary buffer here as it is not static */
  873. if (rspamd_log->saved_message) {
  874. file_log_function (rspamd_log->saved_module,
  875. rspamd_log->saved_id,
  876. rspamd_log->saved_function,
  877. rspamd_log->saved_loglevel,
  878. rspamd_log->saved_message,
  879. arg);
  880. g_free (rspamd_log->saved_message);
  881. g_free (rspamd_log->saved_function);
  882. g_free (rspamd_log->saved_module);
  883. g_free (rspamd_log->saved_id);
  884. rspamd_log->saved_message = NULL;
  885. rspamd_log->saved_function = NULL;
  886. rspamd_log->saved_module = NULL;
  887. rspamd_log->saved_id = NULL;
  888. }
  889. file_log_function ("logger", NULL,
  890. G_STRFUNC,
  891. rspamd_log->saved_loglevel,
  892. tmpbuf,
  893. arg);
  894. file_log_function (module, id,
  895. function,
  896. level_flags,
  897. message,
  898. arg);
  899. rspamd_log->repeats = REPEATS_MIN + 1;
  900. return;
  901. }
  902. }
  903. else {
  904. /* Reset counter if new message differs from saved message */
  905. rspamd_log->last_line_cksum = cksum;
  906. if (rspamd_log->repeats > REPEATS_MIN) {
  907. rspamd_snprintf (tmpbuf,
  908. sizeof (tmpbuf),
  909. "Last message repeated %ud times",
  910. rspamd_log->repeats);
  911. rspamd_log->repeats = 0;
  912. if (rspamd_log->saved_message) {
  913. file_log_function (rspamd_log->saved_module,
  914. rspamd_log->saved_id,
  915. rspamd_log->saved_function,
  916. rspamd_log->saved_loglevel,
  917. rspamd_log->saved_message,
  918. arg);
  919. g_free (rspamd_log->saved_message);
  920. g_free (rspamd_log->saved_function);
  921. g_free (rspamd_log->saved_module);
  922. g_free (rspamd_log->saved_id);
  923. rspamd_log->saved_message = NULL;
  924. rspamd_log->saved_function = NULL;
  925. rspamd_log->saved_module = NULL;
  926. rspamd_log->saved_id = NULL;
  927. }
  928. file_log_function ("logger", NULL,
  929. G_STRFUNC,
  930. level_flags,
  931. tmpbuf,
  932. arg);
  933. /* It is safe to use temporary buffer here as it is not static */
  934. file_log_function (module, id,
  935. function,
  936. level_flags,
  937. message,
  938. arg);
  939. return;
  940. }
  941. else {
  942. rspamd_log->repeats = 0;
  943. }
  944. }
  945. if (!got_time) {
  946. now = rspamd_get_calendar_ticks ();
  947. }
  948. /* Format time */
  949. if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) {
  950. log_time (now, rspamd_log, timebuf, sizeof (timebuf));
  951. }
  952. cptype = g_quark_to_string (rspamd_log->process_type);
  953. if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
  954. if (level_flags & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_MESSAGE)) {
  955. /* White */
  956. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;37m");
  957. }
  958. else if (level_flags & G_LOG_LEVEL_WARNING) {
  959. /* Magenta */
  960. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;32m");
  961. }
  962. else if (level_flags & G_LOG_LEVEL_CRITICAL) {
  963. /* Red */
  964. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[1;31m");
  965. }
  966. }
  967. else {
  968. r = 0;
  969. }
  970. if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) {
  971. r += rspamd_snprintf (tmpbuf + r,
  972. sizeof (tmpbuf) - r,
  973. "%s #%P(%s) ",
  974. timebuf,
  975. rspamd_log->pid,
  976. cptype);
  977. }
  978. else {
  979. r += rspamd_snprintf (tmpbuf + r,
  980. sizeof (tmpbuf) - r,
  981. "(%s) ",
  982. cptype);
  983. }
  984. modulebuf[0] = '\0';
  985. mremain = sizeof (modulebuf);
  986. m = modulebuf;
  987. if (id != NULL) {
  988. guint slen = strlen (id);
  989. slen = MIN (LOG_ID, slen);
  990. mr = rspamd_snprintf (m, mremain, "<%*.s>; ", slen,
  991. id);
  992. m += mr;
  993. mremain -= mr;
  994. }
  995. if (module != NULL) {
  996. mr = rspamd_snprintf (m, mremain, "%s; ", module);
  997. m += mr;
  998. mremain -= mr;
  999. }
  1000. if (function != NULL) {
  1001. mr = rspamd_snprintf (m, mremain, "%s: ", function);
  1002. m += mr;
  1003. mremain -= mr;
  1004. }
  1005. else {
  1006. mr = rspamd_snprintf (m, mremain, ": ");
  1007. m += mr;
  1008. mremain -= mr;
  1009. }
  1010. /* Construct IOV for log line */
  1011. iov[0].iov_base = tmpbuf;
  1012. iov[0].iov_len = r;
  1013. iov[1].iov_base = modulebuf;
  1014. iov[1].iov_len = m - modulebuf;
  1015. iov[2].iov_base = (void *) message;
  1016. iov[2].iov_len = mlen;
  1017. iov[3].iov_base = (void *) &lf_chr;
  1018. iov[3].iov_len = 1;
  1019. if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
  1020. iov[4].iov_base = "\033[0m";
  1021. iov[4].iov_len = sizeof ("\033[0m") - 1;
  1022. /* Call helper (for buffering) */
  1023. file_log_helper (rspamd_log, iov, 5, level_flags);
  1024. }
  1025. else {
  1026. /* Call helper (for buffering) */
  1027. file_log_helper (rspamd_log, iov, 4, level_flags);
  1028. }
  1029. }
  1030. else {
  1031. /* Rspamadm logging version */
  1032. mlen = strlen (message);
  1033. if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
  1034. if (level_flags & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_MESSAGE)) {
  1035. /* White */
  1036. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;37m");
  1037. }
  1038. else if (level_flags & G_LOG_LEVEL_WARNING) {
  1039. /* Magenta */
  1040. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[0;32m");
  1041. }
  1042. else if (level_flags & G_LOG_LEVEL_CRITICAL) {
  1043. /* Red */
  1044. r = rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "\033[1;31m");
  1045. }
  1046. iov[0].iov_base = (void *) tmpbuf;
  1047. iov[0].iov_len = r;
  1048. r = 1;
  1049. }
  1050. else {
  1051. r = 0;
  1052. }
  1053. if (rspamd_log->log_level == G_LOG_LEVEL_DEBUG) {
  1054. log_time (rspamd_get_calendar_ticks (),
  1055. rspamd_log, timebuf, sizeof (timebuf));
  1056. iov[r].iov_base = (void *) timebuf;
  1057. iov[r++].iov_len = strlen (timebuf);
  1058. iov[r].iov_base = (void *) " ";
  1059. iov[r++].iov_len = 1;
  1060. }
  1061. iov[r].iov_base = (void *) message;
  1062. iov[r++].iov_len = mlen;
  1063. iov[r].iov_base = (void *) &lf_chr;
  1064. iov[r++].iov_len = 1;
  1065. if (rspamd_log->flags & RSPAMD_LOG_FLAG_COLOR) {
  1066. iov[r].iov_base = "\033[0m";
  1067. iov[r++].iov_len = sizeof ("\033[0m") - 1;
  1068. /* Call helper (for buffering) */
  1069. file_log_helper (rspamd_log, iov, r, level_flags);
  1070. }
  1071. else {
  1072. /* Call helper (for buffering) */
  1073. file_log_helper (rspamd_log, iov, r, level_flags);
  1074. }
  1075. }
  1076. }
  1077. /**
  1078. * Write log line depending on ip
  1079. */
  1080. void
  1081. rspamd_conditional_debug (rspamd_logger_t *rspamd_log,
  1082. rspamd_inet_addr_t *addr, const gchar *module, const gchar *id,
  1083. const gchar *function, const gchar *fmt, ...)
  1084. {
  1085. static gchar logbuf[LOGBUF_LEN];
  1086. va_list vp;
  1087. gchar *end;
  1088. guint mod_id;
  1089. if (rspamd_log == NULL) {
  1090. rspamd_log = default_logger;
  1091. }
  1092. mod_id = rspamd_logger_add_debug_module (module);
  1093. if (rspamd_logger_need_log (rspamd_log, G_LOG_LEVEL_DEBUG, mod_id) ||
  1094. rspamd_log->is_debug) {
  1095. if (rspamd_log->debug_ip && addr != NULL) {
  1096. if (rspamd_match_radix_map_addr (rspamd_log->debug_ip,
  1097. addr) == NULL) {
  1098. return;
  1099. }
  1100. }
  1101. va_start (vp, fmt);
  1102. end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, vp);
  1103. *end = '\0';
  1104. va_end (vp);
  1105. rspamd_log->log_func (module, id,
  1106. function,
  1107. G_LOG_LEVEL_DEBUG | RSPAMD_LOG_FORCED,
  1108. logbuf,
  1109. rspamd_log);
  1110. }
  1111. }
  1112. void
  1113. rspamd_conditional_debug_fast (rspamd_logger_t *rspamd_log,
  1114. rspamd_inet_addr_t *addr,
  1115. guint mod_id, const gchar *module, const gchar *id,
  1116. const gchar *function, const gchar *fmt, ...)
  1117. {
  1118. static gchar logbuf[LOGBUF_LEN];
  1119. va_list vp;
  1120. gchar *end;
  1121. if (rspamd_log == NULL) {
  1122. rspamd_log = default_logger;
  1123. }
  1124. if (rspamd_logger_need_log (rspamd_log, G_LOG_LEVEL_DEBUG, mod_id) ||
  1125. rspamd_log->is_debug) {
  1126. if (rspamd_log->debug_ip && addr != NULL) {
  1127. if (rspamd_match_radix_map_addr (rspamd_log->debug_ip, addr)
  1128. == NULL) {
  1129. return;
  1130. }
  1131. }
  1132. va_start (vp, fmt);
  1133. end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, vp);
  1134. *end = '\0';
  1135. va_end (vp);
  1136. rspamd_log->log_func (module, id,
  1137. function,
  1138. G_LOG_LEVEL_DEBUG | RSPAMD_LOG_FORCED,
  1139. logbuf,
  1140. rspamd_log);
  1141. }
  1142. }
  1143. /**
  1144. * Wrapper for glib logger
  1145. */
  1146. void
  1147. rspamd_glib_log_function (const gchar *log_domain,
  1148. GLogLevelFlags log_level,
  1149. const gchar *message,
  1150. gpointer arg)
  1151. {
  1152. rspamd_logger_t *rspamd_log = arg;
  1153. if (rspamd_log->enabled &&
  1154. rspamd_logger_need_log (rspamd_log, log_level, -1)) {
  1155. rspamd_log->log_func ("glib", NULL,
  1156. NULL,
  1157. log_level,
  1158. message,
  1159. rspamd_log);
  1160. }
  1161. }
  1162. void
  1163. rspamd_glib_printerr_function (const gchar *message)
  1164. {
  1165. rspamd_common_log_function (NULL, G_LOG_LEVEL_CRITICAL, "glib",
  1166. NULL, G_STRFUNC,
  1167. "%s", message);
  1168. }
  1169. /**
  1170. * Temporary turn on debugging
  1171. */
  1172. void
  1173. rspamd_log_debug (rspamd_logger_t *rspamd_log)
  1174. {
  1175. rspamd_log->is_debug = TRUE;
  1176. }
  1177. /**
  1178. * Turn off temporary debugging
  1179. */
  1180. void
  1181. rspamd_log_nodebug (rspamd_logger_t *rspamd_log)
  1182. {
  1183. rspamd_log->is_debug = FALSE;
  1184. }
  1185. const guint64 *
  1186. rspamd_log_counters (rspamd_logger_t *logger)
  1187. {
  1188. if (logger) {
  1189. return logger->log_cnt;
  1190. }
  1191. return NULL;
  1192. }
  1193. void
  1194. rspamd_log_nolock (rspamd_logger_t *logger)
  1195. {
  1196. if (logger) {
  1197. logger->no_lock = TRUE;
  1198. }
  1199. }
  1200. void
  1201. rspamd_log_lock (rspamd_logger_t *logger)
  1202. {
  1203. if (logger) {
  1204. logger->no_lock = FALSE;
  1205. }
  1206. }
  1207. static gint
  1208. rspamd_log_errlog_cmp (const ucl_object_t **o1, const ucl_object_t **o2)
  1209. {
  1210. const ucl_object_t *ts1, *ts2;
  1211. ts1 = ucl_object_lookup (*o1, "ts");
  1212. ts2 = ucl_object_lookup (*o2, "ts");
  1213. if (ts1 && ts2) {
  1214. gdouble t1 = ucl_object_todouble (ts1), t2 = ucl_object_todouble (ts2);
  1215. if (t1 > t2) {
  1216. return -1;
  1217. }
  1218. else if (t2 > t1) {
  1219. return 1;
  1220. }
  1221. }
  1222. return 0;
  1223. }
  1224. ucl_object_t *
  1225. rspamd_log_errorbuf_export (const rspamd_logger_t *logger)
  1226. {
  1227. struct rspamd_logger_error_elt *cpy, *cur;
  1228. ucl_object_t *top = ucl_object_typed_new (UCL_ARRAY);
  1229. guint i;
  1230. if (logger->errlog == NULL) {
  1231. return top;
  1232. }
  1233. cpy = g_malloc0_n (logger->errlog->max_elts,
  1234. sizeof (*cpy) + logger->errlog->elt_len);
  1235. memcpy (cpy, logger->errlog->elts, logger->errlog->max_elts *
  1236. (sizeof (*cpy) + logger->errlog->elt_len));
  1237. for (i = 0; i < logger->errlog->max_elts; i ++) {
  1238. cur = (struct rspamd_logger_error_elt *)((guchar *)cpy +
  1239. i * ((sizeof (*cpy) + logger->errlog->elt_len)));
  1240. if (cur->completed) {
  1241. ucl_object_t *obj = ucl_object_typed_new (UCL_OBJECT);
  1242. ucl_object_insert_key (obj, ucl_object_fromdouble (cur->ts),
  1243. "ts", 0, false);
  1244. ucl_object_insert_key (obj, ucl_object_fromint (cur->pid),
  1245. "pid", 0, false);
  1246. ucl_object_insert_key (obj,
  1247. ucl_object_fromstring (g_quark_to_string (cur->ptype)),
  1248. "type", 0, false);
  1249. ucl_object_insert_key (obj, ucl_object_fromstring (cur->id),
  1250. "id", 0, false);
  1251. ucl_object_insert_key (obj, ucl_object_fromstring (cur->module),
  1252. "module", 0, false);
  1253. ucl_object_insert_key (obj, ucl_object_fromstring (cur->message),
  1254. "message", 0, false);
  1255. ucl_array_append (top, obj);
  1256. }
  1257. }
  1258. ucl_object_array_sort (top, rspamd_log_errlog_cmp);
  1259. g_free (cpy);
  1260. return top;
  1261. }
  1262. static guint
  1263. rspamd_logger_allocate_mod_bit (void)
  1264. {
  1265. if (log_modules->bitset_allocated * NBBY > log_modules->bitset_len + 1) {
  1266. log_modules->bitset_len ++;
  1267. return log_modules->bitset_len - 1;
  1268. }
  1269. else {
  1270. /* Need to expand */
  1271. log_modules->bitset_allocated *= 2;
  1272. log_modules->bitset = g_realloc (log_modules->bitset,
  1273. log_modules->bitset_allocated);
  1274. return rspamd_logger_allocate_mod_bit ();
  1275. }
  1276. }
  1277. guint
  1278. rspamd_logger_add_debug_module (const gchar *mname)
  1279. {
  1280. struct rspamd_log_module *m;
  1281. if (mname == NULL) {
  1282. return (guint)-1;
  1283. }
  1284. if (log_modules == NULL) {
  1285. log_modules = g_malloc0 (sizeof (*log_modules));
  1286. log_modules->modules = g_hash_table_new (rspamd_strcase_hash,
  1287. rspamd_strcase_equal);
  1288. log_modules->bitset_allocated = 16;
  1289. log_modules->bitset_len = 0;
  1290. log_modules->bitset = g_malloc0 (log_modules->bitset_allocated);
  1291. }
  1292. if ((m = g_hash_table_lookup (log_modules->modules, mname)) == NULL) {
  1293. m = g_malloc0 (sizeof (*m));
  1294. m->mname = g_strdup (mname);
  1295. m->id = rspamd_logger_allocate_mod_bit ();
  1296. clrbit (log_modules->bitset, m->id);
  1297. g_hash_table_insert (log_modules->modules, m->mname, m);
  1298. }
  1299. return m->id;
  1300. }
  1301. void
  1302. rspamd_logger_configure_modules (GHashTable *mods_enabled)
  1303. {
  1304. GHashTableIter it;
  1305. gpointer k, v;
  1306. guint id;
  1307. /* On first iteration, we go through all modules enabled and add missing ones */
  1308. g_hash_table_iter_init (&it, mods_enabled);
  1309. while (g_hash_table_iter_next (&it, &k, &v)) {
  1310. rspamd_logger_add_debug_module ((const gchar *)k);
  1311. }
  1312. g_hash_table_iter_init (&it, mods_enabled);
  1313. while (g_hash_table_iter_next (&it, &k, &v)) {
  1314. id = rspamd_logger_add_debug_module ((const gchar *)k);
  1315. if (isclr (log_modules->bitset, id)) {
  1316. msg_info ("enable debugging for module %s (%d)", (const gchar *) k,
  1317. id);
  1318. setbit (log_modules->bitset, id);
  1319. }
  1320. }
  1321. }
  1322. rspamd_logger_t*
  1323. rspamd_logger_get_singleton (void)
  1324. {
  1325. return default_logger;
  1326. }