truthound 1.0.8__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.
Files changed (877) hide show
  1. truthound/__init__.py +162 -0
  2. truthound/adapters.py +100 -0
  3. truthound/api.py +365 -0
  4. truthound/audit/__init__.py +248 -0
  5. truthound/audit/core.py +967 -0
  6. truthound/audit/filters.py +620 -0
  7. truthound/audit/formatters.py +707 -0
  8. truthound/audit/logger.py +902 -0
  9. truthound/audit/middleware.py +571 -0
  10. truthound/audit/storage.py +1083 -0
  11. truthound/benchmark/__init__.py +123 -0
  12. truthound/benchmark/base.py +757 -0
  13. truthound/benchmark/comparison.py +635 -0
  14. truthound/benchmark/generators.py +706 -0
  15. truthound/benchmark/reporters.py +718 -0
  16. truthound/benchmark/runner.py +635 -0
  17. truthound/benchmark/scenarios.py +712 -0
  18. truthound/cache.py +252 -0
  19. truthound/checkpoint/__init__.py +136 -0
  20. truthound/checkpoint/actions/__init__.py +164 -0
  21. truthound/checkpoint/actions/base.py +324 -0
  22. truthound/checkpoint/actions/custom.py +234 -0
  23. truthound/checkpoint/actions/discord_notify.py +290 -0
  24. truthound/checkpoint/actions/email_notify.py +405 -0
  25. truthound/checkpoint/actions/github_action.py +406 -0
  26. truthound/checkpoint/actions/opsgenie.py +1499 -0
  27. truthound/checkpoint/actions/pagerduty.py +226 -0
  28. truthound/checkpoint/actions/slack_notify.py +233 -0
  29. truthound/checkpoint/actions/store_result.py +249 -0
  30. truthound/checkpoint/actions/teams_notify.py +1570 -0
  31. truthound/checkpoint/actions/telegram_notify.py +419 -0
  32. truthound/checkpoint/actions/update_docs.py +552 -0
  33. truthound/checkpoint/actions/webhook.py +293 -0
  34. truthound/checkpoint/analytics/__init__.py +147 -0
  35. truthound/checkpoint/analytics/aggregations/__init__.py +23 -0
  36. truthound/checkpoint/analytics/aggregations/rollup.py +481 -0
  37. truthound/checkpoint/analytics/aggregations/time_bucket.py +306 -0
  38. truthound/checkpoint/analytics/analyzers/__init__.py +17 -0
  39. truthound/checkpoint/analytics/analyzers/anomaly.py +386 -0
  40. truthound/checkpoint/analytics/analyzers/base.py +270 -0
  41. truthound/checkpoint/analytics/analyzers/forecast.py +421 -0
  42. truthound/checkpoint/analytics/analyzers/trend.py +314 -0
  43. truthound/checkpoint/analytics/models.py +292 -0
  44. truthound/checkpoint/analytics/protocols.py +549 -0
  45. truthound/checkpoint/analytics/service.py +718 -0
  46. truthound/checkpoint/analytics/stores/__init__.py +16 -0
  47. truthound/checkpoint/analytics/stores/base.py +306 -0
  48. truthound/checkpoint/analytics/stores/memory_store.py +353 -0
  49. truthound/checkpoint/analytics/stores/sqlite_store.py +557 -0
  50. truthound/checkpoint/analytics/stores/timescale_store.py +501 -0
  51. truthound/checkpoint/async_actions.py +794 -0
  52. truthound/checkpoint/async_base.py +708 -0
  53. truthound/checkpoint/async_checkpoint.py +617 -0
  54. truthound/checkpoint/async_runner.py +639 -0
  55. truthound/checkpoint/checkpoint.py +527 -0
  56. truthound/checkpoint/ci/__init__.py +61 -0
  57. truthound/checkpoint/ci/detector.py +355 -0
  58. truthound/checkpoint/ci/reporter.py +436 -0
  59. truthound/checkpoint/ci/templates.py +454 -0
  60. truthound/checkpoint/circuitbreaker/__init__.py +133 -0
  61. truthound/checkpoint/circuitbreaker/breaker.py +542 -0
  62. truthound/checkpoint/circuitbreaker/core.py +252 -0
  63. truthound/checkpoint/circuitbreaker/detection.py +459 -0
  64. truthound/checkpoint/circuitbreaker/middleware.py +389 -0
  65. truthound/checkpoint/circuitbreaker/registry.py +357 -0
  66. truthound/checkpoint/distributed/__init__.py +139 -0
  67. truthound/checkpoint/distributed/backends/__init__.py +35 -0
  68. truthound/checkpoint/distributed/backends/celery_backend.py +503 -0
  69. truthound/checkpoint/distributed/backends/kubernetes_backend.py +696 -0
  70. truthound/checkpoint/distributed/backends/local_backend.py +397 -0
  71. truthound/checkpoint/distributed/backends/ray_backend.py +625 -0
  72. truthound/checkpoint/distributed/base.py +774 -0
  73. truthound/checkpoint/distributed/orchestrator.py +765 -0
  74. truthound/checkpoint/distributed/protocols.py +842 -0
  75. truthound/checkpoint/distributed/registry.py +449 -0
  76. truthound/checkpoint/idempotency/__init__.py +120 -0
  77. truthound/checkpoint/idempotency/core.py +295 -0
  78. truthound/checkpoint/idempotency/fingerprint.py +454 -0
  79. truthound/checkpoint/idempotency/locking.py +604 -0
  80. truthound/checkpoint/idempotency/service.py +592 -0
  81. truthound/checkpoint/idempotency/stores.py +653 -0
  82. truthound/checkpoint/monitoring/__init__.py +134 -0
  83. truthound/checkpoint/monitoring/aggregators/__init__.py +15 -0
  84. truthound/checkpoint/monitoring/aggregators/base.py +372 -0
  85. truthound/checkpoint/monitoring/aggregators/realtime.py +300 -0
  86. truthound/checkpoint/monitoring/aggregators/window.py +493 -0
  87. truthound/checkpoint/monitoring/collectors/__init__.py +17 -0
  88. truthound/checkpoint/monitoring/collectors/base.py +257 -0
  89. truthound/checkpoint/monitoring/collectors/memory_collector.py +617 -0
  90. truthound/checkpoint/monitoring/collectors/prometheus_collector.py +451 -0
  91. truthound/checkpoint/monitoring/collectors/redis_collector.py +518 -0
  92. truthound/checkpoint/monitoring/events.py +410 -0
  93. truthound/checkpoint/monitoring/protocols.py +636 -0
  94. truthound/checkpoint/monitoring/service.py +578 -0
  95. truthound/checkpoint/monitoring/views/__init__.py +17 -0
  96. truthound/checkpoint/monitoring/views/base.py +172 -0
  97. truthound/checkpoint/monitoring/views/queue_view.py +220 -0
  98. truthound/checkpoint/monitoring/views/task_view.py +240 -0
  99. truthound/checkpoint/monitoring/views/worker_view.py +263 -0
  100. truthound/checkpoint/registry.py +337 -0
  101. truthound/checkpoint/runner.py +356 -0
  102. truthound/checkpoint/transaction/__init__.py +133 -0
  103. truthound/checkpoint/transaction/base.py +389 -0
  104. truthound/checkpoint/transaction/compensatable.py +537 -0
  105. truthound/checkpoint/transaction/coordinator.py +576 -0
  106. truthound/checkpoint/transaction/executor.py +622 -0
  107. truthound/checkpoint/transaction/idempotency.py +534 -0
  108. truthound/checkpoint/transaction/saga/__init__.py +143 -0
  109. truthound/checkpoint/transaction/saga/builder.py +584 -0
  110. truthound/checkpoint/transaction/saga/definition.py +515 -0
  111. truthound/checkpoint/transaction/saga/event_store.py +542 -0
  112. truthound/checkpoint/transaction/saga/patterns.py +833 -0
  113. truthound/checkpoint/transaction/saga/runner.py +718 -0
  114. truthound/checkpoint/transaction/saga/state_machine.py +793 -0
  115. truthound/checkpoint/transaction/saga/strategies.py +780 -0
  116. truthound/checkpoint/transaction/saga/testing.py +886 -0
  117. truthound/checkpoint/triggers/__init__.py +58 -0
  118. truthound/checkpoint/triggers/base.py +237 -0
  119. truthound/checkpoint/triggers/event.py +385 -0
  120. truthound/checkpoint/triggers/schedule.py +355 -0
  121. truthound/cli.py +2358 -0
  122. truthound/cli_modules/__init__.py +124 -0
  123. truthound/cli_modules/advanced/__init__.py +45 -0
  124. truthound/cli_modules/advanced/benchmark.py +343 -0
  125. truthound/cli_modules/advanced/docs.py +225 -0
  126. truthound/cli_modules/advanced/lineage.py +209 -0
  127. truthound/cli_modules/advanced/ml.py +320 -0
  128. truthound/cli_modules/advanced/realtime.py +196 -0
  129. truthound/cli_modules/checkpoint/__init__.py +46 -0
  130. truthound/cli_modules/checkpoint/init.py +114 -0
  131. truthound/cli_modules/checkpoint/list.py +71 -0
  132. truthound/cli_modules/checkpoint/run.py +159 -0
  133. truthound/cli_modules/checkpoint/validate.py +67 -0
  134. truthound/cli_modules/common/__init__.py +71 -0
  135. truthound/cli_modules/common/errors.py +414 -0
  136. truthound/cli_modules/common/options.py +419 -0
  137. truthound/cli_modules/common/output.py +507 -0
  138. truthound/cli_modules/common/protocol.py +552 -0
  139. truthound/cli_modules/core/__init__.py +48 -0
  140. truthound/cli_modules/core/check.py +123 -0
  141. truthound/cli_modules/core/compare.py +104 -0
  142. truthound/cli_modules/core/learn.py +57 -0
  143. truthound/cli_modules/core/mask.py +77 -0
  144. truthound/cli_modules/core/profile.py +65 -0
  145. truthound/cli_modules/core/scan.py +61 -0
  146. truthound/cli_modules/profiler/__init__.py +51 -0
  147. truthound/cli_modules/profiler/auto_profile.py +175 -0
  148. truthound/cli_modules/profiler/metadata.py +107 -0
  149. truthound/cli_modules/profiler/suite.py +283 -0
  150. truthound/cli_modules/registry.py +431 -0
  151. truthound/cli_modules/scaffolding/__init__.py +89 -0
  152. truthound/cli_modules/scaffolding/base.py +631 -0
  153. truthound/cli_modules/scaffolding/commands.py +545 -0
  154. truthound/cli_modules/scaffolding/plugins.py +1072 -0
  155. truthound/cli_modules/scaffolding/reporters.py +594 -0
  156. truthound/cli_modules/scaffolding/validators.py +1127 -0
  157. truthound/common/__init__.py +18 -0
  158. truthound/common/resilience/__init__.py +130 -0
  159. truthound/common/resilience/bulkhead.py +266 -0
  160. truthound/common/resilience/circuit_breaker.py +516 -0
  161. truthound/common/resilience/composite.py +332 -0
  162. truthound/common/resilience/config.py +292 -0
  163. truthound/common/resilience/protocols.py +217 -0
  164. truthound/common/resilience/rate_limiter.py +404 -0
  165. truthound/common/resilience/retry.py +341 -0
  166. truthound/datadocs/__init__.py +260 -0
  167. truthound/datadocs/base.py +571 -0
  168. truthound/datadocs/builder.py +761 -0
  169. truthound/datadocs/charts.py +764 -0
  170. truthound/datadocs/dashboard/__init__.py +63 -0
  171. truthound/datadocs/dashboard/app.py +576 -0
  172. truthound/datadocs/dashboard/components.py +584 -0
  173. truthound/datadocs/dashboard/state.py +240 -0
  174. truthound/datadocs/engine/__init__.py +46 -0
  175. truthound/datadocs/engine/context.py +376 -0
  176. truthound/datadocs/engine/pipeline.py +618 -0
  177. truthound/datadocs/engine/registry.py +469 -0
  178. truthound/datadocs/exporters/__init__.py +49 -0
  179. truthound/datadocs/exporters/base.py +198 -0
  180. truthound/datadocs/exporters/html.py +178 -0
  181. truthound/datadocs/exporters/json_exporter.py +253 -0
  182. truthound/datadocs/exporters/markdown.py +284 -0
  183. truthound/datadocs/exporters/pdf.py +392 -0
  184. truthound/datadocs/i18n/__init__.py +86 -0
  185. truthound/datadocs/i18n/catalog.py +960 -0
  186. truthound/datadocs/i18n/formatting.py +505 -0
  187. truthound/datadocs/i18n/loader.py +256 -0
  188. truthound/datadocs/i18n/plurals.py +378 -0
  189. truthound/datadocs/renderers/__init__.py +42 -0
  190. truthound/datadocs/renderers/base.py +401 -0
  191. truthound/datadocs/renderers/custom.py +342 -0
  192. truthound/datadocs/renderers/jinja.py +697 -0
  193. truthound/datadocs/sections.py +736 -0
  194. truthound/datadocs/styles.py +931 -0
  195. truthound/datadocs/themes/__init__.py +101 -0
  196. truthound/datadocs/themes/base.py +336 -0
  197. truthound/datadocs/themes/default.py +417 -0
  198. truthound/datadocs/themes/enterprise.py +419 -0
  199. truthound/datadocs/themes/loader.py +336 -0
  200. truthound/datadocs/themes.py +301 -0
  201. truthound/datadocs/transformers/__init__.py +57 -0
  202. truthound/datadocs/transformers/base.py +268 -0
  203. truthound/datadocs/transformers/enrichers.py +544 -0
  204. truthound/datadocs/transformers/filters.py +447 -0
  205. truthound/datadocs/transformers/i18n.py +468 -0
  206. truthound/datadocs/versioning/__init__.py +62 -0
  207. truthound/datadocs/versioning/diff.py +639 -0
  208. truthound/datadocs/versioning/storage.py +497 -0
  209. truthound/datadocs/versioning/version.py +358 -0
  210. truthound/datasources/__init__.py +223 -0
  211. truthound/datasources/_async_protocols.py +222 -0
  212. truthound/datasources/_protocols.py +159 -0
  213. truthound/datasources/adapters.py +428 -0
  214. truthound/datasources/async_base.py +599 -0
  215. truthound/datasources/async_factory.py +511 -0
  216. truthound/datasources/base.py +516 -0
  217. truthound/datasources/factory.py +433 -0
  218. truthound/datasources/nosql/__init__.py +47 -0
  219. truthound/datasources/nosql/base.py +487 -0
  220. truthound/datasources/nosql/elasticsearch.py +801 -0
  221. truthound/datasources/nosql/mongodb.py +636 -0
  222. truthound/datasources/pandas_optimized.py +582 -0
  223. truthound/datasources/pandas_source.py +216 -0
  224. truthound/datasources/polars_source.py +395 -0
  225. truthound/datasources/spark_source.py +479 -0
  226. truthound/datasources/sql/__init__.py +154 -0
  227. truthound/datasources/sql/base.py +710 -0
  228. truthound/datasources/sql/bigquery.py +410 -0
  229. truthound/datasources/sql/cloud_base.py +199 -0
  230. truthound/datasources/sql/databricks.py +471 -0
  231. truthound/datasources/sql/mysql.py +316 -0
  232. truthound/datasources/sql/oracle.py +427 -0
  233. truthound/datasources/sql/postgresql.py +321 -0
  234. truthound/datasources/sql/redshift.py +479 -0
  235. truthound/datasources/sql/snowflake.py +439 -0
  236. truthound/datasources/sql/sqlite.py +286 -0
  237. truthound/datasources/sql/sqlserver.py +437 -0
  238. truthound/datasources/streaming/__init__.py +47 -0
  239. truthound/datasources/streaming/base.py +350 -0
  240. truthound/datasources/streaming/kafka.py +670 -0
  241. truthound/decorators.py +98 -0
  242. truthound/docs/__init__.py +69 -0
  243. truthound/docs/extractor.py +971 -0
  244. truthound/docs/generator.py +601 -0
  245. truthound/docs/parser.py +1037 -0
  246. truthound/docs/renderer.py +999 -0
  247. truthound/drift/__init__.py +22 -0
  248. truthound/drift/compare.py +189 -0
  249. truthound/drift/detectors.py +464 -0
  250. truthound/drift/report.py +160 -0
  251. truthound/execution/__init__.py +65 -0
  252. truthound/execution/_protocols.py +324 -0
  253. truthound/execution/base.py +576 -0
  254. truthound/execution/distributed/__init__.py +179 -0
  255. truthound/execution/distributed/aggregations.py +731 -0
  256. truthound/execution/distributed/arrow_bridge.py +817 -0
  257. truthound/execution/distributed/base.py +550 -0
  258. truthound/execution/distributed/dask_engine.py +976 -0
  259. truthound/execution/distributed/mixins.py +766 -0
  260. truthound/execution/distributed/protocols.py +756 -0
  261. truthound/execution/distributed/ray_engine.py +1127 -0
  262. truthound/execution/distributed/registry.py +446 -0
  263. truthound/execution/distributed/spark_engine.py +1011 -0
  264. truthound/execution/distributed/validator_adapter.py +682 -0
  265. truthound/execution/pandas_engine.py +401 -0
  266. truthound/execution/polars_engine.py +497 -0
  267. truthound/execution/pushdown/__init__.py +230 -0
  268. truthound/execution/pushdown/ast.py +1550 -0
  269. truthound/execution/pushdown/builder.py +1550 -0
  270. truthound/execution/pushdown/dialects.py +1072 -0
  271. truthound/execution/pushdown/executor.py +829 -0
  272. truthound/execution/pushdown/optimizer.py +1041 -0
  273. truthound/execution/sql_engine.py +518 -0
  274. truthound/infrastructure/__init__.py +189 -0
  275. truthound/infrastructure/audit.py +1515 -0
  276. truthound/infrastructure/config.py +1133 -0
  277. truthound/infrastructure/encryption.py +1132 -0
  278. truthound/infrastructure/logging.py +1503 -0
  279. truthound/infrastructure/metrics.py +1220 -0
  280. truthound/lineage/__init__.py +89 -0
  281. truthound/lineage/base.py +746 -0
  282. truthound/lineage/impact_analysis.py +474 -0
  283. truthound/lineage/integrations/__init__.py +22 -0
  284. truthound/lineage/integrations/openlineage.py +548 -0
  285. truthound/lineage/tracker.py +512 -0
  286. truthound/lineage/visualization/__init__.py +33 -0
  287. truthound/lineage/visualization/protocols.py +145 -0
  288. truthound/lineage/visualization/renderers/__init__.py +20 -0
  289. truthound/lineage/visualization/renderers/cytoscape.py +329 -0
  290. truthound/lineage/visualization/renderers/d3.py +331 -0
  291. truthound/lineage/visualization/renderers/graphviz.py +276 -0
  292. truthound/lineage/visualization/renderers/mermaid.py +308 -0
  293. truthound/maskers.py +113 -0
  294. truthound/ml/__init__.py +124 -0
  295. truthound/ml/anomaly_models/__init__.py +31 -0
  296. truthound/ml/anomaly_models/ensemble.py +362 -0
  297. truthound/ml/anomaly_models/isolation_forest.py +444 -0
  298. truthound/ml/anomaly_models/statistical.py +392 -0
  299. truthound/ml/base.py +1178 -0
  300. truthound/ml/drift_detection/__init__.py +26 -0
  301. truthound/ml/drift_detection/concept.py +381 -0
  302. truthound/ml/drift_detection/distribution.py +361 -0
  303. truthound/ml/drift_detection/feature.py +442 -0
  304. truthound/ml/drift_detection/multivariate.py +495 -0
  305. truthound/ml/monitoring/__init__.py +88 -0
  306. truthound/ml/monitoring/alerting/__init__.py +33 -0
  307. truthound/ml/monitoring/alerting/handlers.py +427 -0
  308. truthound/ml/monitoring/alerting/rules.py +508 -0
  309. truthound/ml/monitoring/collectors/__init__.py +19 -0
  310. truthound/ml/monitoring/collectors/composite.py +105 -0
  311. truthound/ml/monitoring/collectors/drift.py +324 -0
  312. truthound/ml/monitoring/collectors/performance.py +179 -0
  313. truthound/ml/monitoring/collectors/quality.py +369 -0
  314. truthound/ml/monitoring/monitor.py +536 -0
  315. truthound/ml/monitoring/protocols.py +451 -0
  316. truthound/ml/monitoring/stores/__init__.py +15 -0
  317. truthound/ml/monitoring/stores/memory.py +201 -0
  318. truthound/ml/monitoring/stores/prometheus.py +296 -0
  319. truthound/ml/rule_learning/__init__.py +25 -0
  320. truthound/ml/rule_learning/constraint_miner.py +443 -0
  321. truthound/ml/rule_learning/pattern_learner.py +499 -0
  322. truthound/ml/rule_learning/profile_learner.py +462 -0
  323. truthound/multitenancy/__init__.py +326 -0
  324. truthound/multitenancy/core.py +852 -0
  325. truthound/multitenancy/integration.py +597 -0
  326. truthound/multitenancy/isolation.py +630 -0
  327. truthound/multitenancy/manager.py +770 -0
  328. truthound/multitenancy/middleware.py +765 -0
  329. truthound/multitenancy/quota.py +537 -0
  330. truthound/multitenancy/resolvers.py +603 -0
  331. truthound/multitenancy/storage.py +703 -0
  332. truthound/observability/__init__.py +307 -0
  333. truthound/observability/context.py +531 -0
  334. truthound/observability/instrumentation.py +611 -0
  335. truthound/observability/logging.py +887 -0
  336. truthound/observability/metrics.py +1157 -0
  337. truthound/observability/tracing/__init__.py +178 -0
  338. truthound/observability/tracing/baggage.py +310 -0
  339. truthound/observability/tracing/config.py +426 -0
  340. truthound/observability/tracing/exporter.py +787 -0
  341. truthound/observability/tracing/integration.py +1018 -0
  342. truthound/observability/tracing/otel/__init__.py +146 -0
  343. truthound/observability/tracing/otel/adapter.py +982 -0
  344. truthound/observability/tracing/otel/bridge.py +1177 -0
  345. truthound/observability/tracing/otel/compat.py +681 -0
  346. truthound/observability/tracing/otel/config.py +691 -0
  347. truthound/observability/tracing/otel/detection.py +327 -0
  348. truthound/observability/tracing/otel/protocols.py +426 -0
  349. truthound/observability/tracing/processor.py +561 -0
  350. truthound/observability/tracing/propagator.py +757 -0
  351. truthound/observability/tracing/provider.py +569 -0
  352. truthound/observability/tracing/resource.py +515 -0
  353. truthound/observability/tracing/sampler.py +487 -0
  354. truthound/observability/tracing/span.py +676 -0
  355. truthound/plugins/__init__.py +198 -0
  356. truthound/plugins/base.py +599 -0
  357. truthound/plugins/cli.py +680 -0
  358. truthound/plugins/dependencies/__init__.py +42 -0
  359. truthound/plugins/dependencies/graph.py +422 -0
  360. truthound/plugins/dependencies/resolver.py +417 -0
  361. truthound/plugins/discovery.py +379 -0
  362. truthound/plugins/docs/__init__.py +46 -0
  363. truthound/plugins/docs/extractor.py +444 -0
  364. truthound/plugins/docs/renderer.py +499 -0
  365. truthound/plugins/enterprise_manager.py +877 -0
  366. truthound/plugins/examples/__init__.py +19 -0
  367. truthound/plugins/examples/custom_validators.py +317 -0
  368. truthound/plugins/examples/slack_notifier.py +312 -0
  369. truthound/plugins/examples/xml_reporter.py +254 -0
  370. truthound/plugins/hooks.py +558 -0
  371. truthound/plugins/lifecycle/__init__.py +43 -0
  372. truthound/plugins/lifecycle/hot_reload.py +402 -0
  373. truthound/plugins/lifecycle/manager.py +371 -0
  374. truthound/plugins/manager.py +736 -0
  375. truthound/plugins/registry.py +338 -0
  376. truthound/plugins/security/__init__.py +93 -0
  377. truthound/plugins/security/exceptions.py +332 -0
  378. truthound/plugins/security/policies.py +348 -0
  379. truthound/plugins/security/protocols.py +643 -0
  380. truthound/plugins/security/sandbox/__init__.py +45 -0
  381. truthound/plugins/security/sandbox/context.py +158 -0
  382. truthound/plugins/security/sandbox/engines/__init__.py +19 -0
  383. truthound/plugins/security/sandbox/engines/container.py +379 -0
  384. truthound/plugins/security/sandbox/engines/noop.py +144 -0
  385. truthound/plugins/security/sandbox/engines/process.py +336 -0
  386. truthound/plugins/security/sandbox/factory.py +211 -0
  387. truthound/plugins/security/signing/__init__.py +57 -0
  388. truthound/plugins/security/signing/service.py +330 -0
  389. truthound/plugins/security/signing/trust_store.py +368 -0
  390. truthound/plugins/security/signing/verifier.py +459 -0
  391. truthound/plugins/versioning/__init__.py +41 -0
  392. truthound/plugins/versioning/constraints.py +297 -0
  393. truthound/plugins/versioning/resolver.py +329 -0
  394. truthound/profiler/__init__.py +1729 -0
  395. truthound/profiler/_lazy.py +452 -0
  396. truthound/profiler/ab_testing/__init__.py +80 -0
  397. truthound/profiler/ab_testing/analysis.py +449 -0
  398. truthound/profiler/ab_testing/base.py +257 -0
  399. truthound/profiler/ab_testing/experiment.py +395 -0
  400. truthound/profiler/ab_testing/tracking.py +368 -0
  401. truthound/profiler/auto_threshold.py +1170 -0
  402. truthound/profiler/base.py +579 -0
  403. truthound/profiler/cache_patterns.py +911 -0
  404. truthound/profiler/caching.py +1303 -0
  405. truthound/profiler/column_profiler.py +712 -0
  406. truthound/profiler/comparison.py +1007 -0
  407. truthound/profiler/custom_patterns.py +1170 -0
  408. truthound/profiler/dashboard/__init__.py +50 -0
  409. truthound/profiler/dashboard/app.py +476 -0
  410. truthound/profiler/dashboard/components.py +457 -0
  411. truthound/profiler/dashboard/config.py +72 -0
  412. truthound/profiler/distributed/__init__.py +83 -0
  413. truthound/profiler/distributed/base.py +281 -0
  414. truthound/profiler/distributed/dask_backend.py +498 -0
  415. truthound/profiler/distributed/local_backend.py +293 -0
  416. truthound/profiler/distributed/profiler.py +304 -0
  417. truthound/profiler/distributed/ray_backend.py +374 -0
  418. truthound/profiler/distributed/spark_backend.py +375 -0
  419. truthound/profiler/distributed.py +1366 -0
  420. truthound/profiler/enterprise_sampling.py +1065 -0
  421. truthound/profiler/errors.py +488 -0
  422. truthound/profiler/evolution/__init__.py +91 -0
  423. truthound/profiler/evolution/alerts.py +426 -0
  424. truthound/profiler/evolution/changes.py +206 -0
  425. truthound/profiler/evolution/compatibility.py +365 -0
  426. truthound/profiler/evolution/detector.py +372 -0
  427. truthound/profiler/evolution/protocols.py +121 -0
  428. truthound/profiler/generators/__init__.py +48 -0
  429. truthound/profiler/generators/base.py +384 -0
  430. truthound/profiler/generators/ml_rules.py +375 -0
  431. truthound/profiler/generators/pattern_rules.py +384 -0
  432. truthound/profiler/generators/schema_rules.py +267 -0
  433. truthound/profiler/generators/stats_rules.py +324 -0
  434. truthound/profiler/generators/suite_generator.py +857 -0
  435. truthound/profiler/i18n.py +1542 -0
  436. truthound/profiler/incremental.py +554 -0
  437. truthound/profiler/incremental_validation.py +1710 -0
  438. truthound/profiler/integration/__init__.py +73 -0
  439. truthound/profiler/integration/adapters.py +345 -0
  440. truthound/profiler/integration/context.py +371 -0
  441. truthound/profiler/integration/executor.py +527 -0
  442. truthound/profiler/integration/naming.py +75 -0
  443. truthound/profiler/integration/protocols.py +243 -0
  444. truthound/profiler/memory.py +1185 -0
  445. truthound/profiler/migration/__init__.py +60 -0
  446. truthound/profiler/migration/base.py +345 -0
  447. truthound/profiler/migration/manager.py +444 -0
  448. truthound/profiler/migration/v1_0_to_v1_1.py +484 -0
  449. truthound/profiler/ml/__init__.py +73 -0
  450. truthound/profiler/ml/base.py +244 -0
  451. truthound/profiler/ml/classifier.py +507 -0
  452. truthound/profiler/ml/feature_extraction.py +604 -0
  453. truthound/profiler/ml/pretrained.py +448 -0
  454. truthound/profiler/ml_inference.py +1276 -0
  455. truthound/profiler/native_patterns.py +815 -0
  456. truthound/profiler/observability.py +1184 -0
  457. truthound/profiler/process_timeout.py +1566 -0
  458. truthound/profiler/progress.py +568 -0
  459. truthound/profiler/progress_callbacks.py +1734 -0
  460. truthound/profiler/quality.py +1345 -0
  461. truthound/profiler/resilience.py +1180 -0
  462. truthound/profiler/sampled_matcher.py +794 -0
  463. truthound/profiler/sampling.py +1288 -0
  464. truthound/profiler/scheduling/__init__.py +82 -0
  465. truthound/profiler/scheduling/protocols.py +214 -0
  466. truthound/profiler/scheduling/scheduler.py +474 -0
  467. truthound/profiler/scheduling/storage.py +457 -0
  468. truthound/profiler/scheduling/triggers.py +449 -0
  469. truthound/profiler/schema.py +603 -0
  470. truthound/profiler/streaming.py +685 -0
  471. truthound/profiler/streaming_patterns.py +1354 -0
  472. truthound/profiler/suite_cli.py +625 -0
  473. truthound/profiler/suite_config.py +789 -0
  474. truthound/profiler/suite_export.py +1268 -0
  475. truthound/profiler/table_profiler.py +547 -0
  476. truthound/profiler/timeout.py +565 -0
  477. truthound/profiler/validation.py +1532 -0
  478. truthound/profiler/visualization/__init__.py +118 -0
  479. truthound/profiler/visualization/base.py +346 -0
  480. truthound/profiler/visualization/generator.py +1259 -0
  481. truthound/profiler/visualization/plotly_renderer.py +811 -0
  482. truthound/profiler/visualization/renderers.py +669 -0
  483. truthound/profiler/visualization/sections.py +540 -0
  484. truthound/profiler/visualization.py +2122 -0
  485. truthound/profiler/yaml_validation.py +1151 -0
  486. truthound/py.typed +0 -0
  487. truthound/ratelimit/__init__.py +248 -0
  488. truthound/ratelimit/algorithms.py +1108 -0
  489. truthound/ratelimit/core.py +573 -0
  490. truthound/ratelimit/integration.py +532 -0
  491. truthound/ratelimit/limiter.py +663 -0
  492. truthound/ratelimit/middleware.py +700 -0
  493. truthound/ratelimit/policy.py +792 -0
  494. truthound/ratelimit/storage.py +763 -0
  495. truthound/rbac/__init__.py +340 -0
  496. truthound/rbac/core.py +976 -0
  497. truthound/rbac/integration.py +760 -0
  498. truthound/rbac/manager.py +1052 -0
  499. truthound/rbac/middleware.py +842 -0
  500. truthound/rbac/policy.py +954 -0
  501. truthound/rbac/storage.py +878 -0
  502. truthound/realtime/__init__.py +141 -0
  503. truthound/realtime/adapters/__init__.py +43 -0
  504. truthound/realtime/adapters/base.py +533 -0
  505. truthound/realtime/adapters/kafka.py +487 -0
  506. truthound/realtime/adapters/kinesis.py +479 -0
  507. truthound/realtime/adapters/mock.py +243 -0
  508. truthound/realtime/base.py +553 -0
  509. truthound/realtime/factory.py +382 -0
  510. truthound/realtime/incremental.py +660 -0
  511. truthound/realtime/processing/__init__.py +67 -0
  512. truthound/realtime/processing/exactly_once.py +575 -0
  513. truthound/realtime/processing/state.py +547 -0
  514. truthound/realtime/processing/windows.py +647 -0
  515. truthound/realtime/protocols.py +569 -0
  516. truthound/realtime/streaming.py +605 -0
  517. truthound/realtime/testing/__init__.py +32 -0
  518. truthound/realtime/testing/containers.py +615 -0
  519. truthound/realtime/testing/fixtures.py +484 -0
  520. truthound/report.py +280 -0
  521. truthound/reporters/__init__.py +46 -0
  522. truthound/reporters/_protocols.py +30 -0
  523. truthound/reporters/base.py +324 -0
  524. truthound/reporters/ci/__init__.py +66 -0
  525. truthound/reporters/ci/azure.py +436 -0
  526. truthound/reporters/ci/base.py +509 -0
  527. truthound/reporters/ci/bitbucket.py +567 -0
  528. truthound/reporters/ci/circleci.py +547 -0
  529. truthound/reporters/ci/detection.py +364 -0
  530. truthound/reporters/ci/factory.py +182 -0
  531. truthound/reporters/ci/github.py +388 -0
  532. truthound/reporters/ci/gitlab.py +471 -0
  533. truthound/reporters/ci/jenkins.py +525 -0
  534. truthound/reporters/console_reporter.py +299 -0
  535. truthound/reporters/factory.py +211 -0
  536. truthound/reporters/html_reporter.py +524 -0
  537. truthound/reporters/json_reporter.py +256 -0
  538. truthound/reporters/markdown_reporter.py +280 -0
  539. truthound/reporters/sdk/__init__.py +174 -0
  540. truthound/reporters/sdk/builder.py +558 -0
  541. truthound/reporters/sdk/mixins.py +1150 -0
  542. truthound/reporters/sdk/schema.py +1493 -0
  543. truthound/reporters/sdk/templates.py +666 -0
  544. truthound/reporters/sdk/testing.py +968 -0
  545. truthound/scanners.py +170 -0
  546. truthound/scheduling/__init__.py +122 -0
  547. truthound/scheduling/cron.py +1136 -0
  548. truthound/scheduling/presets.py +212 -0
  549. truthound/schema.py +275 -0
  550. truthound/secrets/__init__.py +173 -0
  551. truthound/secrets/base.py +618 -0
  552. truthound/secrets/cloud.py +682 -0
  553. truthound/secrets/integration.py +507 -0
  554. truthound/secrets/manager.py +633 -0
  555. truthound/secrets/oidc/__init__.py +172 -0
  556. truthound/secrets/oidc/base.py +902 -0
  557. truthound/secrets/oidc/credential_provider.py +623 -0
  558. truthound/secrets/oidc/exchangers.py +1001 -0
  559. truthound/secrets/oidc/github/__init__.py +110 -0
  560. truthound/secrets/oidc/github/claims.py +718 -0
  561. truthound/secrets/oidc/github/enhanced_provider.py +693 -0
  562. truthound/secrets/oidc/github/trust_policy.py +742 -0
  563. truthound/secrets/oidc/github/verification.py +723 -0
  564. truthound/secrets/oidc/github/workflow.py +691 -0
  565. truthound/secrets/oidc/providers.py +825 -0
  566. truthound/secrets/providers.py +506 -0
  567. truthound/secrets/resolver.py +495 -0
  568. truthound/stores/__init__.py +177 -0
  569. truthound/stores/backends/__init__.py +18 -0
  570. truthound/stores/backends/_protocols.py +340 -0
  571. truthound/stores/backends/azure_blob.py +530 -0
  572. truthound/stores/backends/concurrent_filesystem.py +915 -0
  573. truthound/stores/backends/connection_pool.py +1365 -0
  574. truthound/stores/backends/database.py +743 -0
  575. truthound/stores/backends/filesystem.py +538 -0
  576. truthound/stores/backends/gcs.py +399 -0
  577. truthound/stores/backends/memory.py +354 -0
  578. truthound/stores/backends/s3.py +434 -0
  579. truthound/stores/backpressure/__init__.py +84 -0
  580. truthound/stores/backpressure/base.py +375 -0
  581. truthound/stores/backpressure/circuit_breaker.py +434 -0
  582. truthound/stores/backpressure/monitor.py +376 -0
  583. truthound/stores/backpressure/strategies.py +677 -0
  584. truthound/stores/base.py +551 -0
  585. truthound/stores/batching/__init__.py +65 -0
  586. truthound/stores/batching/base.py +305 -0
  587. truthound/stores/batching/buffer.py +370 -0
  588. truthound/stores/batching/store.py +248 -0
  589. truthound/stores/batching/writer.py +521 -0
  590. truthound/stores/caching/__init__.py +60 -0
  591. truthound/stores/caching/backends.py +684 -0
  592. truthound/stores/caching/base.py +356 -0
  593. truthound/stores/caching/store.py +305 -0
  594. truthound/stores/compression/__init__.py +193 -0
  595. truthound/stores/compression/adaptive.py +694 -0
  596. truthound/stores/compression/base.py +514 -0
  597. truthound/stores/compression/pipeline.py +868 -0
  598. truthound/stores/compression/providers.py +672 -0
  599. truthound/stores/compression/streaming.py +832 -0
  600. truthound/stores/concurrency/__init__.py +81 -0
  601. truthound/stores/concurrency/atomic.py +556 -0
  602. truthound/stores/concurrency/index.py +775 -0
  603. truthound/stores/concurrency/locks.py +576 -0
  604. truthound/stores/concurrency/manager.py +482 -0
  605. truthound/stores/encryption/__init__.py +297 -0
  606. truthound/stores/encryption/base.py +952 -0
  607. truthound/stores/encryption/keys.py +1191 -0
  608. truthound/stores/encryption/pipeline.py +903 -0
  609. truthound/stores/encryption/providers.py +953 -0
  610. truthound/stores/encryption/streaming.py +950 -0
  611. truthound/stores/expectations.py +227 -0
  612. truthound/stores/factory.py +246 -0
  613. truthound/stores/migration/__init__.py +75 -0
  614. truthound/stores/migration/base.py +480 -0
  615. truthound/stores/migration/manager.py +347 -0
  616. truthound/stores/migration/registry.py +382 -0
  617. truthound/stores/migration/store.py +559 -0
  618. truthound/stores/observability/__init__.py +106 -0
  619. truthound/stores/observability/audit.py +718 -0
  620. truthound/stores/observability/config.py +270 -0
  621. truthound/stores/observability/factory.py +208 -0
  622. truthound/stores/observability/metrics.py +636 -0
  623. truthound/stores/observability/protocols.py +410 -0
  624. truthound/stores/observability/store.py +570 -0
  625. truthound/stores/observability/tracing.py +784 -0
  626. truthound/stores/replication/__init__.py +76 -0
  627. truthound/stores/replication/base.py +260 -0
  628. truthound/stores/replication/monitor.py +269 -0
  629. truthound/stores/replication/store.py +439 -0
  630. truthound/stores/replication/syncer.py +391 -0
  631. truthound/stores/results.py +359 -0
  632. truthound/stores/retention/__init__.py +77 -0
  633. truthound/stores/retention/base.py +378 -0
  634. truthound/stores/retention/policies.py +621 -0
  635. truthound/stores/retention/scheduler.py +279 -0
  636. truthound/stores/retention/store.py +526 -0
  637. truthound/stores/streaming/__init__.py +138 -0
  638. truthound/stores/streaming/base.py +801 -0
  639. truthound/stores/streaming/database.py +984 -0
  640. truthound/stores/streaming/filesystem.py +719 -0
  641. truthound/stores/streaming/reader.py +629 -0
  642. truthound/stores/streaming/s3.py +843 -0
  643. truthound/stores/streaming/writer.py +790 -0
  644. truthound/stores/tiering/__init__.py +108 -0
  645. truthound/stores/tiering/base.py +462 -0
  646. truthound/stores/tiering/manager.py +249 -0
  647. truthound/stores/tiering/policies.py +692 -0
  648. truthound/stores/tiering/store.py +526 -0
  649. truthound/stores/versioning/__init__.py +56 -0
  650. truthound/stores/versioning/base.py +376 -0
  651. truthound/stores/versioning/store.py +660 -0
  652. truthound/stores/versioning/strategies.py +353 -0
  653. truthound/types.py +56 -0
  654. truthound/validators/__init__.py +774 -0
  655. truthound/validators/aggregate/__init__.py +27 -0
  656. truthound/validators/aggregate/central.py +116 -0
  657. truthound/validators/aggregate/extremes.py +116 -0
  658. truthound/validators/aggregate/spread.py +118 -0
  659. truthound/validators/aggregate/sum.py +64 -0
  660. truthound/validators/aggregate/type.py +78 -0
  661. truthound/validators/anomaly/__init__.py +93 -0
  662. truthound/validators/anomaly/base.py +431 -0
  663. truthound/validators/anomaly/ml_based.py +1190 -0
  664. truthound/validators/anomaly/multivariate.py +647 -0
  665. truthound/validators/anomaly/statistical.py +599 -0
  666. truthound/validators/base.py +1089 -0
  667. truthound/validators/business_rule/__init__.py +46 -0
  668. truthound/validators/business_rule/base.py +147 -0
  669. truthound/validators/business_rule/checksum.py +509 -0
  670. truthound/validators/business_rule/financial.py +526 -0
  671. truthound/validators/cache.py +733 -0
  672. truthound/validators/completeness/__init__.py +39 -0
  673. truthound/validators/completeness/conditional.py +73 -0
  674. truthound/validators/completeness/default.py +98 -0
  675. truthound/validators/completeness/empty.py +103 -0
  676. truthound/validators/completeness/nan.py +337 -0
  677. truthound/validators/completeness/null.py +152 -0
  678. truthound/validators/cross_table/__init__.py +17 -0
  679. truthound/validators/cross_table/aggregate.py +333 -0
  680. truthound/validators/cross_table/row_count.py +122 -0
  681. truthound/validators/datetime/__init__.py +29 -0
  682. truthound/validators/datetime/format.py +78 -0
  683. truthound/validators/datetime/freshness.py +269 -0
  684. truthound/validators/datetime/order.py +73 -0
  685. truthound/validators/datetime/parseable.py +185 -0
  686. truthound/validators/datetime/range.py +202 -0
  687. truthound/validators/datetime/timezone.py +69 -0
  688. truthound/validators/distribution/__init__.py +49 -0
  689. truthound/validators/distribution/distribution.py +128 -0
  690. truthound/validators/distribution/monotonic.py +119 -0
  691. truthound/validators/distribution/outlier.py +178 -0
  692. truthound/validators/distribution/quantile.py +80 -0
  693. truthound/validators/distribution/range.py +254 -0
  694. truthound/validators/distribution/set.py +125 -0
  695. truthound/validators/distribution/statistical.py +459 -0
  696. truthound/validators/drift/__init__.py +79 -0
  697. truthound/validators/drift/base.py +427 -0
  698. truthound/validators/drift/multi_feature.py +401 -0
  699. truthound/validators/drift/numeric.py +395 -0
  700. truthound/validators/drift/psi.py +446 -0
  701. truthound/validators/drift/statistical.py +510 -0
  702. truthound/validators/enterprise.py +1658 -0
  703. truthound/validators/geospatial/__init__.py +80 -0
  704. truthound/validators/geospatial/base.py +97 -0
  705. truthound/validators/geospatial/boundary.py +238 -0
  706. truthound/validators/geospatial/coordinate.py +351 -0
  707. truthound/validators/geospatial/distance.py +399 -0
  708. truthound/validators/geospatial/polygon.py +665 -0
  709. truthound/validators/i18n/__init__.py +308 -0
  710. truthound/validators/i18n/bidi.py +571 -0
  711. truthound/validators/i18n/catalogs.py +570 -0
  712. truthound/validators/i18n/dialects.py +763 -0
  713. truthound/validators/i18n/extended_catalogs.py +549 -0
  714. truthound/validators/i18n/formatting.py +1434 -0
  715. truthound/validators/i18n/loader.py +1020 -0
  716. truthound/validators/i18n/messages.py +521 -0
  717. truthound/validators/i18n/plural.py +683 -0
  718. truthound/validators/i18n/protocols.py +855 -0
  719. truthound/validators/i18n/tms.py +1162 -0
  720. truthound/validators/localization/__init__.py +53 -0
  721. truthound/validators/localization/base.py +122 -0
  722. truthound/validators/localization/chinese.py +362 -0
  723. truthound/validators/localization/japanese.py +275 -0
  724. truthound/validators/localization/korean.py +524 -0
  725. truthound/validators/memory/__init__.py +94 -0
  726. truthound/validators/memory/approximate_knn.py +506 -0
  727. truthound/validators/memory/base.py +547 -0
  728. truthound/validators/memory/sgd_online.py +719 -0
  729. truthound/validators/memory/streaming_ecdf.py +753 -0
  730. truthound/validators/ml_feature/__init__.py +54 -0
  731. truthound/validators/ml_feature/base.py +249 -0
  732. truthound/validators/ml_feature/correlation.py +299 -0
  733. truthound/validators/ml_feature/leakage.py +344 -0
  734. truthound/validators/ml_feature/null_impact.py +270 -0
  735. truthound/validators/ml_feature/scale.py +264 -0
  736. truthound/validators/multi_column/__init__.py +89 -0
  737. truthound/validators/multi_column/arithmetic.py +284 -0
  738. truthound/validators/multi_column/base.py +231 -0
  739. truthound/validators/multi_column/comparison.py +273 -0
  740. truthound/validators/multi_column/consistency.py +312 -0
  741. truthound/validators/multi_column/statistical.py +299 -0
  742. truthound/validators/optimization/__init__.py +164 -0
  743. truthound/validators/optimization/aggregation.py +563 -0
  744. truthound/validators/optimization/covariance.py +556 -0
  745. truthound/validators/optimization/geo.py +626 -0
  746. truthound/validators/optimization/graph.py +587 -0
  747. truthound/validators/optimization/orchestrator.py +970 -0
  748. truthound/validators/optimization/profiling.py +1312 -0
  749. truthound/validators/privacy/__init__.py +223 -0
  750. truthound/validators/privacy/base.py +635 -0
  751. truthound/validators/privacy/ccpa.py +670 -0
  752. truthound/validators/privacy/gdpr.py +728 -0
  753. truthound/validators/privacy/global_patterns.py +604 -0
  754. truthound/validators/privacy/plugins.py +867 -0
  755. truthound/validators/profiling/__init__.py +52 -0
  756. truthound/validators/profiling/base.py +175 -0
  757. truthound/validators/profiling/cardinality.py +312 -0
  758. truthound/validators/profiling/entropy.py +391 -0
  759. truthound/validators/profiling/frequency.py +455 -0
  760. truthound/validators/pushdown_support.py +660 -0
  761. truthound/validators/query/__init__.py +91 -0
  762. truthound/validators/query/aggregate.py +346 -0
  763. truthound/validators/query/base.py +246 -0
  764. truthound/validators/query/column.py +249 -0
  765. truthound/validators/query/expression.py +274 -0
  766. truthound/validators/query/result.py +323 -0
  767. truthound/validators/query/row_count.py +264 -0
  768. truthound/validators/referential/__init__.py +80 -0
  769. truthound/validators/referential/base.py +395 -0
  770. truthound/validators/referential/cascade.py +391 -0
  771. truthound/validators/referential/circular.py +563 -0
  772. truthound/validators/referential/foreign_key.py +624 -0
  773. truthound/validators/referential/orphan.py +485 -0
  774. truthound/validators/registry.py +112 -0
  775. truthound/validators/schema/__init__.py +41 -0
  776. truthound/validators/schema/column_count.py +142 -0
  777. truthound/validators/schema/column_exists.py +80 -0
  778. truthound/validators/schema/column_order.py +82 -0
  779. truthound/validators/schema/column_pair.py +85 -0
  780. truthound/validators/schema/column_pair_set.py +195 -0
  781. truthound/validators/schema/column_type.py +94 -0
  782. truthound/validators/schema/multi_column.py +53 -0
  783. truthound/validators/schema/multi_column_aggregate.py +175 -0
  784. truthound/validators/schema/referential.py +274 -0
  785. truthound/validators/schema/table_schema.py +91 -0
  786. truthound/validators/schema_validator.py +219 -0
  787. truthound/validators/sdk/__init__.py +250 -0
  788. truthound/validators/sdk/builder.py +680 -0
  789. truthound/validators/sdk/decorators.py +474 -0
  790. truthound/validators/sdk/enterprise/__init__.py +211 -0
  791. truthound/validators/sdk/enterprise/docs.py +725 -0
  792. truthound/validators/sdk/enterprise/fuzzing.py +659 -0
  793. truthound/validators/sdk/enterprise/licensing.py +709 -0
  794. truthound/validators/sdk/enterprise/manager.py +543 -0
  795. truthound/validators/sdk/enterprise/resources.py +628 -0
  796. truthound/validators/sdk/enterprise/sandbox.py +766 -0
  797. truthound/validators/sdk/enterprise/signing.py +603 -0
  798. truthound/validators/sdk/enterprise/templates.py +865 -0
  799. truthound/validators/sdk/enterprise/versioning.py +659 -0
  800. truthound/validators/sdk/templates.py +757 -0
  801. truthound/validators/sdk/testing.py +807 -0
  802. truthound/validators/security/__init__.py +181 -0
  803. truthound/validators/security/redos/__init__.py +182 -0
  804. truthound/validators/security/redos/core.py +861 -0
  805. truthound/validators/security/redos/cpu_monitor.py +593 -0
  806. truthound/validators/security/redos/cve_database.py +791 -0
  807. truthound/validators/security/redos/ml/__init__.py +155 -0
  808. truthound/validators/security/redos/ml/base.py +785 -0
  809. truthound/validators/security/redos/ml/datasets.py +618 -0
  810. truthound/validators/security/redos/ml/features.py +359 -0
  811. truthound/validators/security/redos/ml/models.py +1000 -0
  812. truthound/validators/security/redos/ml/predictor.py +507 -0
  813. truthound/validators/security/redos/ml/storage.py +632 -0
  814. truthound/validators/security/redos/ml/training.py +571 -0
  815. truthound/validators/security/redos/ml_analyzer.py +937 -0
  816. truthound/validators/security/redos/optimizer.py +674 -0
  817. truthound/validators/security/redos/profiler.py +682 -0
  818. truthound/validators/security/redos/re2_engine.py +709 -0
  819. truthound/validators/security/redos.py +886 -0
  820. truthound/validators/security/sql_security.py +1247 -0
  821. truthound/validators/streaming/__init__.py +126 -0
  822. truthound/validators/streaming/base.py +292 -0
  823. truthound/validators/streaming/completeness.py +210 -0
  824. truthound/validators/streaming/mixin.py +575 -0
  825. truthound/validators/streaming/range.py +308 -0
  826. truthound/validators/streaming/sources.py +846 -0
  827. truthound/validators/string/__init__.py +57 -0
  828. truthound/validators/string/casing.py +158 -0
  829. truthound/validators/string/charset.py +96 -0
  830. truthound/validators/string/format.py +501 -0
  831. truthound/validators/string/json.py +77 -0
  832. truthound/validators/string/json_schema.py +184 -0
  833. truthound/validators/string/length.py +104 -0
  834. truthound/validators/string/like_pattern.py +237 -0
  835. truthound/validators/string/regex.py +202 -0
  836. truthound/validators/string/regex_extended.py +435 -0
  837. truthound/validators/table/__init__.py +88 -0
  838. truthound/validators/table/base.py +78 -0
  839. truthound/validators/table/column_count.py +198 -0
  840. truthound/validators/table/freshness.py +362 -0
  841. truthound/validators/table/row_count.py +251 -0
  842. truthound/validators/table/schema.py +333 -0
  843. truthound/validators/table/size.py +285 -0
  844. truthound/validators/timeout/__init__.py +102 -0
  845. truthound/validators/timeout/advanced/__init__.py +247 -0
  846. truthound/validators/timeout/advanced/circuit_breaker.py +675 -0
  847. truthound/validators/timeout/advanced/prediction.py +773 -0
  848. truthound/validators/timeout/advanced/priority.py +618 -0
  849. truthound/validators/timeout/advanced/redis_backend.py +770 -0
  850. truthound/validators/timeout/advanced/retry.py +721 -0
  851. truthound/validators/timeout/advanced/sampling.py +788 -0
  852. truthound/validators/timeout/advanced/sla.py +661 -0
  853. truthound/validators/timeout/advanced/telemetry.py +804 -0
  854. truthound/validators/timeout/cascade.py +477 -0
  855. truthound/validators/timeout/deadline.py +657 -0
  856. truthound/validators/timeout/degradation.py +525 -0
  857. truthound/validators/timeout/distributed.py +597 -0
  858. truthound/validators/timeseries/__init__.py +89 -0
  859. truthound/validators/timeseries/base.py +326 -0
  860. truthound/validators/timeseries/completeness.py +617 -0
  861. truthound/validators/timeseries/gap.py +485 -0
  862. truthound/validators/timeseries/monotonic.py +310 -0
  863. truthound/validators/timeseries/seasonality.py +422 -0
  864. truthound/validators/timeseries/trend.py +510 -0
  865. truthound/validators/uniqueness/__init__.py +59 -0
  866. truthound/validators/uniqueness/approximate.py +475 -0
  867. truthound/validators/uniqueness/distinct_values.py +253 -0
  868. truthound/validators/uniqueness/duplicate.py +118 -0
  869. truthound/validators/uniqueness/primary_key.py +140 -0
  870. truthound/validators/uniqueness/unique.py +191 -0
  871. truthound/validators/uniqueness/within_record.py +599 -0
  872. truthound/validators/utils.py +756 -0
  873. truthound-1.0.8.dist-info/METADATA +474 -0
  874. truthound-1.0.8.dist-info/RECORD +877 -0
  875. truthound-1.0.8.dist-info/WHEEL +4 -0
  876. truthound-1.0.8.dist-info/entry_points.txt +2 -0
  877. truthound-1.0.8.dist-info/licenses/LICENSE +190 -0
@@ -0,0 +1,804 @@
1
+ """OpenTelemetry integration for distributed tracing and metrics.
2
+
3
+ This module provides comprehensive observability for timeout operations:
4
+ - Distributed tracing across service boundaries
5
+ - Metrics collection for timeout events
6
+ - Span context propagation
7
+ - Multiple exporter backends (Console, OTLP, etc.)
8
+
9
+ The design follows OpenTelemetry conventions while providing a clean
10
+ abstraction layer for the Truthound timeout system.
11
+
12
+ Example:
13
+ from truthound.validators.timeout.advanced.telemetry import (
14
+ TelemetryProvider,
15
+ TracingConfig,
16
+ trace_operation,
17
+ )
18
+
19
+ # Configure telemetry
20
+ config = TracingConfig(
21
+ service_name="truthound-validator",
22
+ exporter="otlp",
23
+ endpoint="http://jaeger:4317",
24
+ )
25
+
26
+ provider = TelemetryProvider(config)
27
+
28
+ # Trace an operation
29
+ with provider.trace("validate_batch") as span:
30
+ span.set_attribute("batch_size", 1000)
31
+ result = validate(data)
32
+ span.set_attribute("result", result.status)
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import contextlib
38
+ import functools
39
+ import logging
40
+ import threading
41
+ import time
42
+ import uuid
43
+ from abc import ABC, abstractmethod
44
+ from contextlib import contextmanager
45
+ from dataclasses import dataclass, field
46
+ from datetime import datetime, timezone
47
+ from enum import Enum
48
+ from typing import Any, Callable, Generator, TypeVar
49
+
50
+ logger = logging.getLogger(__name__)
51
+
52
+ T = TypeVar("T")
53
+
54
+
55
+ class SpanStatus(str, Enum):
56
+ """Status codes for spans."""
57
+
58
+ UNSET = "unset"
59
+ OK = "ok"
60
+ ERROR = "error"
61
+
62
+
63
+ class SpanKind(str, Enum):
64
+ """Kind of span."""
65
+
66
+ INTERNAL = "internal"
67
+ SERVER = "server"
68
+ CLIENT = "client"
69
+ PRODUCER = "producer"
70
+ CONSUMER = "consumer"
71
+
72
+
73
+ @dataclass
74
+ class SpanContext:
75
+ """Context for span propagation across service boundaries.
76
+
77
+ Attributes:
78
+ trace_id: Unique identifier for the trace
79
+ span_id: Unique identifier for this span
80
+ parent_span_id: Parent span ID (None if root)
81
+ trace_flags: Trace flags (e.g., sampling)
82
+ trace_state: Vendor-specific trace state
83
+ """
84
+
85
+ trace_id: str
86
+ span_id: str
87
+ parent_span_id: str | None = None
88
+ trace_flags: int = 0
89
+ trace_state: dict[str, str] = field(default_factory=dict)
90
+
91
+ @classmethod
92
+ def create_root(cls) -> "SpanContext":
93
+ """Create a root span context."""
94
+ return cls(
95
+ trace_id=uuid.uuid4().hex,
96
+ span_id=uuid.uuid4().hex[:16],
97
+ )
98
+
99
+ @classmethod
100
+ def create_child(cls, parent: "SpanContext") -> "SpanContext":
101
+ """Create a child span context."""
102
+ return cls(
103
+ trace_id=parent.trace_id,
104
+ span_id=uuid.uuid4().hex[:16],
105
+ parent_span_id=parent.span_id,
106
+ trace_flags=parent.trace_flags,
107
+ trace_state=dict(parent.trace_state),
108
+ )
109
+
110
+ def to_dict(self) -> dict[str, Any]:
111
+ """Convert to dictionary for serialization."""
112
+ return {
113
+ "trace_id": self.trace_id,
114
+ "span_id": self.span_id,
115
+ "parent_span_id": self.parent_span_id,
116
+ "trace_flags": self.trace_flags,
117
+ "trace_state": self.trace_state,
118
+ }
119
+
120
+ @classmethod
121
+ def from_dict(cls, data: dict[str, Any]) -> "SpanContext":
122
+ """Create from dictionary."""
123
+ return cls(
124
+ trace_id=data["trace_id"],
125
+ span_id=data["span_id"],
126
+ parent_span_id=data.get("parent_span_id"),
127
+ trace_flags=data.get("trace_flags", 0),
128
+ trace_state=data.get("trace_state", {}),
129
+ )
130
+
131
+ def to_w3c_traceparent(self) -> str:
132
+ """Convert to W3C traceparent header format."""
133
+ return f"00-{self.trace_id}-{self.span_id}-{self.trace_flags:02x}"
134
+
135
+ @classmethod
136
+ def from_w3c_traceparent(cls, header: str) -> "SpanContext":
137
+ """Parse W3C traceparent header."""
138
+ parts = header.split("-")
139
+ if len(parts) != 4:
140
+ raise ValueError(f"Invalid traceparent format: {header}")
141
+ return cls(
142
+ trace_id=parts[1],
143
+ span_id=parts[2],
144
+ trace_flags=int(parts[3], 16),
145
+ )
146
+
147
+
148
+ @dataclass
149
+ class TracingSpan:
150
+ """Represents a tracing span.
151
+
152
+ Attributes:
153
+ name: Span name
154
+ context: Span context
155
+ kind: Span kind
156
+ start_time: Start timestamp
157
+ end_time: End timestamp (None if still active)
158
+ attributes: Span attributes
159
+ events: Span events
160
+ status: Span status
161
+ status_message: Status message for errors
162
+ """
163
+
164
+ name: str
165
+ context: SpanContext
166
+ kind: SpanKind = SpanKind.INTERNAL
167
+ start_time: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
168
+ end_time: datetime | None = None
169
+ attributes: dict[str, Any] = field(default_factory=dict)
170
+ events: list[dict[str, Any]] = field(default_factory=list)
171
+ status: SpanStatus = SpanStatus.UNSET
172
+ status_message: str = ""
173
+
174
+ def set_attribute(self, key: str, value: Any) -> None:
175
+ """Set a span attribute."""
176
+ self.attributes[key] = value
177
+
178
+ def set_attributes(self, attributes: dict[str, Any]) -> None:
179
+ """Set multiple attributes."""
180
+ self.attributes.update(attributes)
181
+
182
+ def add_event(
183
+ self,
184
+ name: str,
185
+ attributes: dict[str, Any] | None = None,
186
+ timestamp: datetime | None = None,
187
+ ) -> None:
188
+ """Add an event to the span."""
189
+ self.events.append({
190
+ "name": name,
191
+ "timestamp": (timestamp or datetime.now(timezone.utc)).isoformat(),
192
+ "attributes": attributes or {},
193
+ })
194
+
195
+ def set_status(self, status: SpanStatus, message: str = "") -> None:
196
+ """Set span status."""
197
+ self.status = status
198
+ self.status_message = message
199
+
200
+ def set_ok(self) -> None:
201
+ """Mark span as OK."""
202
+ self.set_status(SpanStatus.OK)
203
+
204
+ def set_error(self, message: str = "") -> None:
205
+ """Mark span as error."""
206
+ self.set_status(SpanStatus.ERROR, message)
207
+
208
+ def record_exception(self, exception: Exception) -> None:
209
+ """Record an exception."""
210
+ self.add_event(
211
+ "exception",
212
+ {
213
+ "exception.type": type(exception).__name__,
214
+ "exception.message": str(exception),
215
+ },
216
+ )
217
+ self.set_error(str(exception))
218
+
219
+ def end(self, end_time: datetime | None = None) -> None:
220
+ """End the span."""
221
+ self.end_time = end_time or datetime.now(timezone.utc)
222
+
223
+ @property
224
+ def duration_ms(self) -> float | None:
225
+ """Get span duration in milliseconds."""
226
+ if self.end_time is None:
227
+ return None
228
+ delta = self.end_time - self.start_time
229
+ return delta.total_seconds() * 1000
230
+
231
+ def to_dict(self) -> dict[str, Any]:
232
+ """Convert to dictionary."""
233
+ return {
234
+ "name": self.name,
235
+ "context": self.context.to_dict(),
236
+ "kind": self.kind.value,
237
+ "start_time": self.start_time.isoformat(),
238
+ "end_time": self.end_time.isoformat() if self.end_time else None,
239
+ "duration_ms": self.duration_ms,
240
+ "attributes": self.attributes,
241
+ "events": self.events,
242
+ "status": self.status.value,
243
+ "status_message": self.status_message,
244
+ }
245
+
246
+
247
+ class TelemetryExporter(ABC):
248
+ """Base class for telemetry exporters."""
249
+
250
+ @abstractmethod
251
+ def export_span(self, span: TracingSpan) -> bool:
252
+ """Export a completed span.
253
+
254
+ Args:
255
+ span: Span to export
256
+
257
+ Returns:
258
+ True if export succeeded
259
+ """
260
+ pass
261
+
262
+ @abstractmethod
263
+ def export_metrics(self, metrics: dict[str, Any]) -> bool:
264
+ """Export metrics.
265
+
266
+ Args:
267
+ metrics: Metrics to export
268
+
269
+ Returns:
270
+ True if export succeeded
271
+ """
272
+ pass
273
+
274
+ @abstractmethod
275
+ def shutdown(self) -> None:
276
+ """Shutdown the exporter."""
277
+ pass
278
+
279
+
280
+ class ConsoleExporter(TelemetryExporter):
281
+ """Exporter that prints to console (for development/debugging)."""
282
+
283
+ def __init__(self, verbose: bool = True):
284
+ """Initialize console exporter.
285
+
286
+ Args:
287
+ verbose: Whether to print detailed output
288
+ """
289
+ self.verbose = verbose
290
+
291
+ def export_span(self, span: TracingSpan) -> bool:
292
+ """Export span to console."""
293
+ if self.verbose:
294
+ print(f"[SPAN] {span.name}")
295
+ print(f" Trace ID: {span.context.trace_id}")
296
+ print(f" Span ID: {span.context.span_id}")
297
+ print(f" Duration: {span.duration_ms:.2f}ms")
298
+ print(f" Status: {span.status.value}")
299
+ if span.attributes:
300
+ print(f" Attributes: {span.attributes}")
301
+ else:
302
+ print(
303
+ f"[SPAN] {span.name} - {span.duration_ms:.2f}ms - {span.status.value}"
304
+ )
305
+ return True
306
+
307
+ def export_metrics(self, metrics: dict[str, Any]) -> bool:
308
+ """Export metrics to console."""
309
+ print(f"[METRICS] {metrics}")
310
+ return True
311
+
312
+ def shutdown(self) -> None:
313
+ """No-op for console exporter."""
314
+ pass
315
+
316
+
317
+ class OTLPExporter(TelemetryExporter):
318
+ """OpenTelemetry Protocol (OTLP) exporter.
319
+
320
+ Note: Actual OTLP export requires opentelemetry-exporter-otlp package.
321
+ This implementation provides the interface and buffers spans locally.
322
+ """
323
+
324
+ def __init__(
325
+ self,
326
+ endpoint: str = "http://localhost:4317",
327
+ headers: dict[str, str] | None = None,
328
+ timeout: float = 10.0,
329
+ ):
330
+ """Initialize OTLP exporter.
331
+
332
+ Args:
333
+ endpoint: OTLP endpoint URL
334
+ headers: Optional headers for authentication
335
+ timeout: Export timeout in seconds
336
+ """
337
+ self.endpoint = endpoint
338
+ self.headers = headers or {}
339
+ self.timeout = timeout
340
+ self._buffer: list[TracingSpan] = []
341
+ self._metrics_buffer: list[dict[str, Any]] = []
342
+ self._lock = threading.Lock()
343
+ self._shutdown = False
344
+
345
+ def export_span(self, span: TracingSpan) -> bool:
346
+ """Buffer span for export."""
347
+ if self._shutdown:
348
+ return False
349
+
350
+ with self._lock:
351
+ self._buffer.append(span)
352
+
353
+ # In production, this would send to OTLP endpoint
354
+ # For now, we buffer and log
355
+ logger.debug(f"OTLP: Buffered span {span.name} ({span.context.span_id})")
356
+ return True
357
+
358
+ def export_metrics(self, metrics: dict[str, Any]) -> bool:
359
+ """Buffer metrics for export."""
360
+ if self._shutdown:
361
+ return False
362
+
363
+ with self._lock:
364
+ self._metrics_buffer.append(metrics)
365
+
366
+ logger.debug(f"OTLP: Buffered metrics {metrics.get('name', 'unknown')}")
367
+ return True
368
+
369
+ def flush(self) -> int:
370
+ """Flush buffered data.
371
+
372
+ Returns:
373
+ Number of items flushed
374
+ """
375
+ with self._lock:
376
+ count = len(self._buffer) + len(self._metrics_buffer)
377
+ # In production, this would send to OTLP endpoint
378
+ self._buffer.clear()
379
+ self._metrics_buffer.clear()
380
+ return count
381
+
382
+ def shutdown(self) -> None:
383
+ """Shutdown the exporter."""
384
+ self._shutdown = True
385
+ self.flush()
386
+
387
+
388
+ @dataclass
389
+ class TracingConfig:
390
+ """Configuration for tracing.
391
+
392
+ Attributes:
393
+ service_name: Name of the service
394
+ service_version: Version of the service
395
+ environment: Deployment environment
396
+ exporter_type: Type of exporter (console, otlp)
397
+ endpoint: OTLP endpoint URL
398
+ headers: Authentication headers
399
+ sample_rate: Sampling rate (0.0-1.0)
400
+ enabled: Whether tracing is enabled
401
+ """
402
+
403
+ service_name: str = "truthound"
404
+ service_version: str = "0.2.0"
405
+ environment: str = "development"
406
+ exporter_type: str = "console"
407
+ endpoint: str = "http://localhost:4317"
408
+ headers: dict[str, str] = field(default_factory=dict)
409
+ sample_rate: float = 1.0
410
+ enabled: bool = True
411
+
412
+
413
+ @dataclass
414
+ class MetricsConfig:
415
+ """Configuration for metrics collection.
416
+
417
+ Attributes:
418
+ enabled: Whether metrics are enabled
419
+ export_interval: Seconds between exports
420
+ histogram_buckets: Buckets for histogram metrics
421
+ """
422
+
423
+ enabled: bool = True
424
+ export_interval: float = 60.0
425
+ histogram_buckets: list[float] = field(
426
+ default_factory=lambda: [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000]
427
+ )
428
+
429
+
430
+ class MetricsCollector:
431
+ """Collector for timeout-related metrics.
432
+
433
+ Collects and aggregates metrics for:
434
+ - Execution times
435
+ - Timeout counts
436
+ - Retry counts
437
+ - Circuit breaker state changes
438
+ """
439
+
440
+ def __init__(self, config: MetricsConfig | None = None):
441
+ """Initialize metrics collector.
442
+
443
+ Args:
444
+ config: Metrics configuration
445
+ """
446
+ self.config = config or MetricsConfig()
447
+ self._counters: dict[str, int] = {}
448
+ self._histograms: dict[str, list[float]] = {}
449
+ self._gauges: dict[str, float] = {}
450
+ self._lock = threading.Lock()
451
+
452
+ def increment(self, name: str, value: int = 1, labels: dict[str, str] | None = None) -> None:
453
+ """Increment a counter.
454
+
455
+ Args:
456
+ name: Counter name
457
+ value: Increment value
458
+ labels: Optional labels
459
+ """
460
+ key = self._make_key(name, labels)
461
+ with self._lock:
462
+ self._counters[key] = self._counters.get(key, 0) + value
463
+
464
+ def record_histogram(
465
+ self,
466
+ name: str,
467
+ value: float,
468
+ labels: dict[str, str] | None = None,
469
+ ) -> None:
470
+ """Record a histogram value.
471
+
472
+ Args:
473
+ name: Histogram name
474
+ value: Value to record
475
+ labels: Optional labels
476
+ """
477
+ key = self._make_key(name, labels)
478
+ with self._lock:
479
+ if key not in self._histograms:
480
+ self._histograms[key] = []
481
+ self._histograms[key].append(value)
482
+
483
+ def set_gauge(self, name: str, value: float, labels: dict[str, str] | None = None) -> None:
484
+ """Set a gauge value.
485
+
486
+ Args:
487
+ name: Gauge name
488
+ value: Value to set
489
+ labels: Optional labels
490
+ """
491
+ key = self._make_key(name, labels)
492
+ with self._lock:
493
+ self._gauges[key] = value
494
+
495
+ def _make_key(self, name: str, labels: dict[str, str] | None) -> str:
496
+ """Create a key for metrics storage."""
497
+ if not labels:
498
+ return name
499
+ label_str = ",".join(f"{k}={v}" for k, v in sorted(labels.items()))
500
+ return f"{name}{{{label_str}}}"
501
+
502
+ def get_metrics(self) -> dict[str, Any]:
503
+ """Get all collected metrics.
504
+
505
+ Returns:
506
+ Dictionary of all metrics
507
+ """
508
+ with self._lock:
509
+ return {
510
+ "counters": dict(self._counters),
511
+ "histograms": {k: self._compute_histogram_stats(v) for k, v in self._histograms.items()},
512
+ "gauges": dict(self._gauges),
513
+ }
514
+
515
+ def _compute_histogram_stats(self, values: list[float]) -> dict[str, Any]:
516
+ """Compute histogram statistics."""
517
+ if not values:
518
+ return {"count": 0}
519
+
520
+ sorted_values = sorted(values)
521
+ n = len(sorted_values)
522
+
523
+ return {
524
+ "count": n,
525
+ "sum": sum(values),
526
+ "min": sorted_values[0],
527
+ "max": sorted_values[-1],
528
+ "mean": sum(values) / n,
529
+ "p50": sorted_values[n // 2],
530
+ "p90": sorted_values[int(n * 0.9)],
531
+ "p99": sorted_values[int(n * 0.99)] if n >= 100 else sorted_values[-1],
532
+ }
533
+
534
+ def clear(self) -> None:
535
+ """Clear all metrics."""
536
+ with self._lock:
537
+ self._counters.clear()
538
+ self._histograms.clear()
539
+ self._gauges.clear()
540
+
541
+
542
+ class TelemetryProvider:
543
+ """Main provider for telemetry (tracing and metrics).
544
+
545
+ This class manages the lifecycle of tracers and metrics collectors,
546
+ providing a unified interface for observability.
547
+
548
+ Example:
549
+ provider = TelemetryProvider(TracingConfig(
550
+ service_name="my-validator",
551
+ exporter_type="otlp",
552
+ ))
553
+
554
+ with provider.trace("validate") as span:
555
+ span.set_attribute("rows", 10000)
556
+ result = validate(data)
557
+ """
558
+
559
+ def __init__(
560
+ self,
561
+ tracing_config: TracingConfig | None = None,
562
+ metrics_config: MetricsConfig | None = None,
563
+ ):
564
+ """Initialize telemetry provider.
565
+
566
+ Args:
567
+ tracing_config: Tracing configuration
568
+ metrics_config: Metrics configuration
569
+ """
570
+ self.tracing_config = tracing_config or TracingConfig()
571
+ self.metrics_config = metrics_config or MetricsConfig()
572
+ self._exporter = self._create_exporter()
573
+ self._metrics = MetricsCollector(self.metrics_config)
574
+ self._context_stack: list[SpanContext] = []
575
+ self._lock = threading.Lock()
576
+
577
+ def _create_exporter(self) -> TelemetryExporter:
578
+ """Create the appropriate exporter."""
579
+ if self.tracing_config.exporter_type == "otlp":
580
+ return OTLPExporter(
581
+ endpoint=self.tracing_config.endpoint,
582
+ headers=self.tracing_config.headers,
583
+ )
584
+ return ConsoleExporter()
585
+
586
+ @contextmanager
587
+ def trace(
588
+ self,
589
+ name: str,
590
+ kind: SpanKind = SpanKind.INTERNAL,
591
+ attributes: dict[str, Any] | None = None,
592
+ ) -> Generator[TracingSpan, None, None]:
593
+ """Create a tracing span.
594
+
595
+ Args:
596
+ name: Span name
597
+ kind: Span kind
598
+ attributes: Initial attributes
599
+
600
+ Yields:
601
+ TracingSpan
602
+ """
603
+ if not self.tracing_config.enabled:
604
+ # No-op span
605
+ span = TracingSpan(
606
+ name=name,
607
+ context=SpanContext.create_root(),
608
+ kind=kind,
609
+ )
610
+ yield span
611
+ return
612
+
613
+ # Check sampling
614
+ import random
615
+ if random.random() > self.tracing_config.sample_rate:
616
+ span = TracingSpan(
617
+ name=name,
618
+ context=SpanContext.create_root(),
619
+ kind=kind,
620
+ )
621
+ yield span
622
+ return
623
+
624
+ # Create span context
625
+ with self._lock:
626
+ if self._context_stack:
627
+ context = SpanContext.create_child(self._context_stack[-1])
628
+ else:
629
+ context = SpanContext.create_root()
630
+ self._context_stack.append(context)
631
+
632
+ # Create span
633
+ span = TracingSpan(
634
+ name=name,
635
+ context=context,
636
+ kind=kind,
637
+ )
638
+ if attributes:
639
+ span.set_attributes(attributes)
640
+
641
+ # Add service attributes
642
+ span.set_attributes({
643
+ "service.name": self.tracing_config.service_name,
644
+ "service.version": self.tracing_config.service_version,
645
+ "deployment.environment": self.tracing_config.environment,
646
+ })
647
+
648
+ try:
649
+ yield span
650
+ if span.status == SpanStatus.UNSET:
651
+ span.set_ok()
652
+ except Exception as e:
653
+ span.record_exception(e)
654
+ raise
655
+ finally:
656
+ span.end()
657
+ self._exporter.export_span(span)
658
+
659
+ with self._lock:
660
+ if self._context_stack:
661
+ self._context_stack.pop()
662
+
663
+ # Record metrics
664
+ if span.duration_ms is not None:
665
+ self._metrics.record_histogram(
666
+ "span.duration_ms",
667
+ span.duration_ms,
668
+ {"name": name, "status": span.status.value},
669
+ )
670
+
671
+ def get_current_context(self) -> SpanContext | None:
672
+ """Get current span context.
673
+
674
+ Returns:
675
+ Current SpanContext or None
676
+ """
677
+ with self._lock:
678
+ return self._context_stack[-1] if self._context_stack else None
679
+
680
+ def inject_context(self, carrier: dict[str, str]) -> None:
681
+ """Inject current context into carrier for propagation.
682
+
683
+ Args:
684
+ carrier: Dictionary to inject headers into
685
+ """
686
+ ctx = self.get_current_context()
687
+ if ctx:
688
+ carrier["traceparent"] = ctx.to_w3c_traceparent()
689
+
690
+ def extract_context(self, carrier: dict[str, str]) -> SpanContext | None:
691
+ """Extract context from carrier.
692
+
693
+ Args:
694
+ carrier: Dictionary containing headers
695
+
696
+ Returns:
697
+ Extracted SpanContext or None
698
+ """
699
+ traceparent = carrier.get("traceparent")
700
+ if traceparent:
701
+ try:
702
+ return SpanContext.from_w3c_traceparent(traceparent)
703
+ except ValueError:
704
+ logger.warning(f"Invalid traceparent: {traceparent}")
705
+ return None
706
+
707
+ def get_metrics(self) -> dict[str, Any]:
708
+ """Get collected metrics.
709
+
710
+ Returns:
711
+ Dictionary of metrics
712
+ """
713
+ return self._metrics.get_metrics()
714
+
715
+ def record_timeout(self, operation: str, timeout_seconds: float) -> None:
716
+ """Record a timeout event.
717
+
718
+ Args:
719
+ operation: Operation that timed out
720
+ timeout_seconds: Timeout value
721
+ """
722
+ self._metrics.increment("timeouts.total", 1, {"operation": operation})
723
+ self._metrics.record_histogram(
724
+ "timeout.configured_seconds",
725
+ timeout_seconds,
726
+ {"operation": operation},
727
+ )
728
+
729
+ def record_execution(self, operation: str, duration_ms: float, success: bool) -> None:
730
+ """Record an execution.
731
+
732
+ Args:
733
+ operation: Operation name
734
+ duration_ms: Duration in milliseconds
735
+ success: Whether execution succeeded
736
+ """
737
+ labels = {"operation": operation, "success": str(success).lower()}
738
+ self._metrics.increment("executions.total", 1, labels)
739
+ self._metrics.record_histogram("execution.duration_ms", duration_ms, labels)
740
+
741
+ def shutdown(self) -> None:
742
+ """Shutdown the telemetry provider."""
743
+ self._exporter.shutdown()
744
+
745
+
746
+ # Module-level default provider
747
+ _default_provider: TelemetryProvider | None = None
748
+
749
+
750
+ def create_tracer(config: TracingConfig | None = None) -> TelemetryProvider:
751
+ """Create or get the default telemetry provider.
752
+
753
+ Args:
754
+ config: Optional tracing configuration
755
+
756
+ Returns:
757
+ TelemetryProvider
758
+ """
759
+ global _default_provider
760
+ if _default_provider is None or config is not None:
761
+ _default_provider = TelemetryProvider(config)
762
+ return _default_provider
763
+
764
+
765
+ def create_metrics_collector(config: MetricsConfig | None = None) -> MetricsCollector:
766
+ """Create a metrics collector.
767
+
768
+ Args:
769
+ config: Optional metrics configuration
770
+
771
+ Returns:
772
+ MetricsCollector
773
+ """
774
+ return MetricsCollector(config)
775
+
776
+
777
+ def trace_operation(
778
+ name: str,
779
+ attributes: dict[str, Any] | None = None,
780
+ ) -> Callable[[Callable[..., T]], Callable[..., T]]:
781
+ """Decorator to trace a function.
782
+
783
+ Args:
784
+ name: Span name
785
+ attributes: Initial attributes
786
+
787
+ Returns:
788
+ Decorated function
789
+
790
+ Example:
791
+ @trace_operation("validate_column")
792
+ def validate_column(data, column):
793
+ ...
794
+ """
795
+ def decorator(func: Callable[..., T]) -> Callable[..., T]:
796
+ @functools.wraps(func)
797
+ def wrapper(*args: Any, **kwargs: Any) -> T:
798
+ provider = create_tracer()
799
+ with provider.trace(name, attributes=attributes) as span:
800
+ span.set_attribute("function", func.__name__)
801
+ result = func(*args, **kwargs)
802
+ return result
803
+ return wrapper
804
+ return decorator