tnfr 4.5.2__py3-none-any.whl → 8.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tnfr might be problematic. Click here for more details.
- tnfr/__init__.py +334 -50
- tnfr/__init__.pyi +33 -0
- tnfr/_compat.py +10 -0
- tnfr/_generated_version.py +34 -0
- tnfr/_version.py +49 -0
- tnfr/_version.pyi +7 -0
- tnfr/alias.py +214 -37
- tnfr/alias.pyi +108 -0
- tnfr/backends/__init__.py +354 -0
- tnfr/backends/jax_backend.py +173 -0
- tnfr/backends/numpy_backend.py +238 -0
- tnfr/backends/optimized_numpy.py +420 -0
- tnfr/backends/torch_backend.py +408 -0
- tnfr/cache.py +149 -556
- tnfr/cache.pyi +13 -0
- tnfr/cli/__init__.py +51 -16
- tnfr/cli/__init__.pyi +26 -0
- tnfr/cli/arguments.py +344 -32
- tnfr/cli/arguments.pyi +29 -0
- tnfr/cli/execution.py +676 -50
- tnfr/cli/execution.pyi +70 -0
- tnfr/cli/interactive_validator.py +614 -0
- tnfr/cli/utils.py +18 -3
- tnfr/cli/utils.pyi +7 -0
- tnfr/cli/validate.py +236 -0
- tnfr/compat/__init__.py +85 -0
- tnfr/compat/dataclass.py +136 -0
- tnfr/compat/jsonschema_stub.py +61 -0
- tnfr/compat/matplotlib_stub.py +73 -0
- tnfr/compat/numpy_stub.py +155 -0
- tnfr/config/__init__.py +224 -0
- tnfr/config/__init__.pyi +10 -0
- tnfr/{constants_glyphs.py → config/constants.py} +26 -20
- tnfr/config/constants.pyi +12 -0
- tnfr/config/defaults.py +54 -0
- tnfr/{constants/core.py → config/defaults_core.py} +59 -6
- tnfr/config/defaults_init.py +33 -0
- tnfr/config/defaults_metric.py +104 -0
- tnfr/config/feature_flags.py +81 -0
- tnfr/config/feature_flags.pyi +16 -0
- tnfr/config/glyph_constants.py +31 -0
- tnfr/config/init.py +77 -0
- tnfr/config/init.pyi +8 -0
- tnfr/config/operator_names.py +254 -0
- tnfr/config/operator_names.pyi +36 -0
- tnfr/config/physics_derivation.py +354 -0
- tnfr/config/presets.py +83 -0
- tnfr/config/presets.pyi +7 -0
- tnfr/config/security.py +927 -0
- tnfr/config/thresholds.py +114 -0
- tnfr/config/tnfr_config.py +498 -0
- tnfr/constants/__init__.py +51 -133
- tnfr/constants/__init__.pyi +92 -0
- tnfr/constants/aliases.py +33 -0
- tnfr/constants/aliases.pyi +27 -0
- tnfr/constants/init.py +3 -1
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +9 -15
- tnfr/constants/metric.pyi +19 -0
- tnfr/core/__init__.py +33 -0
- tnfr/core/container.py +226 -0
- tnfr/core/default_implementations.py +329 -0
- tnfr/core/interfaces.py +279 -0
- tnfr/dynamics/__init__.py +213 -633
- tnfr/dynamics/__init__.pyi +83 -0
- tnfr/dynamics/adaptation.py +267 -0
- tnfr/dynamics/adaptation.pyi +7 -0
- tnfr/dynamics/adaptive_sequences.py +189 -0
- tnfr/dynamics/adaptive_sequences.pyi +14 -0
- tnfr/dynamics/aliases.py +23 -0
- tnfr/dynamics/aliases.pyi +19 -0
- tnfr/dynamics/bifurcation.py +232 -0
- tnfr/dynamics/canonical.py +229 -0
- tnfr/dynamics/canonical.pyi +48 -0
- tnfr/dynamics/coordination.py +385 -0
- tnfr/dynamics/coordination.pyi +25 -0
- tnfr/dynamics/dnfr.py +2699 -398
- tnfr/dynamics/dnfr.pyi +26 -0
- tnfr/dynamics/dynamic_limits.py +225 -0
- tnfr/dynamics/feedback.py +252 -0
- tnfr/dynamics/feedback.pyi +24 -0
- tnfr/dynamics/fused_dnfr.py +454 -0
- tnfr/dynamics/homeostasis.py +157 -0
- tnfr/dynamics/homeostasis.pyi +14 -0
- tnfr/dynamics/integrators.py +496 -102
- tnfr/dynamics/integrators.pyi +36 -0
- tnfr/dynamics/learning.py +310 -0
- tnfr/dynamics/learning.pyi +33 -0
- tnfr/dynamics/metabolism.py +254 -0
- tnfr/dynamics/nbody.py +796 -0
- tnfr/dynamics/nbody_tnfr.py +783 -0
- tnfr/dynamics/propagation.py +326 -0
- tnfr/dynamics/runtime.py +908 -0
- tnfr/dynamics/runtime.pyi +77 -0
- tnfr/dynamics/sampling.py +10 -5
- tnfr/dynamics/sampling.pyi +7 -0
- tnfr/dynamics/selectors.py +711 -0
- tnfr/dynamics/selectors.pyi +85 -0
- tnfr/dynamics/structural_clip.py +207 -0
- tnfr/errors/__init__.py +37 -0
- tnfr/errors/contextual.py +492 -0
- tnfr/execution.py +77 -55
- tnfr/execution.pyi +45 -0
- tnfr/extensions/__init__.py +205 -0
- tnfr/extensions/__init__.pyi +18 -0
- tnfr/extensions/base.py +173 -0
- tnfr/extensions/base.pyi +35 -0
- tnfr/extensions/business/__init__.py +71 -0
- tnfr/extensions/business/__init__.pyi +11 -0
- tnfr/extensions/business/cookbook.py +88 -0
- tnfr/extensions/business/cookbook.pyi +8 -0
- tnfr/extensions/business/health_analyzers.py +202 -0
- tnfr/extensions/business/health_analyzers.pyi +9 -0
- tnfr/extensions/business/patterns.py +183 -0
- tnfr/extensions/business/patterns.pyi +8 -0
- tnfr/extensions/medical/__init__.py +73 -0
- tnfr/extensions/medical/__init__.pyi +11 -0
- tnfr/extensions/medical/cookbook.py +88 -0
- tnfr/extensions/medical/cookbook.pyi +8 -0
- tnfr/extensions/medical/health_analyzers.py +181 -0
- tnfr/extensions/medical/health_analyzers.pyi +9 -0
- tnfr/extensions/medical/patterns.py +163 -0
- tnfr/extensions/medical/patterns.pyi +8 -0
- tnfr/flatten.py +29 -50
- tnfr/flatten.pyi +21 -0
- tnfr/gamma.py +66 -53
- tnfr/gamma.pyi +36 -0
- tnfr/glyph_history.py +144 -57
- tnfr/glyph_history.pyi +35 -0
- tnfr/glyph_runtime.py +19 -0
- tnfr/glyph_runtime.pyi +8 -0
- tnfr/immutable.py +70 -30
- tnfr/immutable.pyi +36 -0
- tnfr/initialization.py +22 -16
- tnfr/initialization.pyi +65 -0
- tnfr/io.py +5 -241
- tnfr/io.pyi +13 -0
- tnfr/locking.pyi +7 -0
- tnfr/mathematics/__init__.py +79 -0
- tnfr/mathematics/backend.py +453 -0
- tnfr/mathematics/backend.pyi +99 -0
- tnfr/mathematics/dynamics.py +408 -0
- tnfr/mathematics/dynamics.pyi +90 -0
- tnfr/mathematics/epi.py +391 -0
- tnfr/mathematics/epi.pyi +65 -0
- tnfr/mathematics/generators.py +242 -0
- tnfr/mathematics/generators.pyi +29 -0
- tnfr/mathematics/metrics.py +119 -0
- tnfr/mathematics/metrics.pyi +16 -0
- tnfr/mathematics/operators.py +239 -0
- tnfr/mathematics/operators.pyi +59 -0
- tnfr/mathematics/operators_factory.py +124 -0
- tnfr/mathematics/operators_factory.pyi +11 -0
- tnfr/mathematics/projection.py +87 -0
- tnfr/mathematics/projection.pyi +33 -0
- tnfr/mathematics/runtime.py +182 -0
- tnfr/mathematics/runtime.pyi +64 -0
- tnfr/mathematics/spaces.py +256 -0
- tnfr/mathematics/spaces.pyi +83 -0
- tnfr/mathematics/transforms.py +305 -0
- tnfr/mathematics/transforms.pyi +62 -0
- tnfr/metrics/__init__.py +47 -9
- tnfr/metrics/__init__.pyi +20 -0
- tnfr/metrics/buffer_cache.py +163 -0
- tnfr/metrics/buffer_cache.pyi +24 -0
- tnfr/metrics/cache_utils.py +214 -0
- tnfr/metrics/coherence.py +1510 -330
- tnfr/metrics/coherence.pyi +129 -0
- tnfr/metrics/common.py +23 -16
- tnfr/metrics/common.pyi +35 -0
- tnfr/metrics/core.py +251 -36
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +709 -110
- tnfr/metrics/diagnosis.pyi +86 -0
- tnfr/metrics/emergence.py +245 -0
- tnfr/metrics/export.py +60 -18
- tnfr/metrics/export.pyi +7 -0
- tnfr/metrics/glyph_timing.py +233 -43
- tnfr/metrics/glyph_timing.pyi +81 -0
- tnfr/metrics/learning_metrics.py +280 -0
- tnfr/metrics/learning_metrics.pyi +21 -0
- tnfr/metrics/phase_coherence.py +351 -0
- tnfr/metrics/phase_compatibility.py +349 -0
- tnfr/metrics/reporting.py +63 -28
- tnfr/metrics/reporting.pyi +25 -0
- tnfr/metrics/sense_index.py +1126 -43
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +215 -23
- tnfr/metrics/trig.pyi +13 -0
- tnfr/metrics/trig_cache.py +148 -24
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/multiscale/__init__.py +32 -0
- tnfr/multiscale/hierarchical.py +517 -0
- tnfr/node.py +646 -140
- tnfr/node.pyi +139 -0
- tnfr/observers.py +160 -45
- tnfr/observers.pyi +31 -0
- tnfr/ontosim.py +23 -19
- tnfr/ontosim.pyi +28 -0
- tnfr/operators/__init__.py +1358 -106
- tnfr/operators/__init__.pyi +31 -0
- tnfr/operators/algebra.py +277 -0
- tnfr/operators/canonical_patterns.py +420 -0
- tnfr/operators/cascade.py +267 -0
- tnfr/operators/cycle_detection.py +358 -0
- tnfr/operators/definitions.py +4108 -0
- tnfr/operators/definitions.pyi +78 -0
- tnfr/operators/grammar.py +1164 -0
- tnfr/operators/grammar.pyi +140 -0
- tnfr/operators/hamiltonian.py +710 -0
- tnfr/operators/health_analyzer.py +809 -0
- tnfr/operators/jitter.py +107 -38
- tnfr/operators/jitter.pyi +11 -0
- tnfr/operators/lifecycle.py +314 -0
- tnfr/operators/metabolism.py +618 -0
- tnfr/operators/metrics.py +2138 -0
- tnfr/operators/network_analysis/__init__.py +27 -0
- tnfr/operators/network_analysis/source_detection.py +186 -0
- tnfr/operators/nodal_equation.py +395 -0
- tnfr/operators/pattern_detection.py +660 -0
- tnfr/operators/patterns.py +669 -0
- tnfr/operators/postconditions/__init__.py +38 -0
- tnfr/operators/postconditions/mutation.py +236 -0
- tnfr/operators/preconditions/__init__.py +1226 -0
- tnfr/operators/preconditions/coherence.py +305 -0
- tnfr/operators/preconditions/dissonance.py +236 -0
- tnfr/operators/preconditions/emission.py +128 -0
- tnfr/operators/preconditions/mutation.py +580 -0
- tnfr/operators/preconditions/reception.py +125 -0
- tnfr/operators/preconditions/resonance.py +364 -0
- tnfr/operators/registry.py +74 -0
- tnfr/operators/registry.pyi +9 -0
- tnfr/operators/remesh.py +1415 -91
- tnfr/operators/remesh.pyi +26 -0
- tnfr/operators/structural_units.py +268 -0
- tnfr/operators/unified_grammar.py +105 -0
- tnfr/parallel/__init__.py +54 -0
- tnfr/parallel/auto_scaler.py +234 -0
- tnfr/parallel/distributed.py +384 -0
- tnfr/parallel/engine.py +238 -0
- tnfr/parallel/gpu_engine.py +420 -0
- tnfr/parallel/monitoring.py +248 -0
- tnfr/parallel/partitioner.py +459 -0
- tnfr/py.typed +0 -0
- tnfr/recipes/__init__.py +22 -0
- tnfr/recipes/cookbook.py +743 -0
- tnfr/rng.py +75 -151
- tnfr/rng.pyi +26 -0
- tnfr/schemas/__init__.py +8 -0
- tnfr/schemas/grammar.json +94 -0
- tnfr/sdk/__init__.py +107 -0
- tnfr/sdk/__init__.pyi +19 -0
- tnfr/sdk/adaptive_system.py +173 -0
- tnfr/sdk/adaptive_system.pyi +21 -0
- tnfr/sdk/builders.py +370 -0
- tnfr/sdk/builders.pyi +51 -0
- tnfr/sdk/fluent.py +1121 -0
- tnfr/sdk/fluent.pyi +74 -0
- tnfr/sdk/templates.py +342 -0
- tnfr/sdk/templates.pyi +41 -0
- tnfr/sdk/utils.py +341 -0
- tnfr/secure_config.py +46 -0
- tnfr/security/__init__.py +70 -0
- tnfr/security/database.py +514 -0
- tnfr/security/subprocess.py +503 -0
- tnfr/security/validation.py +290 -0
- tnfr/selector.py +59 -22
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +92 -67
- tnfr/sense.pyi +23 -0
- tnfr/services/__init__.py +17 -0
- tnfr/services/orchestrator.py +325 -0
- tnfr/sparse/__init__.py +39 -0
- tnfr/sparse/representations.py +492 -0
- tnfr/structural.py +639 -263
- tnfr/structural.pyi +83 -0
- tnfr/telemetry/__init__.py +35 -0
- tnfr/telemetry/cache_metrics.py +226 -0
- tnfr/telemetry/cache_metrics.pyi +64 -0
- tnfr/telemetry/nu_f.py +422 -0
- tnfr/telemetry/nu_f.pyi +108 -0
- tnfr/telemetry/verbosity.py +36 -0
- tnfr/telemetry/verbosity.pyi +15 -0
- tnfr/tokens.py +2 -4
- tnfr/tokens.pyi +36 -0
- tnfr/tools/__init__.py +20 -0
- tnfr/tools/domain_templates.py +478 -0
- tnfr/tools/sequence_generator.py +846 -0
- tnfr/topology/__init__.py +13 -0
- tnfr/topology/asymmetry.py +151 -0
- tnfr/trace.py +300 -126
- tnfr/trace.pyi +42 -0
- tnfr/tutorials/__init__.py +38 -0
- tnfr/tutorials/autonomous_evolution.py +285 -0
- tnfr/tutorials/interactive.py +1576 -0
- tnfr/tutorials/structural_metabolism.py +238 -0
- tnfr/types.py +743 -12
- tnfr/types.pyi +357 -0
- tnfr/units.py +68 -0
- tnfr/units.pyi +13 -0
- tnfr/utils/__init__.py +282 -0
- tnfr/utils/__init__.pyi +215 -0
- tnfr/utils/cache.py +4223 -0
- tnfr/utils/cache.pyi +470 -0
- tnfr/{callback_utils.py → utils/callbacks.py} +26 -39
- tnfr/utils/callbacks.pyi +49 -0
- tnfr/utils/chunks.py +108 -0
- tnfr/utils/chunks.pyi +22 -0
- tnfr/utils/data.py +428 -0
- tnfr/utils/data.pyi +74 -0
- tnfr/utils/graph.py +85 -0
- tnfr/utils/graph.pyi +10 -0
- tnfr/utils/init.py +821 -0
- tnfr/utils/init.pyi +80 -0
- tnfr/utils/io.py +559 -0
- tnfr/utils/io.pyi +66 -0
- tnfr/{helpers → utils}/numeric.py +51 -24
- tnfr/utils/numeric.pyi +21 -0
- tnfr/validation/__init__.py +257 -0
- tnfr/validation/__init__.pyi +85 -0
- tnfr/validation/compatibility.py +460 -0
- tnfr/validation/compatibility.pyi +6 -0
- tnfr/validation/config.py +73 -0
- tnfr/validation/graph.py +139 -0
- tnfr/validation/graph.pyi +18 -0
- tnfr/validation/input_validation.py +755 -0
- tnfr/validation/invariants.py +712 -0
- tnfr/validation/rules.py +253 -0
- tnfr/validation/rules.pyi +44 -0
- tnfr/validation/runtime.py +279 -0
- tnfr/validation/runtime.pyi +28 -0
- tnfr/validation/sequence_validator.py +162 -0
- tnfr/validation/soft_filters.py +170 -0
- tnfr/validation/soft_filters.pyi +32 -0
- tnfr/validation/spectral.py +164 -0
- tnfr/validation/spectral.pyi +42 -0
- tnfr/validation/validator.py +1266 -0
- tnfr/validation/window.py +39 -0
- tnfr/validation/window.pyi +1 -0
- tnfr/visualization/__init__.py +98 -0
- tnfr/visualization/cascade_viz.py +256 -0
- tnfr/visualization/hierarchy.py +284 -0
- tnfr/visualization/sequence_plotter.py +784 -0
- tnfr/viz/__init__.py +60 -0
- tnfr/viz/matplotlib.py +278 -0
- tnfr/viz/matplotlib.pyi +35 -0
- tnfr-8.5.0.dist-info/METADATA +573 -0
- tnfr-8.5.0.dist-info/RECORD +353 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/entry_points.txt +1 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/licenses/LICENSE.md +1 -1
- tnfr/collections_utils.py +0 -300
- tnfr/config.py +0 -32
- tnfr/grammar.py +0 -344
- tnfr/graph_utils.py +0 -84
- tnfr/helpers/__init__.py +0 -71
- tnfr/import_utils.py +0 -228
- tnfr/json_utils.py +0 -162
- tnfr/logging_utils.py +0 -116
- tnfr/presets.py +0 -60
- tnfr/validators.py +0 -84
- tnfr/value_utils.py +0 -59
- tnfr-4.5.2.dist-info/METADATA +0 -379
- tnfr-4.5.2.dist-info/RECORD +0 -67
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
- {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
tnfr/structural.pyi
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .mathematics import (
|
|
4
|
+
BasicStateProjector,
|
|
5
|
+
CoherenceOperator,
|
|
6
|
+
FrequencyOperator,
|
|
7
|
+
HilbertSpace,
|
|
8
|
+
MathematicalDynamicsEngine,
|
|
9
|
+
)
|
|
10
|
+
from .operators.definitions import (
|
|
11
|
+
Coherence as Coherence,
|
|
12
|
+
Contraction as Contraction,
|
|
13
|
+
Coupling as Coupling,
|
|
14
|
+
Dissonance as Dissonance,
|
|
15
|
+
Emission as Emission,
|
|
16
|
+
Expansion as Expansion,
|
|
17
|
+
Mutation as Mutation,
|
|
18
|
+
Operator as Operator,
|
|
19
|
+
Reception as Reception,
|
|
20
|
+
Recursivity as Recursivity,
|
|
21
|
+
Resonance as Resonance,
|
|
22
|
+
SelfOrganization as SelfOrganization,
|
|
23
|
+
Silence as Silence,
|
|
24
|
+
Transition as Transition,
|
|
25
|
+
)
|
|
26
|
+
from .operators.registry import OPERATORS as OPERATORS
|
|
27
|
+
from .types import DeltaNFRHook, NodeId, TNFRGraph
|
|
28
|
+
from tnfr.validation import NFRValidator, validate_sequence as validate_sequence
|
|
29
|
+
from typing import Iterable, Sequence
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"create_nfr",
|
|
33
|
+
"create_math_nfr",
|
|
34
|
+
"Operator",
|
|
35
|
+
"Emission",
|
|
36
|
+
"Reception",
|
|
37
|
+
"Coherence",
|
|
38
|
+
"Dissonance",
|
|
39
|
+
"Coupling",
|
|
40
|
+
"Resonance",
|
|
41
|
+
"Silence",
|
|
42
|
+
"Expansion",
|
|
43
|
+
"Contraction",
|
|
44
|
+
"SelfOrganization",
|
|
45
|
+
"Mutation",
|
|
46
|
+
"Transition",
|
|
47
|
+
"Recursivity",
|
|
48
|
+
"OPERATORS",
|
|
49
|
+
"validate_sequence",
|
|
50
|
+
"run_sequence",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
def create_nfr(
|
|
54
|
+
name: str,
|
|
55
|
+
*,
|
|
56
|
+
epi: float = 0.0,
|
|
57
|
+
vf: float = 1.0,
|
|
58
|
+
theta: float = 0.0,
|
|
59
|
+
graph: TNFRGraph | None = None,
|
|
60
|
+
dnfr_hook: DeltaNFRHook = ...,
|
|
61
|
+
) -> tuple[TNFRGraph, str]: ...
|
|
62
|
+
def create_math_nfr(
|
|
63
|
+
name: str,
|
|
64
|
+
*,
|
|
65
|
+
epi: float = 0.0,
|
|
66
|
+
vf: float = 1.0,
|
|
67
|
+
theta: float = 0.0,
|
|
68
|
+
graph: TNFRGraph | None = None,
|
|
69
|
+
dnfr_hook: DeltaNFRHook = ...,
|
|
70
|
+
dimension: int | None = None,
|
|
71
|
+
hilbert_space: HilbertSpace | None = None,
|
|
72
|
+
coherence_operator: CoherenceOperator | None = None,
|
|
73
|
+
coherence_spectrum: Sequence[float] | None = None,
|
|
74
|
+
coherence_c_min: float | None = None,
|
|
75
|
+
coherence_threshold: float | None = None,
|
|
76
|
+
frequency_operator: FrequencyOperator | None = None,
|
|
77
|
+
frequency_diagonal: Sequence[float] | None = None,
|
|
78
|
+
generator_diagonal: Sequence[float] | None = None,
|
|
79
|
+
state_projector: BasicStateProjector | None = None,
|
|
80
|
+
dynamics_engine: MathematicalDynamicsEngine | None = None,
|
|
81
|
+
validator: NFRValidator | None = None,
|
|
82
|
+
) -> tuple[TNFRGraph, str]: ...
|
|
83
|
+
def run_sequence(G: TNFRGraph, node: NodeId, ops: Iterable[Operator]) -> None: ...
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Telemetry helpers for shared observability settings."""
|
|
2
|
+
|
|
3
|
+
from .cache_metrics import (
|
|
4
|
+
CacheMetricsSnapshot,
|
|
5
|
+
CacheTelemetryPublisher,
|
|
6
|
+
ensure_cache_metrics_publisher,
|
|
7
|
+
publish_graph_cache_metrics,
|
|
8
|
+
)
|
|
9
|
+
from .nu_f import (
|
|
10
|
+
NuFSnapshot,
|
|
11
|
+
NuFTelemetryAccumulator,
|
|
12
|
+
NuFWindow,
|
|
13
|
+
ensure_nu_f_telemetry,
|
|
14
|
+
record_nu_f_window,
|
|
15
|
+
)
|
|
16
|
+
from .verbosity import (
|
|
17
|
+
TELEMETRY_VERBOSITY_DEFAULT,
|
|
18
|
+
TELEMETRY_VERBOSITY_LEVELS,
|
|
19
|
+
TelemetryVerbosity,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"CacheMetricsSnapshot",
|
|
24
|
+
"CacheTelemetryPublisher",
|
|
25
|
+
"ensure_cache_metrics_publisher",
|
|
26
|
+
"publish_graph_cache_metrics",
|
|
27
|
+
"NuFWindow",
|
|
28
|
+
"NuFSnapshot",
|
|
29
|
+
"NuFTelemetryAccumulator",
|
|
30
|
+
"ensure_nu_f_telemetry",
|
|
31
|
+
"record_nu_f_window",
|
|
32
|
+
"TelemetryVerbosity",
|
|
33
|
+
"TELEMETRY_VERBOSITY_DEFAULT",
|
|
34
|
+
"TELEMETRY_VERBOSITY_LEVELS",
|
|
35
|
+
]
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""Cache telemetry publishers for structured observability channels."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import weakref
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any, MutableMapping, TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from ..utils import (
|
|
11
|
+
_graph_cache_manager,
|
|
12
|
+
CacheManager,
|
|
13
|
+
CacheStatistics,
|
|
14
|
+
get_logger,
|
|
15
|
+
json_dumps,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING: # pragma: no cover - typing helpers
|
|
19
|
+
from networkx import Graph
|
|
20
|
+
|
|
21
|
+
from ..types import TNFRGraph
|
|
22
|
+
|
|
23
|
+
__all__ = (
|
|
24
|
+
"CacheMetricsSnapshot",
|
|
25
|
+
"CacheTelemetryPublisher",
|
|
26
|
+
"ensure_cache_metrics_publisher",
|
|
27
|
+
"publish_graph_cache_metrics",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class CacheMetricsSnapshot:
|
|
33
|
+
"""Structured cache metrics enriched with ratios and latency estimates."""
|
|
34
|
+
|
|
35
|
+
cache: str
|
|
36
|
+
hits: int
|
|
37
|
+
misses: int
|
|
38
|
+
evictions: int
|
|
39
|
+
total_time: float
|
|
40
|
+
timings: int
|
|
41
|
+
hit_ratio: float | None
|
|
42
|
+
miss_ratio: float | None
|
|
43
|
+
avg_latency: float | None
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def from_statistics(
|
|
47
|
+
cls, name: str, stats: CacheStatistics
|
|
48
|
+
) -> "CacheMetricsSnapshot":
|
|
49
|
+
"""Build a snapshot computing ratios from :class:`CacheStatistics`."""
|
|
50
|
+
|
|
51
|
+
hits = int(stats.hits)
|
|
52
|
+
misses = int(stats.misses)
|
|
53
|
+
evictions = int(stats.evictions)
|
|
54
|
+
total_time = float(stats.total_time)
|
|
55
|
+
timings = int(stats.timings)
|
|
56
|
+
requests = hits + misses
|
|
57
|
+
hit_ratio = (hits / requests) if requests else None
|
|
58
|
+
miss_ratio = (misses / requests) if requests else None
|
|
59
|
+
avg_latency = (total_time / timings) if timings else None
|
|
60
|
+
return cls(
|
|
61
|
+
cache=name,
|
|
62
|
+
hits=hits,
|
|
63
|
+
misses=misses,
|
|
64
|
+
evictions=evictions,
|
|
65
|
+
total_time=total_time,
|
|
66
|
+
timings=timings,
|
|
67
|
+
hit_ratio=hit_ratio,
|
|
68
|
+
miss_ratio=miss_ratio,
|
|
69
|
+
avg_latency=avg_latency,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def as_payload(self) -> dict[str, Any]:
|
|
73
|
+
"""Return a dictionary suitable for structured logging."""
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
"cache": self.cache,
|
|
77
|
+
"hits": self.hits,
|
|
78
|
+
"misses": self.misses,
|
|
79
|
+
"evictions": self.evictions,
|
|
80
|
+
"total_time": self.total_time,
|
|
81
|
+
"timings": self.timings,
|
|
82
|
+
"hit_ratio": self.hit_ratio,
|
|
83
|
+
"miss_ratio": self.miss_ratio,
|
|
84
|
+
"avg_latency": self.avg_latency,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class CacheTelemetryPublisher:
|
|
89
|
+
"""Metrics publisher broadcasting cache counters to observability channels."""
|
|
90
|
+
|
|
91
|
+
def __init__(
|
|
92
|
+
self,
|
|
93
|
+
*,
|
|
94
|
+
graph: "TNFRGraph | Graph | MutableMapping[str, Any] | None" = None,
|
|
95
|
+
logger: logging.Logger | None = None,
|
|
96
|
+
hit_ratio_alert: float = 0.5,
|
|
97
|
+
latency_alert: float = 0.1,
|
|
98
|
+
) -> None:
|
|
99
|
+
self._logger = logger or get_logger("tnfr.telemetry.cache")
|
|
100
|
+
self._graph_ref: (
|
|
101
|
+
weakref.ReferenceType["TNFRGraph | Graph | MutableMapping[str, Any]"] | None
|
|
102
|
+
) = None
|
|
103
|
+
self._hit_ratio_alert = float(hit_ratio_alert)
|
|
104
|
+
self._latency_alert = float(latency_alert)
|
|
105
|
+
self.attach_graph(graph)
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def logger(self) -> logging.Logger:
|
|
109
|
+
"""Logger used for structured cache telemetry."""
|
|
110
|
+
|
|
111
|
+
return self._logger
|
|
112
|
+
|
|
113
|
+
def attach_graph(
|
|
114
|
+
self, graph: "TNFRGraph | Graph | MutableMapping[str, Any] | None"
|
|
115
|
+
) -> None:
|
|
116
|
+
"""Attach ``graph`` so observability callbacks receive metrics."""
|
|
117
|
+
|
|
118
|
+
if graph is None:
|
|
119
|
+
return
|
|
120
|
+
try:
|
|
121
|
+
self._graph_ref = weakref.ref(graph) # type: ignore[arg-type]
|
|
122
|
+
except TypeError: # pragma: no cover - defensive path for exotic graphs
|
|
123
|
+
self._graph_ref = None
|
|
124
|
+
|
|
125
|
+
def _resolve_graph(
|
|
126
|
+
self,
|
|
127
|
+
) -> "TNFRGraph | Graph | MutableMapping[str, Any] | None":
|
|
128
|
+
return self._graph_ref() if self._graph_ref is not None else None
|
|
129
|
+
|
|
130
|
+
def __call__(self, name: str, stats: CacheStatistics) -> None:
|
|
131
|
+
"""Emit structured telemetry and invoke observability hooks."""
|
|
132
|
+
|
|
133
|
+
snapshot = CacheMetricsSnapshot.from_statistics(name, stats)
|
|
134
|
+
payload = snapshot.as_payload()
|
|
135
|
+
message = json_dumps({"event": "cache_metrics", **payload}, sort_keys=True)
|
|
136
|
+
self._logger.info(message)
|
|
137
|
+
|
|
138
|
+
if (
|
|
139
|
+
snapshot.hit_ratio is not None
|
|
140
|
+
and snapshot.hit_ratio < self._hit_ratio_alert
|
|
141
|
+
and snapshot.misses > 0
|
|
142
|
+
):
|
|
143
|
+
warning = json_dumps(
|
|
144
|
+
{
|
|
145
|
+
"event": "cache_metrics.low_hit_ratio",
|
|
146
|
+
"cache": name,
|
|
147
|
+
"hit_ratio": snapshot.hit_ratio,
|
|
148
|
+
"threshold": self._hit_ratio_alert,
|
|
149
|
+
"requests": snapshot.hits + snapshot.misses,
|
|
150
|
+
},
|
|
151
|
+
sort_keys=True,
|
|
152
|
+
)
|
|
153
|
+
self._logger.warning(warning)
|
|
154
|
+
|
|
155
|
+
if (
|
|
156
|
+
snapshot.avg_latency is not None
|
|
157
|
+
and snapshot.avg_latency > self._latency_alert
|
|
158
|
+
and snapshot.timings > 0
|
|
159
|
+
):
|
|
160
|
+
warning = json_dumps(
|
|
161
|
+
{
|
|
162
|
+
"event": "cache_metrics.high_latency",
|
|
163
|
+
"cache": name,
|
|
164
|
+
"avg_latency": snapshot.avg_latency,
|
|
165
|
+
"threshold": self._latency_alert,
|
|
166
|
+
"timings": snapshot.timings,
|
|
167
|
+
},
|
|
168
|
+
sort_keys=True,
|
|
169
|
+
)
|
|
170
|
+
self._logger.warning(warning)
|
|
171
|
+
|
|
172
|
+
graph = self._resolve_graph()
|
|
173
|
+
if graph is not None:
|
|
174
|
+
from ..utils import CallbackEvent, callback_manager
|
|
175
|
+
|
|
176
|
+
ctx = {"cache": name, "metrics": payload}
|
|
177
|
+
callback_manager.invoke_callbacks(graph, CallbackEvent.CACHE_METRICS, ctx)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
_PUBLISHER_ATTR = "_tnfr_cache_metrics_publisher"
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def ensure_cache_metrics_publisher(
|
|
184
|
+
manager: CacheManager,
|
|
185
|
+
*,
|
|
186
|
+
graph: "TNFRGraph | Graph | MutableMapping[str, Any] | None" = None,
|
|
187
|
+
logger: logging.Logger | None = None,
|
|
188
|
+
hit_ratio_alert: float = 0.5,
|
|
189
|
+
latency_alert: float = 0.1,
|
|
190
|
+
) -> CacheTelemetryPublisher:
|
|
191
|
+
"""Attach a :class:`CacheTelemetryPublisher` to ``manager`` if missing."""
|
|
192
|
+
|
|
193
|
+
publisher = getattr(manager, _PUBLISHER_ATTR, None)
|
|
194
|
+
if not isinstance(publisher, CacheTelemetryPublisher):
|
|
195
|
+
publisher = CacheTelemetryPublisher(
|
|
196
|
+
graph=graph,
|
|
197
|
+
logger=logger,
|
|
198
|
+
hit_ratio_alert=hit_ratio_alert,
|
|
199
|
+
latency_alert=latency_alert,
|
|
200
|
+
)
|
|
201
|
+
manager.register_metrics_publisher(publisher)
|
|
202
|
+
setattr(manager, _PUBLISHER_ATTR, publisher)
|
|
203
|
+
else:
|
|
204
|
+
if graph is not None:
|
|
205
|
+
publisher.attach_graph(graph)
|
|
206
|
+
return publisher
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def publish_graph_cache_metrics(
|
|
210
|
+
graph: "TNFRGraph | Graph | MutableMapping[str, Any]",
|
|
211
|
+
*,
|
|
212
|
+
manager: CacheManager | None = None,
|
|
213
|
+
hit_ratio_alert: float = 0.5,
|
|
214
|
+
latency_alert: float = 0.1,
|
|
215
|
+
) -> None:
|
|
216
|
+
"""Publish cache metrics for ``graph`` using the shared manager."""
|
|
217
|
+
|
|
218
|
+
if manager is None:
|
|
219
|
+
manager = _graph_cache_manager(getattr(graph, "graph", graph))
|
|
220
|
+
ensure_cache_metrics_publisher(
|
|
221
|
+
manager,
|
|
222
|
+
graph=graph,
|
|
223
|
+
hit_ratio_alert=hit_ratio_alert,
|
|
224
|
+
latency_alert=latency_alert,
|
|
225
|
+
)
|
|
226
|
+
manager.publish_metrics()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from ..types import TNFRGraph
|
|
5
|
+
from ..utils import CacheManager, CacheStatistics
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from networkx import Graph
|
|
8
|
+
from typing import Any, MutableMapping
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"CacheMetricsSnapshot",
|
|
12
|
+
"CacheTelemetryPublisher",
|
|
13
|
+
"ensure_cache_metrics_publisher",
|
|
14
|
+
"publish_graph_cache_metrics",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class CacheMetricsSnapshot:
|
|
19
|
+
cache: str
|
|
20
|
+
hits: int
|
|
21
|
+
misses: int
|
|
22
|
+
evictions: int
|
|
23
|
+
total_time: float
|
|
24
|
+
timings: int
|
|
25
|
+
hit_ratio: float | None
|
|
26
|
+
miss_ratio: float | None
|
|
27
|
+
avg_latency: float | None
|
|
28
|
+
@classmethod
|
|
29
|
+
def from_statistics(
|
|
30
|
+
cls, name: str, stats: CacheStatistics
|
|
31
|
+
) -> CacheMetricsSnapshot: ...
|
|
32
|
+
def as_payload(self) -> dict[str, Any]: ...
|
|
33
|
+
|
|
34
|
+
class CacheTelemetryPublisher:
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
*,
|
|
38
|
+
graph: TNFRGraph | Graph | MutableMapping[str, Any] | None = None,
|
|
39
|
+
logger: logging.Logger | None = None,
|
|
40
|
+
hit_ratio_alert: float = 0.5,
|
|
41
|
+
latency_alert: float = 0.1,
|
|
42
|
+
) -> None: ...
|
|
43
|
+
@property
|
|
44
|
+
def logger(self) -> logging.Logger: ...
|
|
45
|
+
def attach_graph(
|
|
46
|
+
self, graph: TNFRGraph | Graph | MutableMapping[str, Any] | None
|
|
47
|
+
) -> None: ...
|
|
48
|
+
def __call__(self, name: str, stats: CacheStatistics) -> None: ...
|
|
49
|
+
|
|
50
|
+
def ensure_cache_metrics_publisher(
|
|
51
|
+
manager: CacheManager,
|
|
52
|
+
*,
|
|
53
|
+
graph: TNFRGraph | Graph | MutableMapping[str, Any] | None = None,
|
|
54
|
+
logger: logging.Logger | None = None,
|
|
55
|
+
hit_ratio_alert: float = 0.5,
|
|
56
|
+
latency_alert: float = 0.1,
|
|
57
|
+
) -> CacheTelemetryPublisher: ...
|
|
58
|
+
def publish_graph_cache_metrics(
|
|
59
|
+
graph: TNFRGraph | Graph | MutableMapping[str, Any],
|
|
60
|
+
*,
|
|
61
|
+
manager: CacheManager | None = None,
|
|
62
|
+
hit_ratio_alert: float = 0.5,
|
|
63
|
+
latency_alert: float = 0.1,
|
|
64
|
+
) -> None: ...
|