Which docs page
docs/functions-develop-metrics.md — "Use metrics to monitor functions".
What is missing
The page documents recordMetric / record_metric / RecordMetric for the three runtimes and stops there. That leaves out a capability Python functions already have, and it leaves the reader with no way to know that the runtimes differ.
A Python function can register arbitrary Prometheus collectors today, with no SDK change, because the instance serves prometheus_client's process-global registry:
# pulsar-functions/instance/src/main/python/prometheus_client_fix.py:50
def start_http_server(port, addr='', registry=core.REGISTRY):
# pulsar-functions/instance/src/main/python/python_instance_main.py:307 — called with the default
prometheus_client_fix.start_http_server(args.metrics_port)
ContextImpl registers its own summary into that same global by omitting the registry argument (contextimpl.py:67), and prometheus_client defaults every collector to core.REGISTRY. So this works and is scraped on the function's existing metrics port:
from prometheus_client import Counter
orders = Counter('my_orders_total', 'Orders processed', ['region'])
def process(input, context):
orders.labels(region='us-east').inc()
return input
That matters because record_metric only ever writes to a single summary, so counters, gauges, histograms and custom labels are otherwise unreachable. A user reading this page today would conclude none of that is possible.
Java and Go cannot do this. Both keep their registry private — Go's is an unexported package variable in pulsar-function-go/pf, and Java's FunctionCollectorRegistry is internal. Requests to expose them are open at apache/pulsar#26403 (Go) and apache/pulsar#24853 (Java). So this is a genuine per-runtime difference the page should state rather than leave the reader to infer.
Two caveats worth documenting alongside it
Both are reasons to be explicit rather than reasons to stay silent:
- It currently works by convention, not contract. Nothing declares that the instance serves the global registry, so today it could change without anyone considering it a breaking change. Documenting it is what turns it into a supported behaviour — which is the decision this issue is really asking for.
- Metric name collisions fail loudly. Registering a collector named
pulsar_function_user_metric, or anything else already registered, raises at registration time. Worth a sentence, and worth noting that the pulsar_function_ prefix is reserved.
A smaller inconsistency on the same page
Line 25 says custom metrics are available "for Java and Python functions"; line 27 then says "for Java, Python and Go functions" and the page includes a Go tab with a working RecordMetric example. Go does support RecordMetric, so line 25 is the wrong one.
Suggested resolution
Either:
Either is better than the current silence, which leaves a working capability undiscoverable and simultaneously unprotected from being removed by accident.
Happy to open the PR once there is a steer on which of the two is wanted — that is a maintainer's call rather than a docs detail.
Verified against apache/pulsar origin/master.
Which docs page
docs/functions-develop-metrics.md— "Use metrics to monitor functions".What is missing
The page documents
recordMetric/record_metric/RecordMetricfor the three runtimes and stops there. That leaves out a capability Python functions already have, and it leaves the reader with no way to know that the runtimes differ.A Python function can register arbitrary Prometheus collectors today, with no SDK change, because the instance serves
prometheus_client's process-global registry:ContextImplregisters its own summary into that same global by omitting theregistryargument (contextimpl.py:67), andprometheus_clientdefaults every collector tocore.REGISTRY. So this works and is scraped on the function's existing metrics port:That matters because
record_metriconly ever writes to a single summary, so counters, gauges, histograms and custom labels are otherwise unreachable. A user reading this page today would conclude none of that is possible.Java and Go cannot do this. Both keep their registry private — Go's is an unexported package variable in
pulsar-function-go/pf, and Java'sFunctionCollectorRegistryis internal. Requests to expose them are open at apache/pulsar#26403 (Go) and apache/pulsar#24853 (Java). So this is a genuine per-runtime difference the page should state rather than leave the reader to infer.Two caveats worth documenting alongside it
Both are reasons to be explicit rather than reasons to stay silent:
pulsar_function_user_metric, or anything else already registered, raises at registration time. Worth a sentence, and worth noting that thepulsar_function_prefix is reserved.A smaller inconsistency on the same page
Line 25 says custom metrics are available "for Java and Python functions"; line 27 then says "for Java, Python and Go functions" and the page includes a Go tab with a working
RecordMetricexample. Go does supportRecordMetric, so line 25 is the wrong one.Suggested resolution
Either:
Either is better than the current silence, which leaves a working capability undiscoverable and simultaneously unprotected from being removed by accident.
Happy to open the PR once there is a steer on which of the two is wanted — that is a maintainer's call rather than a docs detail.
Verified against
apache/pulsarorigin/master.