pgwatch3 Gets Remote Sinks for Custom Metric Routing

PostgreSQL monitoring tool pgwatch3 is extending its storage flexibility with a new RPC-based remote sink mechanism, developed as part of the Google Summer of Code 2024 program. The feature lets users pipe metric measurements to any external system without modifying pgwatch3 itself.

The core idea follows the same storage abstraction that existed in pgwatch2: metrics are collected from a source database and written to a "sink," the designated storage unit. Until now, supported sinks were limited to PostgreSQL, JSON files, and Prometheus. Those cover the primary use cases, but leave little room for integrating measurements into bespoke pipelines or specialized data formats.

Remote sinks open that up by exposing an interface built on Go's standard RPC library. Instead of waiting for the pgwatch team to add each new output format on request, users can write their own sink type and stream measurements to it directly.

How It Works

The design keeps pgwatch3 agnostic about what happens at the receiving end. A remote sink is invoked via a single Remote Procedure Call, so no extra processing is required on the pgwatch side, and no changes are needed in the existing pgwatch3 setup. The user simply runs the remote sink server and pgwatch sends measurements to it.

From the architecture standpoint, there are three key takeaways:

  • Remote sinks are called via a single Remote Procedure Call, meaning no additional processing is required in pgwatch.
  • pgwatch does not care about the details of the remote sink implementation at the back end.
  • No additional changes are required in the pgwatch3 setup to use remote sinks.

To use a remote sink, you can simply run:

pgwatch --sink=rpc://somehost:42/foo ...

A development build with working examples is available on GitHub. The demo currently supports CSV and Parquet output formats, with more examples planned for future releases.

Building Your Own Sink

Developers who want to create a custom sink can clone the repository and add a new file under the sinks folder, naming it after the sink format they want to implement. The next step is declaring an enum for the new sink in sink/types.go and updating the conditional dispatch logic. The project intends to replace that manual step later with automatic call preparation based on the enum values.

During sink development, the primary_receiver instance passed into the UpdateMeasurement() function of your sink serves two purposes:

  • Retrieving metadata parameters associated with the Remote Procedure Call.
  • Receiving sync metric signals (such as "DELETE monitored database" or "ADD new metric") if the sink wants to support them.

A dummy client included in the repository can simulate pgwatch3 and generate requests for a newly developed sink, so testing doesn't require launching a full pgwatch instance. Contributors are encouraged to open pull requests if they think their sink will be useful to others; discussion and issue tracking happen in the project's GitHub section.