3
3
"""
4
4
5
5
import logging
6
+ from typing import Any
6
7
7
8
from openapi_core import OpenAPI
8
9
from openapi_core .contrib .werkzeug import WerkzeugOpenAPIRequest , WerkzeugOpenAPIResponse
18
19
from localstack .aws .chain import Handler , HandlerChain
19
20
from localstack .constants import INTERNAL_RESOURCE_PATH
20
21
from localstack .http import Response
22
+ from localstack .utils .analytics .usage import UsageSetCounter
21
23
22
24
LOG = logging .getLogger (__name__ )
23
25
24
26
27
+ class UsageCollectorFactory :
28
+ _collector_registry : dict [str , Any ] = {}
29
+ """Registry for the different paths."""
30
+
31
+ NAMESPACE_PREFIX = "internal"
32
+ """Namespace prefix to track usage of public endpoints (_localstack/ and _aws/)."""
33
+
34
+ @classmethod
35
+ def get_collector (cls , path : str ):
36
+ namespace = f"{ cls .NAMESPACE_PREFIX } /{ path } "
37
+ if namespace not in cls ._collector_registry :
38
+ cls ._collector_registry [namespace ] = UsageSetCounter (namespace )
39
+ return cls ._collector_registry [namespace ]
40
+
41
+
25
42
class OpenAPIValidator (Handler ):
26
43
open_apis : list ["OpenAPI" ]
27
44
28
45
def __init__ (self ) -> None :
29
46
self ._load_specs ()
30
47
48
+ def _record_usage (self , context : RequestContext ) -> None :
49
+ if config .DISABLE_EVENTS :
50
+ return
51
+
52
+ request_path = context .request .path
53
+ user_agent = context .request .headers .get ("User-Agent" )
54
+ if not request_path or not user_agent :
55
+ return
56
+ collector = UsageCollectorFactory .get_collector (context .request .path )
57
+ collector .record (user_agent )
58
+
31
59
def _load_specs (self ) -> None :
32
60
"""Load the openapi spec plugins iff at least one between request and response validation is set."""
33
61
if not (config .OPENAPI_VALIDATE_REQUEST or config .OPENAPI_VALIDATE_RESPONSE ):
@@ -45,6 +73,7 @@ class OpenAPIRequestValidator(OpenAPIValidator):
45
73
"""
46
74
47
75
def __call__ (self , chain : HandlerChain , context : RequestContext , response : Response ):
76
+ self ._record_usage (context )
48
77
if not config .OPENAPI_VALIDATE_REQUEST :
49
78
return
50
79
0 commit comments