Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/msolli/proletarian/llms.txt

Use this file to discover all available pages before exploring further.

Proletarian does not depend on any logging framework. Instead of pulling in a logging library, it calls a function you provide whenever something notable happens during queue worker operation. This gives you complete control over how — and at what severity level — events are recorded.

Log function signature

The logging function is passed as the :proletarian/log option to worker/create-queue-worker. It must be a function that accepts two arguments:
(fn [event-keyword data-map] ...)
  • event-keyword — a namespaced keyword that identifies the type of event (see the full list below).
  • data-map — a map of contextual data describing the event, such as the job type, attempt number, and worker ID.
If you do not specify a :proletarian/log option, the default is a println-logger that prints every event to standard output using println.
There is no “severity” or “level” built in to the log events. Proletarian does not decide whether an event is a debug message or an error — that determination is yours to make based on the event keyword and your application’s requirements.

Log event keywords

The following keywords are emitted by the queue worker during normal operation and error conditions:
KeywordWhen it fires
::worker/polling-for-jobsA worker thread is about to poll the database for the next job
::worker/handling-jobA job has been dequeued and is about to be executed
::worker/job-finishedA job completed successfully
::worker/job-interruptedA job was interrupted mid-execution (e.g. during graceful shutdown)
::worker/handle-job-exceptionA job threw an Exception; retry logic will be evaluated
::worker/handle-job-exception-with-interruptA job threw an exception but the thread interrupt flag was also set; job will be left in the queue
::worker/job-worker-errorAn unexpected Throwable was thrown during the poll/run cycle
::worker/queue-worker-shutdown-errorAn error occurred while stopping the queue worker
::worker/worker-interruptedA worker thread received an InterruptedException while polling
::worker/sql-transient-exceptionA transient SQL exception occurred during polling
:proletarian.retry/retryingA failed job is being scheduled for a retry
:proletarian.retry/not-retryingA failed job has exhausted all retries and will be archived as failed
:proletarian.executor/shutting-downThe thread pool executor has begun shutting down
:proletarian.executor/completed-shutdownThe thread pool executor finished shutting down cleanly
:proletarian.executor/already-shut-downstop! was called but the executor was already shut down
:proletarian.executor/interrupted-while-shutting-downThe shutdown thread was itself interrupted while awaiting executor termination
The ::worker/ prefix expands to :proletarian.worker/, so these keywords are fully qualified as e.g. :proletarian.worker/polling-for-jobs.

Data included in the data map

The data-map argument is merged from multiple context layers. Depending on the event, it may contain:
  • :proletarian.worker/queue-worker-id — the string ID of the queue worker (derived from the queue name unless overridden)
  • :worker-thread-id — the 1-based index of the worker thread within this queue worker
  • :job-id — the UUID of the job being processed
  • :job-type — the keyword job type
  • :attempt — the current attempt number (1-based)
  • :exception / :throwable — the caught exception or error object, included on error events
  • :retry-at — a java.time.Instant indicating when a retried job will next be eligible for processing
  • :retries-left — the number of remaining retries, included in retry events
  • :retry-spec — the retry strategy map, included in not-retrying events

Example: integrating with clojure.tools.logging

The following example, taken directly from the Proletarian README, shows how to map event keywords to log levels and wire everything up using clojure.tools.logging:
(ns your-app.workers
  (:require [clojure.tools.logging :as log]
            [next.jdbc :as jdbc]
            [proletarian.worker :as worker]
            [your-app.handlers :as handlers]))

(defn log-level
  [x]
  (case x
    ::worker/queue-worker-shutdown-error         :error
    ::worker/handle-job-exception-with-interrupt :error
    ::worker/handle-job-exception                :error
    ::worker/job-worker-error                    :error
    ::worker/polling-for-jobs                    :debug
    :proletarian.retry/not-retrying              :error
    :info))

(defn logger
  [x data]
  (log/logp (log-level x) x data))

(def email-worker
  (let [ds (jdbc/get-datasource "jdbc:postgresql://...")]
    (worker/create-queue-worker ds handlers/handle-job! {:proletarian/log logger})))
The log-level function acts as a dispatch table: exception-related events map to :error, polling maps to :debug, and everything else defaults to :info. Adjust the mappings to suit your monitoring and alerting requirements.
A reasonable starting mapping:
  • :error for ::worker/handle-job-exception, ::worker/handle-job-exception-with-interrupt, ::worker/job-worker-error, ::worker/queue-worker-shutdown-error, and :proletarian.retry/not-retrying — these represent failures that may require attention.
  • :debug for ::worker/polling-for-jobs — this fires frequently and is noise at :info level.
  • :info for everything else, including ::worker/handling-job, ::worker/job-finished, and :proletarian.retry/retrying.

Build docs developers (and LLMs) love