Skip to content

Introduce Metric service (for v12)#1396

Closed
vmitsenko wants to merge 1 commit into
masterfrom
feature/introduce_metrics_service_v12
Closed

Introduce Metric service (for v12)#1396
vmitsenko wants to merge 1 commit into
masterfrom
feature/introduce_metrics_service_v12

Conversation

@vmitsenko

Copy link
Copy Markdown
Collaborator

Introduce Metric service for v12

@vmitsenko vmitsenko requested a review from nicolasbisurgi May 8, 2026 14:00
nicolasbisurgi added a commit that referenced this pull request Jun 4, 2026
… v12 (#1411)

* feat: add Metrics service unifying model-performance stats across v11 and v12

Add `tm1.metrics`, exposing TM1 model-performance statistics with one method
per Stats Category (by_cube, by_server, by_rule, by_client, by_cube_by_client,
by_chore, by_process) that returns the same shape regardless of TM1 version.

- v11: reads the }Stats* control cubes via MDX/cellset.
- v12: reads the Metrics() OData endpoint plus the cube-bound rule-stats
  actions (start/stop/flush_collecting_rule_stats).

The v11/v12 branch is hidden inside each method. Gauge categories (by_cube,
by_server) return a long Metric/Value/Unit shape; entity categories return a
wide one-row-per-entity shape. Canonical metric names follow IBM's v12
vocabulary; units pass through unconverted with the source NativeName retained.

Logic lives in deep, server-free modules behind the service: vocabulary
(v11->canonical map), mdx (v11 query builder), odata_filter (v12 $filter,
extracted from #1396), shapers (raw payload -> records). 44 unit + 12
integration tests.

Supersedes #1396 — its Metrics() $filter logic and service wiring are
preserved here. Also adds Utils.datetime_to_iso and a max_version bound on
TM1pyVersionException (for v11-only categories invoked on v12).

* style: black-format datetime_to_iso

* refactor: align Metrics service with TM1py flat-module conventions

Collapse the TM1py/Metrics/ sub-package (vocabulary, mdx, odata_filter,
shapers) into TM1py/Services/MetricService.py as module-level helpers, matching
the single-flat-file pattern every other service follows. Consolidate the five
Metric*_test.py files into one Tests/MetricService_test.py per the
one-test-file-per-service convention. Fold usage examples into the service
docstring so they render in the auto-generated mkdocs API Reference. Remove ADR/
PRD references from docstrings and comments.

No behavior change: 44 unit tests pass; black and ruff clean.

* fix: by_rule reading is v11-only; v12 has no rule-stats read endpoint

Verified live on PA Database 12.5.9: start/stop/flush_collecting_rule_stats
return 204 but flush creates no }StatsByRule cube and exposes no rule-stats
OData entity ($metadata defines only the three lifecycle actions; Metrics()
carries no rule_* names). The previous claim that flush 'creates }StatsByRule
on demand' was false, and by_rule on v12 silently returned [] forever.

by_rule now raises NotImplementedError on v12 with a clear message; the v11
Performance-Monitor path is unchanged. Corrected the flush/by_rule docstrings
and the class usage example; split the lifecycle/by_rule integration tests to
assert the real behavior (lifecycle 204s, no cube created, by_rule raises).

* fix: by_rule reads }StatsByRule on v12 too (revert NotImplementedError)

Corrects the prior commit. On PA Database 12.5.9, flush_collected_rule_stats
DOES create/populate }StatsByRule — verified live: dims }Cubes x }LineNumber x
}RuleStats (identical to v11), and the existing v11 cellset read/shape path
returns correct records on v12. The cube appears only after the full sequence:
start_collecting_rule_stats -> change/exercise the rules -> wait ~60s sampling
interval -> flush_collected_rule_stats. My earlier probes skipped the rule
activity and the wait, so the cube hadn't materialized.

Restores the unified by_rule (read on both versions; [] + warning when the cube
is absent, with a v12-specific hint describing the collection sequence) and the
accurate flush docstring. Tests assert by_rule returns the list/shape on both
versions and the lifecycle returns 204s (cleanup only deletes }StatsByRule if
the test itself created it).

* feat: add performance-monitor controls to Metrics service (v11-only)

Mirror the Performance Monitor on/off/read controls onto MetricService,
delegating to ServerService, since the v11 }Stats* read paths depend on
the monitor running.

- ServerService: add get_performance_monitor_state(); guard start/stop/get
  with @deprecated_in_version("12.0.0") since PerformanceMonitorOn is a
  v11-only config parameter (previously start/stop silently ran on v12)
- MetricService: thin start_/stop_/get_performance_monitor_state delegates,
  same v12 guard; update by_rule hint + class docstring example
- Tests: v11 toggle round-trip, metrics<->server agreement, v12 raises

* fix: address PR #1411 review (datetime, version errors, cellset guards, tests)

- datetime_to_iso: convert tz-aware datetimes to UTC and preserve sub-second
  precision to milliseconds (was hard-coded .000Z, ignored tzinfo)
- MetricService: wire v12-only `since` Timestamp filter into by_cube/by_server
  (rejected on v11, symmetric to time_interval on v12)
- drop misleading required_version=V12 from v11-only version errors
  (max_version carries the meaning); document the deliberate split between
  version-gated reads (TM1pyVersionException) and deprecated perfmon mutators
- warn on truncated v11 cellsets (len(Cells) < axis product) instead of
  silently reading missing cells as None
- add context to bare KeyErrors (unknown measure / missing measure dimension)
- tests: mocked-REST dispatch + metrics= filtering + by_rule missing-cube
  warning (G1-G3), entity shapers for by_process/by_chore/by_client (G4),
  and datetime_to_iso tz/precision coverage
@nicolasbisurgi

Copy link
Copy Markdown
Collaborator

closed in favor of #1411

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