Skip to content

Conversation

@elizandropacheco
Copy link
Contributor

@elizandropacheco elizandropacheco commented Sep 16, 2025

Title

feat: add Prometheus-compatible /metrics endpoint (gated by PROMETHEUS_METRICS)

Description

This PR introduces a Prometheus-compatible metrics endpoint to expose runtime and instance-level insights for Evolution API. The endpoint is disabled by default and can be enabled via an environment flag.

What’s changed

  • Added a new GET /metrics route in src/api/routes/index.router.ts, conditionally registered when process.env.PROMETHEUS_METRICS === 'true'.
  • The endpoint outputs Prometheus 0.0.4 text format (text/plain) with a minimal, stable metric set:
    • evolution_environment_info{version,clientName,serverUrl} 1 — environment metadata
    • evolution_instances_total — number of instances currently tracked
    • evolution_instance_up{instance,integration} — 1 if state == "open", else 0
    • evolution_instance_state{instance,integration,state} — labeled gauge with the current state
  • The route uses waMonitor.waInstances (no auth required) so Prometheus can scrape it by default.

Why

  • Provide first-party observability without sidecars.
  • Enable dashboards/alerts around instance states (e.g., detect disconnections).
  • Expose environment metadata for troubleshooting and inventory.

How to use

  1. Set:
PROMETHEUS_METRICS=true
  1. Start the server and scrape:
GET /metrics
Content-Type: text/plain; version=0.0.4; charset=utf-8
  1. Create/connect instances to see:
  • evolution_instances_total increase
  • evolution_instance_up flip to 1 when an instance state is open

Example output

# HELP evolution_environment_info Environment information
# TYPE evolution_environment_info gauge
evolution_environment_info{version="2.3.2",clientName="evolution_exchange",serverUrl="http://localhost:8080"} 1
# HELP evolution_instances_total Total number of instances
# TYPE evolution_instances_total gauge
evolution_instances_total 3
# HELP evolution_instance_up 1 if instance state is open, else 0
# TYPE evolution_instance_up gauge
# HELP evolution_instance_state Instance state as a labelled metric
# TYPE evolution_instance_state gauge
evolution_instance_up{instance="demo-1",integration="WHATSAPP-BAILEYS"} 0
evolution_instance_state{instance="demo-1",integration="WHATSAPP-BAILEYS",state="close"} 1

Notes

  • Auth is intentionally not required for Prometheus scraping. A follow-up PR can add optional guards or an allowlist.
  • Metric set is intentionally small and stable to avoid cardinality spikes; can be extended later.

Files changed

  • src/api/routes/index.router.ts

Checklist

  • Conditional registration via PROMETHEUS_METRICS
  • Prometheus 0.0.4 text output
  • Instance state reflected per instance/integration labels
  • README/CHANGELOG mention (if maintainers prefer)
  • Optional tests (enabled/disabled paths)

Summary by Sourcery

Add an optional Prometheus metrics endpoint for environment and instance-level insights, and adjust the deployment setup with a dedicated Dockerfile and updated docker-compose configuration.

New Features:

  • Expose a Prometheus-compatible /metrics endpoint gated by the PROMETHEUS_METRICS environment flag
  • Emit environment metadata, total instances, and per-instance up/state gauges in Prometheus text format

Build:

  • Introduce Dockerfile.metrics and update docker-compose to use the evolution/api:metrics image

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Sep 16, 2025

Reviewer's Guide

This PR adds a conditional Prometheus-compatible /metrics endpoint that streams environment and instance-level gauges in text format and updates the Docker setup to build and deploy a metrics‐enabled image.

Sequence diagram for conditional /metrics endpoint registration and response

sequenceDiagram
participant Env as "process.env"
participant Router as "Express Router"
participant Prometheus as "Prometheus Scraper"
participant Server as "API Server"
participant waMonitor as "waMonitor"

Env->>Router: PROMETHEUS_METRICS === 'true'
Router->>Server: Register GET /metrics route
Prometheus->>Server: GET /metrics
Server->>waMonitor: Read waInstances
Server->>Prometheus: Return metrics text (environment info, instances, states)
Loading

File-Level Changes

Change Details Files
Introduce conditional Prometheus /metrics route
  • Wrap route registration in PROMETHEUS_METRICS check
  • Set Content-Type and Cache-Control headers for Prometheus format
  • Implement escapeLabel utility to sanitize metric labels
  • Assemble and send text/plain 0.0.4 metrics for environment info, total instances, and per-instance state
src/api/routes/index.router.ts
Update Docker configuration for metrics image
  • Change service image to metrics-enabled tag
  • Add Dockerfile.metrics to build the metrics image
docker-compose.yaml
Dockerfile.metrics

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Consider using a Prometheus client library (e.g., prom-client) instead of manually assembling metric strings for better maintainability and safety.
  • Move the metrics formatting and escapeLabel logic into a separate module or service so the router remains focused on request handling.
  • Pull static metrics definitions (HELP/TYPE lines and escapeLabel helper) out of the handler to avoid recreating them on every scrape.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider using a Prometheus client library (e.g., prom-client) instead of manually assembling metric strings for better maintainability and safety.
- Move the metrics formatting and escapeLabel logic into a separate module or service so the router remains focused on request handling.
- Pull static metrics definitions (HELP/TYPE lines and escapeLabel helper) out of the handler to avoid recreating them on every scrape.

## Individual Comments

### Comment 1
<location> `src/api/routes/index.router.ts:60` </location>
<code_context>
+
+    const lines: string[] = [];
+
+    const clientName = process.env.DATABASE_CONNECTION_CLIENT_NAME || '';
+    const serverUrl = serverConfig.URL || '';
+
</code_context>

<issue_to_address>
**suggestion:** Defaulting to empty string for clientName may obscure missing configuration.

Using an empty string may hide configuration problems in metrics. A sentinel value like 'unknown' would make missing configuration clearer in Prometheus.

```suggestion
    const clientName = process.env.DATABASE_CONNECTION_CLIENT_NAME || 'unknown';
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@DavidsonGomes
Copy link
Collaborator

Please, fix the lint with npm run lint

@elizandropacheco
Copy link
Contributor Author

Fixed

@DavidsonGomes DavidsonGomes merged commit e75dae3 into EvolutionAPI:develop Sep 17, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants