crypticorn 2.16.0__py3-none-any.whl → 2.17.0rc1__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.
@@ -13,5 +13,7 @@ from crypticorn.common.ansi_colors import *
13
13
  from crypticorn.common.middleware import *
14
14
  from crypticorn.common.warnings import *
15
15
  from crypticorn.common.openapi import *
16
+ from crypticorn.common.metrics import *
16
17
  from crypticorn.common.router.status_router import router as status_router
17
18
  from crypticorn.common.router.admin_router import router as admin_router
19
+
@@ -0,0 +1,20 @@
1
+ # metrics/registry.py
2
+ from prometheus_client import (
3
+ Counter, Gauge, Histogram, Summary, CollectorRegistry
4
+ )
5
+
6
+ registry = CollectorRegistry()
7
+
8
+ http_requests_total = Counter(
9
+ "http_requests_total",
10
+ "Total HTTP requests",
11
+ ["method", "endpoint", "status_code"],
12
+ registry=registry
13
+ )
14
+
15
+ http_request_duration_seconds = Histogram(
16
+ "http_request_duration_seconds",
17
+ "HTTP request duration in seconds",
18
+ ["endpoint"],
19
+ registry=registry
20
+ )
@@ -1,10 +1,50 @@
1
+ import time
1
2
  from fastapi import FastAPI
2
3
  from fastapi.middleware.cors import CORSMiddleware
4
+ from starlette.middleware.base import BaseHTTPMiddleware
5
+ from starlette.requests import Request
3
6
  from crypticorn.common.logging import configure_logging
4
7
  from contextlib import asynccontextmanager
8
+ from typing_extensions import deprecated
9
+ import warnings
10
+ from crypticorn.common.warnings import CrypticornDeprecatedSince217
11
+ from crypticorn.common.metrics import http_requests_total, http_request_duration_seconds
5
12
 
13
+ class PrometheusMiddleware(BaseHTTPMiddleware):
14
+ async def dispatch(self, request, call_next):
15
+ start = time.perf_counter()
16
+ response = await call_next(request)
17
+ duration = time.perf_counter() - start
6
18
 
19
+ http_requests_total.labels(
20
+ method=request.method,
21
+ endpoint=request.url.path,
22
+ status_code=response.status_code
23
+ ).inc()
24
+
25
+ http_request_duration_seconds.labels(
26
+ endpoint=request.url.path
27
+ ).observe(duration)
28
+
29
+ return response
30
+
31
+
32
+ @deprecated("Use add_middleware instead", category=None)
7
33
  def add_cors_middleware(app: "FastAPI"):
34
+ warnings.warn("add_cors_middleware is deprecated. Use add_middleware instead.", CrypticornDeprecatedSince217)
35
+ app.add_middleware(
36
+ CORSMiddleware,
37
+ allow_origins=[
38
+ "http://localhost:5173", # vite dev server
39
+ "http://localhost:4173", # vite preview server
40
+ ],
41
+ allow_origin_regex="^https://([a-zA-Z0-9-]+.)*crypticorn.(dev|com)/?$", # matches (multiple or no) subdomains of crypticorn.dev and crypticorn.com
42
+ allow_credentials=True,
43
+ allow_methods=["*"],
44
+ allow_headers=["*"],
45
+ )
46
+
47
+ def add_middleware(app: "FastAPI"):
8
48
  app.add_middleware(
9
49
  CORSMiddleware,
10
50
  allow_origins=[
@@ -16,6 +56,7 @@ def add_cors_middleware(app: "FastAPI"):
16
56
  allow_methods=["*"],
17
57
  allow_headers=["*"],
18
58
  )
59
+ app.add_middleware(PrometheusMiddleware)
19
60
 
20
61
 
21
62
  @asynccontextmanager
@@ -11,10 +11,12 @@ import threading
11
11
  import time
12
12
  import psutil
13
13
  import re
14
- from fastapi import APIRouter, Query
14
+ import logging
15
15
  from typing import Literal
16
+ from fastapi import APIRouter, Query, Response
17
+ from prometheus_client import generate_latest, CONTENT_TYPE_LATEST
16
18
  from crypticorn.common.logging import LogLevel
17
- import logging
19
+ from crypticorn.common.metrics import registry
18
20
 
19
21
  router = APIRouter(tags=["Admin"], prefix="/admin")
20
22
 
@@ -104,3 +106,11 @@ def list_installed_packages(
104
106
  or any(re.match(pattern, dist.metadata["Name"]) for pattern in include)
105
107
  }
106
108
  return dict(sorted(packages.items()))
109
+
110
+
111
+ @router.get("/metrics", operation_id="getMetrics")
112
+ def metrics():
113
+ """
114
+ Get Prometheus metrics for the application. Returns plain text.
115
+ """
116
+ return Response(generate_latest(registry), media_type=CONTENT_TYPE_LATEST)
@@ -62,6 +62,12 @@ class CrypticornDeprecatedSince215(CrypticornDeprecationWarning):
62
62
  def __init__(self, message: str, *args: object) -> None:
63
63
  super().__init__(message, *args, since=(2, 15), expected_removal=(3, 0))
64
64
 
65
+ class CrypticornDeprecatedSince217(CrypticornDeprecationWarning):
66
+ """A specific `CrypticornDeprecationWarning` subclass defining functionality deprecated since Crypticorn 2.17."""
67
+
68
+ def __init__(self, message: str, *args: object) -> None:
69
+ super().__init__(message, *args, since=(2, 17), expected_removal=(3, 0))
70
+
65
71
 
66
72
  class CrypticornExperimentalWarning(Warning):
67
73
  """A Crypticorn specific experimental functionality warning.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crypticorn
3
- Version: 2.16.0
3
+ Version: 2.17.0rc1
4
4
  Summary: Maximise Your Crypto Trading Profits with Machine Learning
5
5
  Author-email: Crypticorn <timon@crypticorn.com>
6
6
  License-Expression: MIT
@@ -25,6 +25,7 @@ Requires-Dist: click<9.0.0,>=8.0.0
25
25
  Requires-Dist: psutil<8.0.0,>=7.0.0
26
26
  Requires-Dist: setuptools<81.0.0,>=80.0.0
27
27
  Requires-Dist: strenum
28
+ Requires-Dist: prometheus-client<1.0.0,>=0.22.0
28
29
  Requires-Dist: urllib3<3.0.0,>=1.25.3
29
30
  Requires-Dist: python_dateutil<3.0.0,>=2.8.2
30
31
  Requires-Dist: aiohttp<4.0.0,>=3.8.4
@@ -65,7 +65,7 @@ crypticorn/cli/templates/auth.py,sha256=i27-Ts-Eiyv6_WRshOp7NV5OYUNbw2-kiN5Ll0k2
65
65
  crypticorn/cli/templates/dependabot.yml,sha256=ct5ieB8KAV1KLzoYKUNm6dZ9wKG_P_JQHgRjZUfT54w,861
66
66
  crypticorn/cli/templates/merge-env.sh,sha256=BNPrDTihII0yG2gehBkWwWj0GqHmb6xwmrAgwFpl8dA,554
67
67
  crypticorn/cli/templates/ruff.yml,sha256=gWicFFTzC4nToSmRkIIGipos8CZ447YG0kebBCJhtJE,319
68
- crypticorn/common/__init__.py,sha256=DXEuUU_kaLBSBcvpiFie_ROuK5XEZuTMIfsg-BZE0iE,752
68
+ crypticorn/common/__init__.py,sha256=Now08P5NDnIUQ2WWZ4MUo066FV58x7oOK95jpFT-kj8,793
69
69
  crypticorn/common/ansi_colors.py,sha256=-tMlUTE8NI7TPv7uj0kGRe-SI2hGaUNPKBFI_dfiZy0,1392
70
70
  crypticorn/common/auth.py,sha256=b7jhR8k7bQFfgokI_Eqji0MpfiyD4EhCoddefUSqs6Y,9925
71
71
  crypticorn/common/decorators.py,sha256=t5Y3vSJ-gt0n2vOYYjYN0dtzNXvZxrJs2SEItpzG8oo,1127
@@ -73,15 +73,16 @@ crypticorn/common/enums.py,sha256=x-2xe0NUI8kB6DNg9GLjqAjYOsFAGwP-jdM1YgIt9AI,13
73
73
  crypticorn/common/errors.py,sha256=qPCYpmxw0uZNmQw9RYj9vUsg-_R5aRn7fYE8qxTAnyA,30129
74
74
  crypticorn/common/exceptions.py,sha256=4oT58wcL9zQuqYU8op_36uZ1Kzt7JRCccu-o_usgqtU,6392
75
75
  crypticorn/common/logging.py,sha256=n-qaYreRNFVAFRUd91hzYoaTExNLysd9cgEXm-v6eJY,4440
76
- crypticorn/common/middleware.py,sha256=O7XiXPimNYUhF9QTv6yFUTVlb91-SK-3CfTrWMNP6Ck,1011
76
+ crypticorn/common/metrics.py,sha256=UDiWu9-B0BvePsCpcrN1EqxNRWxf_TimyUL8YfwJRco,461
77
+ crypticorn/common/middleware.py,sha256=nclyrDEBF2Ypw7CTYYCU_PXDkmtWnQOt-hknBEYIf-4,2573
77
78
  crypticorn/common/mixins.py,sha256=l7XQrBISaee6fDZXy96k0HnQ18XYocjTUXlNpVxhaOY,2206
78
79
  crypticorn/common/openapi.py,sha256=D8bCpCVVzYQptHrJ7SYOgCxI3R_d0cjW9KMOBq-x0xk,279
79
80
  crypticorn/common/pagination.py,sha256=eD4S8t-NHECWYCFTu3taeDv07_AzPBbopoKSZRBSiCM,2621
80
81
  crypticorn/common/scopes.py,sha256=ZreqkW_XshlyLJjciAfaIFmcy4HO6RnCsbbkjCw-fxc,2900
81
82
  crypticorn/common/urls.py,sha256=v23H2gevTNZ6HMRXDPiuc8znBbNdNqj0JTAdm5Hhms8,1223
82
83
  crypticorn/common/utils.py,sha256=LcWudhcjZtULg87yYghh5muTYdHvk3UmkEAXmX7xgLk,3073
83
- crypticorn/common/warnings.py,sha256=YU7JKIJpVAoBlqCXaaP61t7jzLibB1G0yjQ1NHUJ6xU,2755
84
- crypticorn/common/router/admin_router.py,sha256=x81s1gxhH7nLf7txqAIjVxrNgQmXsA1YG7g9v9KJwHA,3740
84
+ crypticorn/common/warnings.py,sha256=gg7_vqb30P91JWQfy3x8Ee9VrYUKuy6aEkeGuL6Mp7M,3083
85
+ crypticorn/common/router/admin_router.py,sha256=BcA-zRL5Nb5saSoGFgWEuYtPOKM8PJ60KLY3yiD5S2E,4094
85
86
  crypticorn/common/router/status_router.py,sha256=NpLaCF2a1jApo95iolKzzUKuyHbpf4Xwc0sM7dxQ9DE,873
86
87
  crypticorn/hive/__init__.py,sha256=hRfTlEzEql4msytdUC_04vfaHzVKG5CGZle1M-9QFgY,81
87
88
  crypticorn/hive/main.py,sha256=bSOY2PBi4VV_mvN1c0FQAI-En28f8HnmoZDm3g9X6lU,3103
@@ -279,9 +280,9 @@ crypticorn/trade/client/models/strategy_update.py,sha256=f7UsKSlNardj5h6uqHYbacj
279
280
  crypticorn/trade/client/models/tpsl.py,sha256=iuHwBxHaUdtJn7NhcTE6Skzv4nmoSF8jEnf7_bTglwk,3730
280
281
  crypticorn/trade/client/models/tpsl_create.py,sha256=nX4i2BGWv5rmu3SLgRngfvEMFOWa3CIy0G3fyoxI-e4,3351
281
282
  crypticorn/trade/client/models/trading_action_type.py,sha256=BysUEOl85zs79EA2zOcDN1EExcpQdABaJ4Jz08_z8VU,857
282
- crypticorn-2.16.0.dist-info/licenses/LICENSE,sha256=HonAVvzFXkP2C1d7D3ByIKPwjGH8NcHTAQvKH7uvOHQ,1856
283
- crypticorn-2.16.0.dist-info/METADATA,sha256=nNS1g853y575ebtgifCqxjGYtwmi1tkBp2g_IcmC450,9993
284
- crypticorn-2.16.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
285
- crypticorn-2.16.0.dist-info/entry_points.txt,sha256=d_xHsGvUTebPveVUK0SrpDFQ5ZRSjlI7lNCc11sn2PM,59
286
- crypticorn-2.16.0.dist-info/top_level.txt,sha256=EP3NY216qIBYfmvGl0L2Zc9ItP0DjGSkiYqd9xJwGcM,11
287
- crypticorn-2.16.0.dist-info/RECORD,,
283
+ crypticorn-2.17.0rc1.dist-info/licenses/LICENSE,sha256=HonAVvzFXkP2C1d7D3ByIKPwjGH8NcHTAQvKH7uvOHQ,1856
284
+ crypticorn-2.17.0rc1.dist-info/METADATA,sha256=LQz-vbKaperW4olSKyppd4LKSLEsGRfg95STN9vjv58,10044
285
+ crypticorn-2.17.0rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
286
+ crypticorn-2.17.0rc1.dist-info/entry_points.txt,sha256=d_xHsGvUTebPveVUK0SrpDFQ5ZRSjlI7lNCc11sn2PM,59
287
+ crypticorn-2.17.0rc1.dist-info/top_level.txt,sha256=EP3NY216qIBYfmvGl0L2Zc9ItP0DjGSkiYqd9xJwGcM,11
288
+ crypticorn-2.17.0rc1.dist-info/RECORD,,