Skip to content

pcp2openmetrics: add live timestamp mode#2637

Open
lmchilton wants to merge 1 commit into
performancecopilot:mainfrom
lmchilton:pcp2openmetrics-timestamps
Open

pcp2openmetrics: add live timestamp mode#2637
lmchilton wants to merge 1 commit into
performancecopilot:mainfrom
lmchilton:pcp2openmetrics-timestamps

Conversation

@lmchilton

Copy link
Copy Markdown
Contributor

update pcp2openmetrics tool to allow for live timestamp mode option. This update follows openmetric / prometheus exposing timestamp guidelines. Updated man page & QA #1131

Resolves issue #2538

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added live timestamp mode for pcp2openmetrics (-l / --times); when enabled, emitted OpenMetrics samples in live mode include explicit sample timestamps.
  • Bug Fixes
    • Improved OpenMetrics output normalization by refining how placeholder tokens are rewritten during filtering.
  • Documentation
    • Updated the pcp2openmetrics manpage to describe the new --times / -l option (“Live timestamp mode”).
  • Tests
    • Extended the QA flow with an additional pcp2openmetrics -s2 --times … run to validate live timestamp output and the updated normalization.

Walkthrough

pcp2openmetrics now accepts -l/--times for live timestamp output. The manpage documents the option, and QA normalization plus an added test invocation were updated for the new output.

Changes

Live timestamp mode

Layer / File(s) Summary
CLI option and docs
src/pcp2openmetrics/pcp2openmetrics.py, src/pcp2openmetrics/pcp2openmetrics.1
Recognizes times, adds -l/--times, and documents live timestamp mode in the manpage.
Live timestamp output
src/pcp2openmetrics/pcp2openmetrics.py
Includes timestamps in live OpenMetrics output when time_stamp is enabled.
QA normalization and test
qa/1131
Updates the OpenMetrics filter placeholders and adds a pcp2openmetrics -s2 --times hinv.ncpu test run.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Parser as pcp2openmetrics.py option parser
  participant Writer as PCP2OPENMETRICS.write_openmetrics()
  participant Output as OpenMetrics output
  User->>Parser: run with -l / --times
  Parser->>Writer: set self.time_stamp = 1
  Writer->>Output: emit sample lines with timestamps
Loading

Poem

I hopped through counters, brisk and keen,
and found a -l in the machine.
Now live outputs softly gleam,
with timestamp sparkles in the stream.
🐇

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding live timestamp mode to pcp2openmetrics.
Description check ✅ Passed The description is clearly related to the changeset and mentions the live timestamp mode, man page, and QA updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pcp2openmetrics/pcp2openmetrics.1`:
- Around line 421-425: The SYNOPSIS short-option cluster is missing the newly
documented lowercase l option, so update the synopsis in pcp2openmetrics.1 to
match the documented command-line options. Keep the short-option list consistent
with the `-l, --time-stamp` entry by adding `l` in the compact options section
so users can discover it from the top-level usage summary.

In `@src/pcp2openmetrics/pcp2openmetrics.py`:
- Around line 142-146: The counter timestamp cache in pcp2openmetrics.py can
grow without bound because counter_timestamps only ever adds new (metric_name,
instance_id) keys. Update the live-mode counter handling paths around the
related metric processing code (including the sections near the referenced
counter-timestamp logic) to evict stale entries when instances disappear or are
no longer observed. Use the existing counter_timestamps structure as the cleanup
point so long-running exporter stability is preserved.
- Around line 58-59: The self.keys list in pcp2openmetrics.py has a missing
separator between the time_stamp and count_scale entries, causing those config
directives to merge into one invalid key. Update the list in the initialization
block where self.keys is defined so time_stamp and count_scale are separate
elements, preserving recognition of both directives.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: c37c1883-be10-4564-8af4-8c0dd5fd28c9

📥 Commits

Reviewing files that changed from the base of the PR and between 3d1a65d and 371f9c2.

⛔ Files ignored due to path filters (1)
  • qa/1131.out is excluded by !**/*.out
📒 Files selected for processing (3)
  • qa/1131
  • src/pcp2openmetrics/pcp2openmetrics.1
  • src/pcp2openmetrics/pcp2openmetrics.py

Comment thread src/pcp2openmetrics/pcp2openmetrics.1 Outdated
Comment thread src/pcp2openmetrics/pcp2openmetrics.py Outdated
Comment thread src/pcp2openmetrics/pcp2openmetrics.py Outdated
Comment on lines +142 to +146
# Counter metric timestamp tracking
# key - (metric_name, instance_id)
# value - timestamp when first seen
self.counter_timestamps = {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

Prevent unbounded growth of counter_timestamps in long-running live mode.

self.counter_timestamps only adds keys and never removes stale (metric, inst) entries. With high instance churn, this can grow indefinitely and degrade long-lived exporter stability.

Also applies to: 509-513, 520-523

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pcp2openmetrics/pcp2openmetrics.py` around lines 142 - 146, The counter
timestamp cache in pcp2openmetrics.py can grow without bound because
counter_timestamps only ever adds new (metric_name, instance_id) keys. Update
the live-mode counter handling paths around the related metric processing code
(including the sections near the referenced counter-timestamp logic) to evict
stale entries when instances disappear or are no longer observed. Use the
existing counter_timestamps structure as the cleanup point so long-running
exporter stability is preserved.

@lmchilton lmchilton force-pushed the pcp2openmetrics-timestamps branch from 371f9c2 to bcc4cc6 Compare June 25, 2026 17:32
Comment thread src/pcp2openmetrics/pcp2openmetrics.py Outdated
if self.time_stamp and openmetrics_type(desc) == "counter":
counter_key = (metric, inst)
creation_ts = self.counter_timestamps.get(counter_key, ts)
body += '%s%s %s\n' % (openmetrics_name_ts, openmetrics_labels(inst, name, desc, labels), creation_ts)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think its incorrect to expose timestamps for counter metrics only here - we should treat live mode the same as archive (a few lines above) in this regard, and export the timestamp for the sample (as per the v1 OM spec, and as we always have).

The "_created" lines are indeed intended for counters only, re-reading the spec(s). They could be applicable to both archive and live PCP values, however, looking at our code - and in particular the fetchgroup code behind the python API - these are not going to be handled correctly (there is no knowledge of "mark" records in src/libpcp/src/fetchgroup.c which is the code being used by pmconfig.py and in turn by pcp2openmetrics.py). We should ignore the _created timestamp, its not ever going to be correctly handled here.

Finally, the PMWEBAPI(3) uses the parameter name "times" to enable these timestamps - could we mirror that here? i.e. instead of --time_stamp lets use --times? (and this should remain the default in archive mode).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@natoscott thank you for the clarification! I updated everything

update pcp2openmetrics tool to allow for live timestamp
mode option. This update follows openmetric / prometheus
exposing timestamp guidelines. Updated man page & QA performancecopilot#1131

Resolves upstream RFE issue [performancecopilot#2538]
@lmchilton lmchilton force-pushed the pcp2openmetrics-timestamps branch from bcc4cc6 to 3e0d882 Compare June 30, 2026 15:42

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@qa/1131`:
- Around line 107-108: The new QA case uses pcp2openmetrics with only -s2, which
still falls back to the tool’s default 10-second interval and slows the test.
Update the command in this test case to pass an explicit short time interval
with pcp2openmetrics so the assertion remains fast while preserving coverage;
locate the change in the qa/1131 test around the pcp2openmetrics invocation.

In `@src/pcp2openmetrics/pcp2openmetrics.py`:
- Line 204: The `--times` option help text in `pmSetLongOption` is misleading
because the implementation in `pcp2openmetrics.py` only appends a sample
timestamp to emitted series rather than adding a new metric. Update the
`--times` description to reflect the actual behavior, and keep the wording
aligned with the logic used later when timestamps are emitted so users
understand what the flag does.
- Line 58: The config option handling in the pcp2openmetrics parser is wired to
the wrong runtime field, so `times=yes` never affects output. Update the option
mapping in the config parsing logic around the `times` entry so it sets
`self.time_stamp` (or rename the runtime flag consistently), and verify the
output gating that reads `self.time_stamp` now reflects the
`pcp2openmetrics.conf` setting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: b8a86648-056d-4fd0-9d75-45cbdadeebdb

📥 Commits

Reviewing files that changed from the base of the PR and between bcc4cc6 and 3e0d882.

⛔ Files ignored due to path filters (1)
  • qa/1131.out is excluded by !**/*.out
📒 Files selected for processing (3)
  • qa/1131
  • src/pcp2openmetrics/pcp2openmetrics.1
  • src/pcp2openmetrics/pcp2openmetrics.py

Comment thread qa/1131
Comment on lines +107 to +108
echo "--- pcp2openmetrics -s2 --times hinv.ncpu"
pcp2openmetrics -s2 --times hinv.ncpu | _filter_pcp2openmetrics

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Avoid the default 10-second sleep in this new QA case.

-s2 here inherits the tool's default interval, so this single assertion adds about 10 seconds to the test run. Passing an explicit short -t keeps the regression fast without weakening coverage.

Minimal fix
-echo "--- pcp2openmetrics -s2 --times hinv.ncpu"
-pcp2openmetrics -s2 --times hinv.ncpu | _filter_pcp2openmetrics
+echo "--- pcp2openmetrics -s2 -t1 --times hinv.ncpu"
+pcp2openmetrics -s2 -t1 --times hinv.ncpu | _filter_pcp2openmetrics
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
echo "--- pcp2openmetrics -s2 --times hinv.ncpu"
pcp2openmetrics -s2 --times hinv.ncpu | _filter_pcp2openmetrics
echo "--- pcp2openmetrics -s2 -t1 --times hinv.ncpu"
pcp2openmetrics -s2 -t1 --times hinv.ncpu | _filter_pcp2openmetrics
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qa/1131` around lines 107 - 108, The new QA case uses pcp2openmetrics with
only -s2, which still falls back to the tool’s default 10-second interval and
slows the test. Update the command in this test case to pass an explicit short
time interval with pcp2openmetrics so the assertion remains fast while
preserving coverage; locate the change in the qa/1131 test around the
pcp2openmetrics invocation.

self.keys = ('source', 'output', 'derived', 'globals',
'samples', 'interval', 'precision', 'daemonize',
'timefmt', 'everything',
'timefmt', 'everything', 'times',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

pmconfig_file="$(fd -i '^pmconfig\.py$' . src | head -n1)"
echo "Inspecting: ${pmconfig_file}"

rg -n -C3 'def read_options|setattr|times|time_stamp' "$pmconfig_file" \
  src/pcp2openmetrics/pcp2openmetrics.py

Repository: performancecopilot/pcp

Length of output: 8199


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '150,240p' src/python/pcp/pmconfig.py
printf '\n---\n'
sed -n '1,140p' src/pcp2openmetrics/pcp2openmetrics.py
printf '\n---\n'
sed -n '160,245p' src/pcp2openmetrics/pcp2openmetrics.py

Repository: performancecopilot/pcp

Length of output: 14180


Map the config option to time_stamp
times=yes in pcp2openmetrics.conf is parsed onto self.times, but output is gated by self.time_stamp, so the config key never changes behavior. Map this option to the runtime flag (or rename the flag to match).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pcp2openmetrics/pcp2openmetrics.py` at line 58, The config option
handling in the pcp2openmetrics parser is wired to the wrong runtime field, so
`times=yes` never affects output. Update the option mapping in the config
parsing logic around the `times` entry so it sets `self.time_stamp` (or rename
the runtime flag consistently), and verify the output gating that reads
`self.time_stamp` now reflects the `pcp2openmetrics.conf` setting.

opts.pmSetLongOption("space-scale-force", 1, "B", "SCALE", "forced space unit")
opts.pmSetLongOption("time-scale", 1, "y", "SCALE", "default time unit")
opts.pmSetLongOption("time-scale-force", 1, "Y", "SCALE", "forced time unit")
opts.pmSetLongOption("times", 0, "l", "", "addition of timestamp gauge metric")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make the --times help text match the implementation.

This option does not add a new “timestamp gauge metric”; Line 505 appends a sample timestamp to emitted series. The current --help text will send users looking for a metric that never appears.

Suggested wording
-        opts.pmSetLongOption("times", 0, "l", "", "addition of timestamp gauge metric")
+        opts.pmSetLongOption("times", 0, "l", "", "append sample timestamps to live output")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
opts.pmSetLongOption("times", 0, "l", "", "addition of timestamp gauge metric")
opts.pmSetLongOption("times", 0, "l", "", "append sample timestamps to live output")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pcp2openmetrics/pcp2openmetrics.py` at line 204, The `--times` option
help text in `pmSetLongOption` is misleading because the implementation in
`pcp2openmetrics.py` only appends a sample timestamp to emitted series rather
than adding a new metric. Update the `--times` description to reflect the actual
behavior, and keep the wording aligned with the logic used later when timestamps
are emitted so users understand what the flag does.

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