new_task->event_loop = event_loop;
new_task->task_timestamp = ev_time();
new_task->time_real_finish = NAN;
+ rspamd_uuid_v7(new_task->task_uuid, new_task->task_pool->tag.uid,
+ sizeof(new_task->task_pool->tag.uid), new_task->task_timestamp);
new_task->request_headers = kh_init(rspamd_req_headers_hash);
new_task->sock = -1;
rspamd_mempool_t *task_pool; /**< memory pool for task */
double time_real_finish;
ev_tstamp task_timestamp;
+ char task_uuid[37]; /**< UUID v7 for cross-system correlation */
gboolean (*fin_callback)(struct rspamd_task *task, void *arg);
/**< callback for filters finalizing */
}
}
+int rspamd_uuid_v7(char uuid_out[37], char *opt_uid_buf, gsize uid_buflen, double timestamp)
+{
+ uint8_t uuid[16];
+ uint8_t rand_bytes[10];
+ char hex[32];
+ uint64_t ms = (uint64_t) (timestamp * 1000.0);
+
+ ottery_rand_bytes(rand_bytes, sizeof(rand_bytes));
+
+ /* Bytes 0-5: 48-bit millisecond timestamp, big-endian */
+ uuid[0] = (ms >> 40) & 0xff;
+ uuid[1] = (ms >> 32) & 0xff;
+ uuid[2] = (ms >> 24) & 0xff;
+ uuid[3] = (ms >> 16) & 0xff;
+ uuid[4] = (ms >> 8) & 0xff;
+ uuid[5] = ms & 0xff;
+
+ /* Bytes 6-7: version 7 (0111) + 12 random bits */
+ uuid[6] = 0x70 | (rand_bytes[0] & 0x0f);
+ uuid[7] = rand_bytes[1];
+
+ /* Bytes 8-9: variant 10 + 14 random bits */
+ uuid[8] = 0x80 | (rand_bytes[2] & 0x3f);
+ uuid[9] = rand_bytes[3];
+
+ /* Bytes 10-15: 48 random bits */
+ uuid[10] = rand_bytes[4];
+ uuid[11] = rand_bytes[5];
+ uuid[12] = rand_bytes[6];
+ uuid[13] = rand_bytes[7];
+ uuid[14] = rand_bytes[8];
+ uuid[15] = rand_bytes[9];
+
+ /* Encode all 16 bytes as 32 hex chars, then insert dashes */
+ rspamd_encode_hex_buf(uuid, 16, hex, sizeof(hex));
+
+ /* Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */
+ memcpy(uuid_out, hex, 8);
+ uuid_out[8] = '-';
+ memcpy(uuid_out + 9, hex + 8, 4);
+ uuid_out[13] = '-';
+ memcpy(uuid_out + 14, hex + 12, 4);
+ uuid_out[18] = '-';
+ memcpy(uuid_out + 19, hex + 16, 4);
+ uuid_out[23] = '-';
+ memcpy(uuid_out + 24, hex + 20, 12);
+ uuid_out[36] = '\0';
+
+ /* Derive log UID from bytes 8-15 (variant + random portion) */
+ if (opt_uid_buf) {
+ /* 8 binary bytes -> 16 hex chars + NUL = 17 bytes minimum */
+ if (uid_buflen < 17) {
+ return -1;
+ }
+ int enc_len = rspamd_encode_hex_buf(&uuid[8], 8,
+ opt_uid_buf, uid_buflen - 1);
+ opt_uid_buf[enc_len] = '\0';
+ return enc_len;
+ }
+
+ return 0;
+}
+
int rspamd_shmem_mkstemp(char *pattern)
{
int fd = -1;
*/
void rspamd_random_hex(char *buf, uint64_t len);
+/**
+ * Generate a UUID v7 (time-ordered) string.
+ * @param uuid_out output buffer for the 36-char UUID string + NUL
+ * @param opt_uid_buf if not NULL, filled with hex log UID derived from UUID's random part
+ * @param uid_buflen size of opt_uid_buf in bytes (ignored when opt_uid_buf is NULL)
+ * @param timestamp wall-clock time as double (e.g. from ev_time())
+ * @return number of UID chars written to opt_uid_buf, 0 if opt_uid_buf is NULL,
+ * -1 if uid_buflen is too small
+ */
+int rspamd_uuid_v7(char uuid_out[37], char *opt_uid_buf, gsize uid_buflen, double timestamp);
+
/**
* Returns
* @param pattern pattern to create (should end with some number of X symbols), modified by this function
* Returns ID of the task being processed.
*/
LUA_FUNCTION_DEF(task, get_uid);
+/***
+ * @method task:get_uuid()
+ * Returns UUID v7 of the task (time-ordered, suitable for cross-system correlation).
+ */
+LUA_FUNCTION_DEF(task, get_uuid);
/***
* @method task:get_resolver()
* Returns ready to use rspamd_resolver object suitable for making asynchronous DNS requests.
LUA_INTERFACE_DEF(task, get_received_headers),
LUA_INTERFACE_DEF(task, get_queue_id),
LUA_INTERFACE_DEF(task, get_uid),
+ LUA_INTERFACE_DEF(task, get_uuid),
LUA_INTERFACE_DEF(task, get_resolver),
LUA_INTERFACE_DEF(task, set_resolver),
LUA_INTERFACE_DEF(task, inc_dns_req),
return 1;
}
+static int
+lua_task_get_uuid(lua_State *L)
+{
+ LUA_TRACE_POINT;
+ struct rspamd_task *task = lua_check_task(L, 1);
+
+ if (task) {
+ lua_pushstring(L, task->task_uuid);
+ }
+ else {
+ return luaL_error(L, "invalid arguments");
+ }
+
+ return 1;
+}
+
static int
lua_task_get_resolver(lua_State *L)
{