odysseus 0.1.1__tar.gz

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.
odysseus-0.1.1/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
20
+
@@ -0,0 +1,63 @@
1
+ Metadata-Version: 2.2
2
+ Name: odysseus
3
+ Version: 0.1.1
4
+ Summary: A client for CodeTitans Odysseus Logging Platform.
5
+ Author-email: Paweł Hofman <pawel@codetitans.pl>
6
+ License: Copyright (c) 2018 The Python Packaging Authority
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
25
+
26
+
27
+ Project-URL: Homepage, https://github.com/codetitans/odysseus-py
28
+ Project-URL: Issues, https://github.com/codetitans/odysseus-py/issues
29
+ Keywords: logs,logging,Odysseus
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Operating System :: OS Independent
32
+ Requires-Python: >=3.8
33
+ Description-Content-Type: text/markdown
34
+ License-File: LICENSE
35
+ Requires-Dist: requests<3.0,>=2.32.3
36
+ Requires-Dist: tzlocal<6.0,>=5.2
37
+
38
+ # Odysseus Platform - Python client
39
+
40
+ This repository contains full source code of the simple Python project capable of uploading log entries or events happening on a backend application - back to the [Odysseus Logging Platform](https://odysseus.codetitans.dev).
41
+
42
+ Once it's added as a dependency of your Python application, it has to be connected with your existing logging system and logs serialization has to be redirected to be able to process them and pass back to the server.
43
+
44
+ ## Disclaimer
45
+
46
+ Full utilization of the Odysseus Logging Platform services is subject to the proper contract and not part of that client functionality. By using this software you essentially agree that since it's an open-source project you read it and understand all repercussions of using it. Thus you will never claim or call for any compensations or damages in connection with downtime of your own services caused by this software.
47
+
48
+ ## Build
49
+
50
+ To create the new bundled release simply call following command:
51
+
52
+ ```shell
53
+ $ ./build.sh package
54
+ ```
55
+
56
+ What it does internally, is only performs several checks around missing environmental setup and calls the build command:
57
+
58
+ ```shell
59
+ $ python3 -m build
60
+ ```
61
+
62
+ -----
63
+ CodeTitans Sp. z o.o. (2025-)
@@ -0,0 +1,26 @@
1
+ # Odysseus Platform - Python client
2
+
3
+ This repository contains full source code of the simple Python project capable of uploading log entries or events happening on a backend application - back to the [Odysseus Logging Platform](https://odysseus.codetitans.dev).
4
+
5
+ Once it's added as a dependency of your Python application, it has to be connected with your existing logging system and logs serialization has to be redirected to be able to process them and pass back to the server.
6
+
7
+ ## Disclaimer
8
+
9
+ Full utilization of the Odysseus Logging Platform services is subject to the proper contract and not part of that client functionality. By using this software you essentially agree that since it's an open-source project you read it and understand all repercussions of using it. Thus you will never claim or call for any compensations or damages in connection with downtime of your own services caused by this software.
10
+
11
+ ## Build
12
+
13
+ To create the new bundled release simply call following command:
14
+
15
+ ```shell
16
+ $ ./build.sh package
17
+ ```
18
+
19
+ What it does internally, is only performs several checks around missing environmental setup and calls the build command:
20
+
21
+ ```shell
22
+ $ python3 -m build
23
+ ```
24
+
25
+ -----
26
+ CodeTitans Sp. z o.o. (2025-)
@@ -0,0 +1,23 @@
1
+ [project]
2
+ name = "odysseus"
3
+ version = "0.1.1"
4
+ authors = [
5
+ { name="Paweł Hofman", email="pawel@codetitans.pl" },
6
+ ]
7
+ description = "A client for CodeTitans Odysseus Logging Platform."
8
+ readme = "README.md"
9
+ requires-python = ">=3.8"
10
+ classifiers = [
11
+ "Programming Language :: Python :: 3",
12
+ "Operating System :: OS Independent",
13
+ ]
14
+ license = { file="LICENSE" }
15
+ keywords = ["logs", "logging", "Odysseus"]
16
+ dependencies = [
17
+ "requests >= 2.32.3, < 3.0",
18
+ "tzlocal >= 5.2, < 6.0",
19
+ ]
20
+
21
+ [project.urls]
22
+ Homepage = "https://github.com/codetitans/odysseus-py"
23
+ Issues = "https://github.com/codetitans/odysseus-py/issues"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,196 @@
1
+ import datetime
2
+ import requests
3
+ import urllib.parse
4
+
5
+ from threading import Lock, Timer
6
+ from typing import Optional, Any, TypeVar, Generic, Dict
7
+ from tzlocal import get_localzone
8
+ from uuid import uuid4, UUID
9
+
10
+ ########################################################################################################################
11
+ log_silent = False
12
+ log_tag = 'Odysseus'
13
+
14
+ def internal_log(message: str):
15
+ if log_silent:
16
+ return
17
+ ts = datetime.datetime.now(tz=get_localzone())
18
+ time = "{:02d}:{:02d}:{:02d}".format(ts.hour, ts.minute, ts.second)
19
+ print(f"[{time}] [INFO] {log_tag}: {message}")
20
+
21
+
22
+ class OdysseusLog:
23
+
24
+ def __init__(self, message: str, session_id: UUID,
25
+ severity: int = 0, tag: Optional[str] = None,
26
+ file: Optional[str] = None, line: Optional[int] = None,
27
+ user: Optional[str] = None, timestamp: Optional[datetime.datetime] = None,
28
+ context: Optional[Dict[str, Any]] = None):
29
+
30
+ self.session_id = session_id.hex
31
+ self.message = message
32
+ self.severity = severity
33
+ self.tag = tag
34
+ self.timestamp = datetime.datetime.now(tz=get_localzone()).isoformat() if timestamp is None else timestamp.isoformat()
35
+ self.file = file
36
+ self.line = line
37
+ self.user = user
38
+ self.context = context
39
+
40
+
41
+ class OdysseusEvent:
42
+
43
+ def __init__(self, id: UUID, name: str, session_id: UUID, type: int = 0, stream_id: Optional[UUID] = None, position: int = 0,
44
+ user: Optional[str] = None, timestamp: Optional[datetime.datetime] = None,
45
+ data: Optional[Dict[str, Any]] = None, meta: Optional[Dict[str, Any]] = None):
46
+
47
+ self.id = id.hex
48
+ self.session_id = session_id.hex
49
+ self.name = name
50
+ self.type = type
51
+ self.timestamp = datetime.datetime.now(tz=get_localzone()).isoformat() if timestamp is None else timestamp.isoformat()
52
+ self.stream_id = uuid4().hex if stream_id is None else stream_id.hex
53
+ self.position = position
54
+ self.user = user
55
+ self.data = data
56
+ self.meta = meta
57
+
58
+
59
+ T = TypeVar('T')
60
+
61
+ class OdysseusCollection(Generic[T]):
62
+
63
+ def __init__(self, endpoint: str, entity_name: str, delay: int = 5):
64
+ self.entries: [T] = []
65
+ self.to_upload: [T] = []
66
+ self.endpoint = endpoint
67
+ self.entity_name = entity_name
68
+ self.delay = delay
69
+ self.timer = None
70
+ self.lock = Lock()
71
+
72
+ def add(self, item: T):
73
+ with self.lock:
74
+ self.entries.append(item)
75
+
76
+ if self.timer is None:
77
+ self.timer = Timer(self.delay, self.execute_upload)
78
+ self.timer.start()
79
+
80
+ def execute_upload(self):
81
+
82
+ # copy the entries aside and try to upload them
83
+ with self.lock:
84
+ self.to_upload = self.entries
85
+ self.entries = []
86
+
87
+ success = False
88
+ try:
89
+ success = self.upload_entries(self.to_upload)
90
+ if success:
91
+ # once upload finished successfully, clear all temporary data
92
+ with self.lock:
93
+ self.to_upload = []
94
+ self.timer = None
95
+ except Exception as e:
96
+ internal_log(f"Failed to upload {self.entity_name} to Odysseus: {e}")
97
+
98
+ if not success or len(self.entries) > 0:
99
+ with self.lock:
100
+ self.to_upload.extend(self.entries)
101
+ self.entries = []
102
+
103
+ # restart the timer
104
+ self.timer = Timer(self.delay, self.execute_upload)
105
+ self.timer.start()
106
+
107
+ def upload_entries(self, data: [T]) -> bool:
108
+ url = "https://odysseus.codetitans.dev" + self.endpoint
109
+ # url = "http://192.168.2.183:5757" + self.endpoint
110
+ response = requests.post(url, json=[x.__dict__ for x in data])
111
+
112
+ global log_silent
113
+ if 200 <= response.status_code < 300:
114
+ if not log_silent:
115
+ text = response.text
116
+ internal_log(f"Successfully uploaded {self.entity_name} to Odysseus: {response.status_code} (\"{text}\")")
117
+ return True
118
+ else:
119
+ if not log_silent:
120
+ text = response.text
121
+ internal_log(f"Failed to upload {self.entity_name} to Odysseus: {response.status_code} ({text})")
122
+ return False
123
+
124
+
125
+ class OdysseusClient:
126
+
127
+ def __init__(self, app_id: str, app_key: str, user: Optional[str] = None, session: Optional[UUID] = None,
128
+ min_severity: int = 1, silent: bool = False):
129
+ global log_silent
130
+ log_silent = silent
131
+
132
+ self.user_id = user
133
+ self.session_id = uuid4() if session is None else session
134
+ self.min_severity_level = min_severity
135
+ self.app_id = app_id
136
+ self.app_key = app_key
137
+ self.logs = OdysseusCollection[OdysseusLog](endpoint="/api/logs" + urllib.parse.quote('/' + app_id + '/' + app_key), delay=5, entity_name="logs")
138
+ self.events = OdysseusCollection[OdysseusEvent](endpoint="/api/events" + urllib.parse.quote('/' + app_id + '/' + app_key), delay=5, entity_name="events")
139
+
140
+ internal_log(f"Initialised for application: \"{self.app_id}\" (session: \"{self.session_id.hex}\", delay: {self.logs.delay}s)")
141
+
142
+ @property
143
+ def user(self) -> Optional[str]:
144
+ return self.user_id
145
+
146
+ @user.setter
147
+ def user(self, value: Optional[str] = None):
148
+ self.user_id = value
149
+
150
+ @property
151
+ def session(self) -> UUID:
152
+ return self.session_id
153
+
154
+ @session.setter
155
+ def session(self, value: UUID):
156
+ self.session_id = value
157
+
158
+ @property
159
+ def min_severity(self) -> int:
160
+ return self.min_severity_level
161
+
162
+ @min_severity.setter
163
+ def min_severity(self, value: int):
164
+ self.min_severity_level = value
165
+
166
+ def log(self, message: str, severity: int, tag: Optional[str] = None,
167
+ file: Optional[str] = None, line: Optional[int] = None, timestamp: Optional[datetime.datetime] = None,
168
+ context: Optional[Dict[str, Any]] = None) -> Optional[OdysseusLog]:
169
+ if severity < self.min_severity_level:
170
+ return None
171
+
172
+ return self.add_log(OdysseusLog(message, self.session_id, severity=severity, tag=tag,
173
+ user=self.user_id, timestamp=timestamp, file=file, line=line, context=context))
174
+
175
+ def add_log(self, entry: OdysseusLog) -> Optional[OdysseusLog]:
176
+ if entry.severity < self.min_severity_level:
177
+ return None
178
+
179
+ self.logs.add(entry)
180
+ return entry
181
+
182
+ def event(self, name: str, id: Optional[UUID] = None, type: int = 0, stream_id: Optional[UUID] = None, position: Optional[int] = None,
183
+ timestamp: Optional[datetime.datetime] = None,
184
+ data: Optional[Dict[str, Any]] = None, meta: Optional[Dict[str, Any]] = None) -> OdysseusEvent:
185
+ return self.add_event(OdysseusEvent(
186
+ uuid4() if id is None else id,
187
+ name=name, session_id=self.session_id, type=type, stream_id=stream_id, position=position,
188
+ user=self.user, timestamp=timestamp, data=data, meta=meta))
189
+
190
+ def add_event(self, event: OdysseusEvent) -> OdysseusEvent:
191
+ self.events.add(event)
192
+ return event
193
+
194
+
195
+
196
+
@@ -0,0 +1,63 @@
1
+ Metadata-Version: 2.2
2
+ Name: odysseus
3
+ Version: 0.1.1
4
+ Summary: A client for CodeTitans Odysseus Logging Platform.
5
+ Author-email: Paweł Hofman <pawel@codetitans.pl>
6
+ License: Copyright (c) 2018 The Python Packaging Authority
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
25
+
26
+
27
+ Project-URL: Homepage, https://github.com/codetitans/odysseus-py
28
+ Project-URL: Issues, https://github.com/codetitans/odysseus-py/issues
29
+ Keywords: logs,logging,Odysseus
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Operating System :: OS Independent
32
+ Requires-Python: >=3.8
33
+ Description-Content-Type: text/markdown
34
+ License-File: LICENSE
35
+ Requires-Dist: requests<3.0,>=2.32.3
36
+ Requires-Dist: tzlocal<6.0,>=5.2
37
+
38
+ # Odysseus Platform - Python client
39
+
40
+ This repository contains full source code of the simple Python project capable of uploading log entries or events happening on a backend application - back to the [Odysseus Logging Platform](https://odysseus.codetitans.dev).
41
+
42
+ Once it's added as a dependency of your Python application, it has to be connected with your existing logging system and logs serialization has to be redirected to be able to process them and pass back to the server.
43
+
44
+ ## Disclaimer
45
+
46
+ Full utilization of the Odysseus Logging Platform services is subject to the proper contract and not part of that client functionality. By using this software you essentially agree that since it's an open-source project you read it and understand all repercussions of using it. Thus you will never claim or call for any compensations or damages in connection with downtime of your own services caused by this software.
47
+
48
+ ## Build
49
+
50
+ To create the new bundled release simply call following command:
51
+
52
+ ```shell
53
+ $ ./build.sh package
54
+ ```
55
+
56
+ What it does internally, is only performs several checks around missing environmental setup and calls the build command:
57
+
58
+ ```shell
59
+ $ python3 -m build
60
+ ```
61
+
62
+ -----
63
+ CodeTitans Sp. z o.o. (2025-)
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/odysseus/__init__.py
5
+ src/odysseus/odysseus.py
6
+ src/odysseus.egg-info/PKG-INFO
7
+ src/odysseus.egg-info/SOURCES.txt
8
+ src/odysseus.egg-info/dependency_links.txt
9
+ src/odysseus.egg-info/requires.txt
10
+ src/odysseus.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ requests<3.0,>=2.32.3
2
+ tzlocal<6.0,>=5.2
@@ -0,0 +1 @@
1
+ odysseus