tutorial

Monitoring Axelor ERP with Vigilmon

Axelor is an open source Java ERP/CRM/BPM platform used by European SMEs and enterprises. This guide shows you how to monitor every critical layer — Tomcat, PostgreSQL, the REST API, Quartz jobs, BPM workflows, and JVM health — with Vigilmon.

Axelor Open Suite is a comprehensive open source ERP platform covering accounting, sales, purchasing, inventory, manufacturing, HR, CRM, and project management — all in a single Java application running on Apache Tomcat. For the SMEs and mid-market enterprises that rely on Axelor as their core business system, a failure in the ERP isn't a minor inconvenience: it stops invoicing, order processing, inventory management, and payroll in their tracks. Vigilmon gives you visibility into every critical Axelor layer, from Tomcat application health to Quartz batch jobs and PostgreSQL query latency.

What You'll Set Up

  • Axelor application (Tomcat) health monitoring
  • PostgreSQL database health and latency monitoring
  • Axelor REST API response time monitoring
  • Active user session monitoring
  • Quartz scheduler heartbeat monitoring
  • BPM (Camunda) workflow process health monitoring
  • Disk space monitoring for ERP attachments
  • JVM heap and GC health monitoring
  • Module load health verification
  • PostgreSQL backup success heartbeat

Prerequisites

  • Axelor Open Suite deployed on Apache Tomcat (typically 9.x or 10.x)
  • PostgreSQL as the database backend
  • Access to the server (SSH) to deploy health check scripts
  • A free Vigilmon account

Why Monitoring Axelor Is Critical

Axelor is the operational nervous system of the businesses that run it. Unlike a consumer web app where downtime means a bad user experience, Axelor downtime means:

  • Accountants can't enter invoices or close periods — financial reporting halts.
  • Sales staff can't create quotations or orders — revenue pipeline freezes.
  • Warehouse workers can't move stock — inventory goes untracked.
  • Quartz batch jobs fail silently — automated accounting closings, inventory valuations, and payroll calculations don't run.
  • BPM workflows stall — approval processes (purchase orders, leave requests, expense claims) are blocked, with no notification to users.

Vigilmon monitors each of these failure modes with checks that go deeper than "is the server running."


Step 1: Monitor Axelor Application Health

Axelor runs as a Java web application on Tomcat. The first monitor should verify that Tomcat is accepting HTTP requests and the Axelor application has started correctly.

Axelor exposes a built-in login page at the root URL. Use it as the application health signal:

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter your Axelor URL: https://erp.yourcompany.com/.
  4. Set Expected HTTP status to 200.
  5. Set Check interval to 1 minute.
  6. Enable Response body contains and enter Axelor (the login page title contains this string).
  7. Click Save.

For deeper application health, Axelor versions 6.x+ expose a management endpoint. If your deployment has it enabled:

GET https://erp.yourcompany.com/ws/public/app/info

This returns application version, module list, and server metadata. Add a Vigilmon monitor for this endpoint and check that it returns HTTP 200 — a failure here indicates Axelor has not fully initialized.


Step 2: Monitor PostgreSQL Database Health

All Axelor ERP data lives in PostgreSQL. Create a shell script health check to expose database connectivity over HTTP using a minimal Python or Node.js server:

#!/bin/bash
# /usr/local/bin/axelor-db-health.sh
# Returns 0 if PostgreSQL is healthy, 1 if not
psql -U axelor -d axelor -c "SELECT 1" -q -t 2>/dev/null | grep -q 1

Wrap this in a simple health endpoint using a lightweight HTTP responder. Here's a Python approach you can run as a systemd service:

#!/usr/bin/env python3
# /usr/local/bin/axelor-health-server.py
import subprocess, json
from http.server import HTTPServer, BaseHTTPRequestHandler

class HealthHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/health/db':
            result = subprocess.run(
                ['psql', '-U', 'axelor', '-d', 'axelor', '-c', 'SELECT 1', '-q', '-t'],
                capture_output=True, timeout=5
            )
            healthy = result.returncode == 0
            self.send_response(200 if healthy else 503)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            self.wfile.write(json.dumps({'db': 'ok' if healthy else 'error'}).encode())
        else:
            self.send_response(404)
            self.end_headers()

    def log_message(self, *args):
        pass  # suppress access logs

HTTPServer(('127.0.0.1', 9100), HealthHandler).serve_forever()

Run this as a systemd service on port 9100 (internal only), then expose specific paths via your nginx reverse proxy with IP restrictions. In Vigilmon:

  1. Add a monitor for https://erp.yourcompany.com/health/db.
  2. Set Expected HTTP status to 200.
  3. Set Check interval to 1 minute.

Step 3: Monitor Axelor REST API Response Time

Axelor's REST/JSON-RPC API is the interface between the AngularJS frontend and the Java backend. All ERP operations — opening a sales order, searching for a contact, computing an invoice — go through this API. Slow API responses mean a slow ERP experience for every user.

Monitor a lightweight API endpoint that exercises the full request path:

  1. In Vigilmon, add an HTTP / HTTPS monitor.
  2. URL: https://erp.yourcompany.com/ws/public/app/info.
  3. Set Check interval to 2 minutes.
  4. Set Response time alert at 3000 ms (3 seconds) — p95 API response time above 3s indicates a JVM or database problem.
  5. Set Expected HTTP status to 200.

For authenticated API checks (to test full ERP paths), use Vigilmon's Custom Headers feature to pass a valid API token, or create a read-only API user specifically for monitoring.


Step 4: Monitor Active User Sessions

Axelor's session capacity is limited by your Tomcat heap size and the server's CPU/memory. Monitoring active session count helps you detect unusual spikes (batch imports, a stuck process holding sessions open) before they cause OOM errors.

Extend the health server to query active sessions from PostgreSQL (Axelor stores session data in the database):

# Add to axelor-health-server.py
elif self.path == '/health/sessions':
    result = subprocess.run(
        ['psql', '-U', 'axelor', '-d', 'axelor', '-t', '-c',
         "SELECT COUNT(*) FROM auth_session WHERE expiry > NOW()"],
        capture_output=True, timeout=5
    )
    count = int(result.stdout.strip()) if result.returncode == 0 else -1
    # Alert if session count exceeds configured threshold
    THRESHOLD = int(os.environ.get('SESSION_ALERT_THRESHOLD', '100'))
    healthy = 0 <= count < THRESHOLD
    self.send_response(200 if healthy else 503)
    self.send_header('Content-Type', 'application/json')
    self.end_headers()
    self.wfile.write(json.dumps({'active_sessions': count}).encode())

Set SESSION_ALERT_THRESHOLD to your infrastructure's comfortable limit. In Vigilmon, add a monitor for /health/sessions and alert on non-200.


Step 5: Monitor Quartz Scheduler with Heartbeat Monitors

Axelor uses Quartz Scheduler for automated batch jobs: accounting period closings, inventory valuations, payroll calculations, and automated email sequences. A failed Quartz job causes silent business logic failures that may not surface for hours or days.

The most robust approach is to monitor each critical batch job with a Vigilmon heartbeat:

  1. In Vigilmon, click Add MonitorCron / Heartbeat.
  2. Name it Axelor Accounting Batch.
  3. Set Expected interval to match your job's schedule (e.g., 24 hours for a nightly accounting close).
  4. Copy the heartbeat URL.

Wrap your Quartz job to ping Vigilmon on successful completion. In Axelor's Groovy scripting or Java custom code:

// In your custom Quartz job class
@Override
protected void executeInContext(JobExecutionContext context, ActionRequest request, ActionResponse response) {
    try {
        // ... your batch job logic ...
        pingVigilmon(System.getenv("VIGILMON_BATCH_TOKEN"));
    } catch (Exception e) {
        log.error("Axelor batch job failed", e);
        throw e;
    }
}

private void pingVigilmon(String token) {
    if (token == null || token.isEmpty()) return;
    try {
        new URL("https://vigilmon.online/heartbeat/" + token).openConnection().getContent();
    } catch (Exception ignored) {}
}

Create a separate heartbeat monitor for each critical Quartz job. If the job fails or Quartz stops running, no ping arrives and Vigilmon alerts you.


Step 6: Monitor BPM Workflow Health

Axelor BPM (powered by Camunda) enables approval workflows: purchase order approvals, leave request chains, expense authorizations. A stuck workflow can block employees from getting approvals they need to do their work.

# Add to axelor-health-server.py — requires psql access to axelor DB
elif self.path == '/health/bpm':
    # Count workflow instances that haven't progressed in > 24 hours
    result = subprocess.run(
        ['psql', '-U', 'axelor', '-d', 'axelor', '-t', '-c', """
            SELECT COUNT(*) FROM wkf_instance
            WHERE status = 'started'
            AND updated_on < NOW() - INTERVAL '24 hours'
        """],
        capture_output=True, timeout=5
    )
    stuck = int(result.stdout.strip()) if result.returncode == 0 else -1
    healthy = stuck == 0
    self.send_response(200 if healthy else 503)
    self.send_header('Content-Type', 'application/json')
    self.end_headers()
    self.wfile.write(json.dumps({'bpm': 'ok' if healthy else 'degraded', 'stuck_processes': stuck}).encode())

In Vigilmon, add a monitor for /health/bpm with a 30-minute check interval. Alert when stuck processes appear — this indicates the BPM engine has crashed or a workflow is waiting for a resource that no longer exists.


Step 7: Monitor Disk Space for ERP Attachments

Axelor stores file attachments (invoices, contracts, documents, payslips) on disk. A full disk causes upload failures silently — users see an error, but the audit trail and document store are incomplete.

# Add to axelor-health-server.py
elif self.path == '/health/disk':
    import shutil
    attach_path = os.environ.get('AXELOR_ATTACHMENTS_PATH', '/opt/axelor/attachments')
    usage = shutil.disk_usage(attach_path)
    used_pct = round(usage.used / usage.total * 100, 1)
    healthy = used_pct < 80
    self.send_response(200 if healthy else 503)
    self.send_header('Content-Type', 'application/json')
    self.end_headers()
    self.wfile.write(json.dumps({
        'disk_used_pct': used_pct,
        'free_gb': round(usage.free / 1024**3, 1)
    }).encode())

Alert when disk usage exceeds 80% — this gives you time to archive old attachments or expand storage before upload failures begin.


Step 8: Monitor JVM Heap and GC Health

Axelor is a Java application, and JVM heap exhaustion causes erratic behavior (GC thrashing, OOM kills) before the application actually crashes. Monitor the JVM via JMX or via Tomcat's manager API:

Enable the Tomcat Manager application (restrict to localhost only):

<!-- conf/tomcat-users.xml -->
<role rolename="manager-jmx"/>
<user username="vigilmon" password="STRONG_RANDOM_PASSWORD" roles="manager-jmx"/>
# Add to axelor-health-server.py
elif self.path == '/health/jvm':
    import urllib.request, base64
    auth = base64.b64encode(b'vigilmon:STRONG_RANDOM_PASSWORD').decode()
    try:
        req = urllib.request.Request(
            'http://localhost:8080/manager/jmxproxy/?get=java.lang:type=Memory&att=HeapMemoryUsage',
            headers={'Authorization': f'Basic {auth}'}
        )
        data = urllib.request.urlopen(req, timeout=5).read().decode()
        # Parse "used" value from JMX response
        import re
        used = int(re.search(r'used=(\d+)', data).group(1))
        committed = int(re.search(r'committed=(\d+)', data).group(1))
        heap_pct = round(used / committed * 100, 1)
        healthy = heap_pct < 85
        self.send_response(200 if healthy else 503)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps({'heap_used_pct': heap_pct}).encode())
    except Exception as e:
        self.send_response(503)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps({'jvm': 'error', 'message': str(e)}).encode())

Alert when JVM heap usage exceeds 85% — prolonged high heap usage precedes GC thrashing and OOM errors.


Step 9: Monitor PostgreSQL Backup Success

Axelor contains your organization's financial records, customer data, and operational history. A failed backup that goes unnoticed is a disaster risk. Set up a heartbeat monitor:

  1. In Vigilmon, create a Cron / Heartbeat monitor named Axelor DB Backup.
  2. Set Expected interval to 25 hours (slightly more than daily, to absorb slight timing drift).
  3. Copy the heartbeat URL.

Add the ping to your backup script:

#!/bin/bash
# /usr/local/bin/axelor-backup.sh
BACKUP_DIR="/backups/axelor"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/axelor_$DATE.sql.gz"

mkdir -p "$BACKUP_DIR"
if pg_dump -U axelor axelor | gzip > "$BACKUP_FILE"; then
    # Verify the backup is non-empty
    if [ -s "$BACKUP_FILE" ]; then
        curl -fsS "https://vigilmon.online/heartbeat/YOUR_HEARTBEAT_TOKEN" > /dev/null
        # Rotate backups older than 7 days
        find "$BACKUP_DIR" -name "*.sql.gz" -mtime +7 -delete
    fi
fi

Schedule with cron:

0 2 * * * root /usr/local/bin/axelor-backup.sh

Vigilmon alerts if no ping arrives within 25 hours, meaning your backup either failed or was never triggered.


Recommended Alert Configuration

| Monitor | Alert Condition | Severity | |---|---|---| | Axelor application health | Non-200 or body missing Axelor | Critical | | PostgreSQL connectivity | Non-200 | Critical | | REST API response time | p95 > 3s | High | | Active session count | Approaching threshold | High | | Quartz batch heartbeat | Missed interval | Critical | | BPM stuck processes | > 0 stuck for 24h | High | | Disk space (attachments) | > 80% used | High | | JVM heap usage | > 85% | High | | PostgreSQL backup heartbeat | Missed 25h interval | Critical |


Conclusion

Axelor is mission-critical ERP software — when it fails, entire business functions stop. Vigilmon gives you proactive monitoring across the full Axelor stack: application availability, database health, API performance, Quartz batch jobs, BPM workflows, and the backup infrastructure that protects your data. With these monitors in place, you know about problems before they become business emergencies.

Start monitoring your Axelor ERP at vigilmon.online.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →