onaplogging: Docstrings, refactor, type hinting
[logging-analytics.git] / pylog / onaplogging / marker / markerFactory.py
1 # Copyright 2018 ke liang <lokyse@163.com>.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #         http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import abc
16 import threading
17
18 from deprecated import deprecated
19 from warnings import warn
20 from typing import Dict, Optional
21
22 from .marker import Marker
23 from .marker import BaseMarker
24
25 lock = threading.RLock()
26
27
28 class IMarkerFactory(object):
29     """Abstract marker factory for defining structure.
30
31     TODO:
32         after deprecated child methods are removed, rename them here.
33     Extends:
34         object
35     Method list:
36         getMarker
37         deleteMarker
38         exist
39     Raises:
40         NotImplementedError
41     """
42
43     __metaclass__ = abc.ABCMeta
44
45     @abc.abstractmethod
46     def getMarker(self, marker_name=None):
47         raise NotImplementedError()
48
49     @abc.abstractmethod
50     def deleteMarker(self, marker_name=None):
51         raise NotImplementedError()
52
53     @abc.abstractmethod
54     def exist(self, marker_name=None):
55         raise NotImplementedError()
56
57
58 class MarkerFactory(IMarkerFactory):
59     """A factory class maganing every marker.
60
61     It is designed to check the existance, create and remove single markers.
62     This class follows a singleton pattern - only one instance can be created.
63
64     Extends:
65         IMarkerFactory
66     Properties:
67         marker_map      : a map of existing markers.
68     Attributes:
69         _instance       : a marker factory instance.
70     Methods:
71         getMarker       : creates a new marker or returns an available one.
72         deleteMarker    : removes a specific marker.
73         exist           : checks if a specific marker exists.
74     """
75
76     _instance = None
77     _marker_map = {}
78
79     @property
80     def marker_map(self):
81         # type: () -> Dict
82         if not hasattr(self, '_marker_map'):
83             self._marker_map = {}
84         return self._marker_map
85
86     def get_marker(self, name=None):
87         # type: (Optional[str]) -> Marker
88         """
89         Use it to get any marker by its name. If it doesn't exist - it
90         will  create a new  marker that  will be added to the factory.
91         Blocks the thread while executing.
92
93         Args:
94             name        : A marker name. Defaults to None.
95         Raises:
96             ValueError  : If `name` is None.
97         Returns:
98             Marker      : A found or just newly created marker.
99         """
100
101         if name is None:
102             raise ValueError("Marker name is None. Must have a str value.")
103
104         lock.acquire()
105
106         marker = self.marker_map.get(name, None)
107
108         if marker is None:
109             marker = BaseMarker(name)
110             self.marker_map[name] = marker
111
112         lock.release()
113
114         return marker
115
116     def delete_marker(self, name=None):
117         # type: (Optional[str]) -> bool
118         """
119         Args:
120             name: A marker name. Defaults to None.
121         Returns:
122             bool: The status of deletion.
123         """
124
125         lock.acquire()
126         exists = self.exists(name)
127         if exists:
128             del self.marker_map[name]
129             return True
130         lock.release()
131
132         return False
133
134     def exists(self, name=None):
135         # type: (Optional[str]) -> bool
136         """
137         Checks whether the search for a marker returns None and returns the
138         status of the operation.
139
140         Args:
141             name: marker name. Defaults to None.
142         Returns:
143             bool: status of whether the marker was found.
144         """
145         marker = self.marker_map.get(name, None)
146         return marker is not None
147
148     def __new__(cls, *args, **kwargs):
149         if cls._instance is None:
150             cls._instance = super(MarkerFactory, cls).__new__(cls)
151
152         warn("_marker_map attribute will be replaced by marker_map property.",
153               DeprecationWarning)
154         return cls._instance
155
156     @deprecated(reason="Will be removed. Call exists(name) instead.")
157     def exist(self, marker_name=None):
158         return self.exists(marker_name)
159
160     @deprecated(reason="Will be removed. Call get_marker(name) instead.")
161     def getMarker(self, marker_name=None):
162         return self.get_marker(marker_name)
163
164     @deprecated(reason="Will be removed. Call delete_marker(name) instead.")
165     def deleteMarker(self, marker_name=None):
166         return self.delete_marker(marker_name)