Monitor Pdftools OCR Service
You can monitor the OCR service programmatically using health check endpoints exposed by both the Manager and Worker components. To check the readiness status, you can trigger these endpoints:
- Manager:
http:/healthz/ready
- Worker:
http:/healthz/ready
Check log files to monitor the correct operation of the services. The path to the log files is configurable. Review Default appsettings.json for an example of the configured path to a log file.
Manager configuration overview
The OCR Service Manager uses appsettings.json files to manage its configuration. The following example shows a configuration for the Manager component, which also shows how it interacts with Workers.
The default path of the manager configuration file:
C:\Program Files\Pdftools\Pdftools OCR Service\PdftoolsOcrService\appsettings.json
Default appsettings.json
{
"Database": {
"DatabaseType": "SqlLite",
"DeleteJobsAfterDays": 2
},
"FileStorage": {
"FileStorageType": "HostFileSystem",
"FilesDirectoryPath": "C:/ProgramData/Pdftools/OcrService/Files",
"DeleteFilesAfterDays": 2
},
"ServiceCommunication": {
"ServiceCommunicationType": "Rest",
"ConnectionString": "http://localhost:7998/"
},
"PortNumber": 7982,
"MaxRequestBodySizeBytes": 104857600,
"LogFilePath": "C:/ProgramData/Pdftools/OcrService/logs/manager-log.txt",
"LogRetentionDays": 7
}
DatabaseDatabaseType: Database backend (for exampleSqlLiteorPostgreSql). If you usePostgreSql, also addConnectionString.ConnectionString: Connection string forPostgreSql; omitted in the default settings becauseSqlLitedoesn’t require a password.DeleteJobsAfterDays: Number of days after which completed job records are removed.JobPollingIntervalMs: The maximum interval, in milliseconds, between job-status checks while the manager waits for a blocking job to finish. The default is5000.
FileStorageFileStorageType: Storage backend (for exampleHostFileSystem).FilesDirectoryPath: Directory that stores OCR-processed files.DeleteFilesAfterDays: Number of days after which stored files are deleted.
ServiceCommunicationServiceCommunicationType: Method the manager uses to reach worker nodes (currentlyRest).ConnectionString: Endpoint URL of the worker node or load balancer.WorkerHttpTimeoutMinutes: How long, in minutes, the manager waits for a worker node to respond. The default is20.MaxConcurrentRequests: The maximum number of requests the manager sends to worker nodes at the same time. The default is10.SafetyTimeoutMinutes: How long, in minutes, a blocking request waits for a job to reach a final state. The default is120.
MaxRequestBodySizeBytes: Maximum number of bytes for the request size. Default is 104857600 bytes, approximately 100 MB. If necessary, increase this value for larger files.PortNumber: Port that the manager listens on; the default is7982.LogFilePath: Path to the log file.LogRetentionDays: Number of days to retain log files.
JobPollingIntervalMs, WorkerHttpTimeoutMinutes, MaxConcurrentRequests, and SafetyTimeoutMinutes are optional. To override a default, add JobPollingIntervalMs under Database and the other keys under ServiceCommunication in the manager appsettings.json file.
Worker configuration overview
The OCR Service Worker uses appsettings.json files to manage its configuration. The following example shows a configuration for the Worker node.
The following is the default path of the worker configuration file:
C:\Program Files\Pdftools\Pdftools OCR Service\PdftoolsOcrWorker\appsettings.json
Default appsettings.json
{
"PortNumber": 7998,
"LogFilePath": "C:/ProgramData/Pdftools/OcrService/logs/worker-log.txt",
"LogRetentionDays": 7,
"FileStorage": {
"FileStorageType": "HostFileSystem",
"FilesDirectoryPath": "C:/ProgramData/Pdftools/OcrService/Files"
},
"ServiceCommunication": {
"ServiceCommunicationType": "Rest"
},
"Licensing": {
"LicenseKey": "<LICENSE_KEY>",
"LgsURL": "http://localhost:9999"
}
}
PortNumber: Port used by the worker node for incoming requests, 7998 is the default in this case.LogFilePath: Path to the log file and the retention period for logs.LogRetentionDays: Retention period for logs.FileStorageFileStorageType: Storage system type (for exampleHostFileSystem).FilesDirectoryPath: Directory path for storing OCR-processed files.
ServiceCommunicationServiceCommunicationType: Communication method that reaches the worker (currentlyRest).
LicensingLicenseKey: Your Pdftools product key. Provide the license key in every worker that you set up.LgsURL: Your connection URL to the Licensing Gateway Service (LGS). An optional property. If you don’t specify theLgsURL, the Pdftools OCR Service automatically connects to the Pdftools Licensing Service, requiring an internet connection.
Engine processes
The worker runs OCR in separate engine processes. Each engine process handles one job at a time, so the number of engine processes is the number of jobs the worker runs in parallel. When the worker starts, it sets this number to the lowest of the following values, and always starts at least one engine process:
- One engine process per logical processor.
- A ceiling of 10 engine processes.
- One engine process per GB of memory, after the worker reserves 1 GB for itself and the operating system.
- The value of
MaxWorkerProcesses, if you set it. Refer toWorkerProcesssettings.
The memory value is the total memory of the host, not the free memory, and the worker doesn’t take other applications on the host into account. To leave memory and processors for other applications, set MaxWorkerProcesses. In a container with a memory limit, the worker can count less memory than the limit. For details, review Memory limit.
When the worker starts its engine processes, it logs their number and the limit that determined it. For example:
Worker capacity: 4 engine processes, limited by RAM. Logical processors 8 (ceiling 10), memory 5.9 GB (1 GB per engine, 1 GB reserved), configured maximum not set.
The limit is one of CPU, RAM, the ceiling, or configuration. If the line shows memory unknown, the worker couldn’t read the memory size and didn’t limit the number by memory.
WorkerProcess settings
The WorkerProcess settings control the worker’s engine processes. All settings are optional. The default appsettings.json file doesn’t contain a WorkerProcess section, so the worker uses the default values. To change a setting, add the section to the worker appsettings.json file, and then restart the worker. For example:
"WorkerProcess": {
"MaxWorkerProcesses": 4
}
MaxWorkerProcesses: The maximum number of engine processes. Not set by default. This setting can only lower the number that the worker calculates. If you set a higher value, the worker logs a warning and doesn’t apply it.StartupConfirmationTimeoutSeconds: How long, in seconds, the worker waits for each engine process to report that it started when the worker starts. If an engine process misses the timeout, the worker restarts it one time. The default is60. If the worker log showsdid not send startup confirmation within, raise this value. On Linux, also review systemd stops the worker during startup.RespawnStartupConfirmationTimeoutSeconds: How long, in seconds, the worker waits for an engine process that it restarts while running, for example after a crash. The default is60.WorkerResponseTimeoutSeconds: How long, in seconds, a single job can run in an engine process before the worker treats the engine process as unresponsive and restarts it. The default is300. Keep this value lower than the manager’sWorkerHttpTimeoutMinutes.
You can also set these values as environment variables, for example in Docker. Join the section and the setting with a double underscore, such as WorkerProcess__MaxWorkerProcesses=4. An environment variable overrides the value in appsettings.json. On Windows, prefer the appsettings.json file, because a Windows service reads a new system environment variable only after Windows restarts.
Manager settings that depend on the worker
With the default Rest communication type, the manager sends up to MaxConcurrentRequests jobs to the worker at the same time, 10 by default. It waits up to WorkerHttpTimeoutMinutes, 20 minutes by default, for each job. Jobs beyond the worker’s number of engine processes wait in the worker until an engine process is free, and that wait counts toward WorkerHttpTimeoutMinutes.
If a worker runs fewer than 10 engine processes and processes long multi-page documents, jobs can time out while they wait. In this case, in the manager appsettings.json file, set MaxConcurrentRequests to the worker’s number of engine processes, or raise WorkerHttpTimeoutMinutes. Refer to Manager configuration overview.
Manage the services on Linux
On a native Linux installation, the manager and worker run as systemd services.
Service control
To inspect or manage the running services, use these commands:
# Status
sudo systemctl status pdftools-ocr-service pdftools-ocr-worker
# Restart both (for example, after editing appsettings.json)
sudo systemctl restart pdftools-ocr-worker pdftools-ocr-service
# Stop (preserves on-disk state)
sudo systemctl stop pdftools-ocr-service pdftools-ocr-worker
# Disable boot-time start (enabled by default after install)
sudo systemctl disable pdftools-ocr-service pdftools-ocr-worker
Log locations
On a native Linux installation, the OCR Service writes logs to the following locations:
| Source | Location |
|---|---|
| Manager (structured) | /var/log/pdftools/manager-log.txt |
| Worker (structured) | /var/log/pdftools/worker-log.txt |
| systemd manager unit | journalctl -u pdftools-ocr-service |
| systemd worker unit | journalctl -u pdftools-ocr-worker |
Disk usage
Two paths grow over time:
| Path | Contents | Cleanup |
|---|---|---|
/var/lib/pdftools/files/ | Job inputs and intermediate state | Manager deletes entries after DeleteFilesAfterDays (default 2). |
/var/log/pdftools/ | Service logs | Rotated after LogRetentionDays (default 7). |
Manual cleanup is rarely needed because the manager runs a background sweep. If logs grow unexpectedly, inspect journalctl for an error loop.
Troubleshooting on Linux
These sections cover common install and runtime issues on a native Linux installation.
Package isn’t signed or GPG check failed (RPM)
The OCR Service package isn’t GPG-signed. Pass --nogpgcheck to bypass the check:
sudo dnf install --nogpgcheck ./pdftools-ocr-service-VERSION_NUMBER-1.x86_64.rpm
Install rejects with has not been validated on
The pre-install guard detected that your distribution isn’t in the validated set. To proceed, do one of the following:
- Use a validated distribution. Refer to Supported.
- If your distribution is listed under Likely supported, retry the install using the override in Install on a likely supported distribution).
- If your distribution is listed under Not supported, deploy Pdftools OCR Service in Docker instead.
Worker logs show Engine creation failed: NativeBase type initializer threw exception
The host is on EL9, Amazon Linux 2023, SLES 15, or another unsupported distribution. Pdftools OCR Service requires GLIBCXX_3.4.30 (GCC 12 or newer), which the host’s libstdc++ doesn’t provide. Switch to Docker or upgrade to a supported distribution.
Worker segfaults on start, or apt install rejects with a libxml2 dependency error
The host is on Ubuntu 25.10 or a future Debian release that bumped the libxml2 SONAME. The OCR plugin and worker binary both link libxml2.so.2, which isn’t available on these distributions. Switch to Docker.
License is not valid in worker logs
Check the following:
- The
LicenseKeyfield in/opt/pdftools/ocr-worker/appsettings.jsonisn’t still the"<LICENSE_KEY>"placeholder. - The host can reach the Pdftools licensing service, or your on-premises Licensing Gateway Service (
LgsURL) if configured. - The owner of
appsettings.jsonispdftools:pdftools. If you edited the file as root, restore ownership with:sudo chown pdftools:pdftools /opt/pdftools/ocr-worker/appsettings.json
If the licensing service doesn’t answer when the worker starts, for example after a reboot, the worker retries the license check. It retries after 5, 10, and 30 seconds, and then every minute, and each failed retry logs License check retry with the reason. The worker starts its engine processes as soon as the check succeeds, without a restart. The worker doesn’t retry a rejected license key: correct the key, and then restart the worker.
/healthz/ready returns Degraded indefinitely
The worker process is up, but the OCR engine probe hasn’t succeeded. Check /var/log/pdftools/worker-log.txt for the actual error. Common causes are an invalid license key, a missing license entitlement, or a network issue reaching the licensing service.
If the worker log shows License check retry, the worker can’t reach the licensing service yet and keeps retrying. The worker becomes ready after the license check succeeds and an engine process has started.
systemd stops the worker during startup
The worker’s systemd unit allows 300 seconds to start (TimeoutStartSec=300). Before the worker starts its engine processes, it checks its license, which can take up to 100 seconds if the licensing service doesn’t answer. Then it waits up to twice StartupConfirmationTimeoutSeconds for its engine processes. With the default of 60 seconds, the total fits within 300 seconds.
If you set StartupConfirmationTimeoutSeconds higher than about 100 seconds, also raise the unit’s start timeout. Set it to at least 100 seconds plus twice StartupConfirmationTimeoutSeconds, with a margin. Otherwise, systemd stops the worker during startup and restarts it repeatedly. To raise the start timeout, follow these steps:
- Open an override file for the worker unit:
sudo systemctl edit pdftools-ocr-worker
- In the editor, add the following lines, and then save the file:
[Service]TimeoutStartSec=600
- Restart the worker:
sudo systemctl restart pdftools-ocr-worker
Port 7982 or 7998 already in use
Identify the conflicting process:
sudo ss -ltnp | grep -E '7982|7998'
Stop the conflicting process, or change the PortNumber in the relevant appsettings.json.
Gather a support bundle
To collect diagnostics for a support ticket, run the commands for your package format. Each command appends to pdftools-support-bundle.txt.
RPM (Rocky, AlmaLinux, RHEL, Oracle Linux)
To gather the support bundle on an RPM-based system:
sudo journalctl -u pdftools-ocr-service -u pdftools-ocr-worker --no-pager -n 500 > pdftools-support-bundle.txt
sudo tail -n 500 /var/log/pdftools/manager-log.txt /var/log/pdftools/worker-log.txt >> pdftools-support-bundle.txt
rpm -q pdftools-ocr-service >> pdftools-support-bundle.txt
cat /etc/os-release >> pdftools-support-bundle.txt
free -h >> pdftools-support-bundle.txt
df -h /var/lib/pdftools /var/log/pdftools /opt/pdftools >> pdftools-support-bundle.txt
DEB (Ubuntu, Debian)
To gather the support bundle on a DEB-based system:
sudo journalctl -u pdftools-ocr-service -u pdftools-ocr-worker --no-pager -n 500 > pdftools-support-bundle.txt
sudo tail -n 500 /var/log/pdftools/manager-log.txt /var/log/pdftools/worker-log.txt >> pdftools-support-bundle.txt
dpkg -l pdftools-ocr-service >> pdftools-support-bundle.txt
cat /etc/os-release >> pdftools-support-bundle.txt
free -h >> pdftools-support-bundle.txt
df -h /var/lib/pdftools /var/log/pdftools /opt/pdftools >> pdftools-support-bundle.txt
Attach the resulting pdftools-support-bundle.txt to your support request, together with the exact error message you observed.
Troubleshooting HTTP errors
A request to the manager can fail with the following status codes:
-
400 Bad Requeston job submission: The request parameters failed validation. For example, fix an unknownPredefinedProfilevalue, an unsupported language, or a misspelled parameter name. The JSON response body names the rejected parameter. -
404 Not Foundon result retrieval: The job identifier is unknown, or the job has expired. The service deletes completed jobs after two days by default (Database.DeleteJobsAfterDays). -
500 Internal Server ErrorwithWorker communication error: The manager can’t reach the worker. Check that the worker is running and has a valid license key:- On Linux, inspect the worker log with
journalctl -u pdftools-ocr-workeror in/var/log/pdftools/. - In Docker, run
docker compose logs worker. - On Windows, check the
worker-logYYYYMMDD.txtfile inC:\ProgramData\Pdftools\OcrService\logs\.
While the worker is unreachable, the manager’s
/healthz/readyendpoint reportsDegraded. - On Linux, inspect the worker log with