dt-extensions-sdk 1.1.0__py3-none-any.whl → 1.1.1__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.
- docs/conf.py +98 -0
- {dt_extensions_sdk-1.1.0.dist-info → dt_extensions_sdk-1.1.1.dist-info}/METADATA +58 -12
- {dt_extensions_sdk-1.1.0.dist-info → dt_extensions_sdk-1.1.1.dist-info}/RECORD +10 -9
- dynatrace_extension/__about__.py +1 -1
- dynatrace_extension/sdk/event.py +1 -3
- dynatrace_extension/sdk/extension.py +212 -127
- dynatrace_extension/sdk/metric.py +0 -2
- {dt_extensions_sdk-1.1.0.dist-info → dt_extensions_sdk-1.1.1.dist-info}/WHEEL +0 -0
- {dt_extensions_sdk-1.1.0.dist-info → dt_extensions_sdk-1.1.1.dist-info}/entry_points.txt +0 -0
- {dt_extensions_sdk-1.1.0.dist-info → dt_extensions_sdk-1.1.1.dist-info}/licenses/LICENSE.txt +0 -0
docs/conf.py
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
2
|
+
#
|
3
|
+
# This file only contains a selection of the most common options. For a full
|
4
|
+
# list see the documentation:
|
5
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
6
|
+
|
7
|
+
# -- Path setup --------------------------------------------------------------
|
8
|
+
|
9
|
+
# If extensions (or modules to document with autodoc) are in another directory,
|
10
|
+
# add these directories to sys.path here. If the directory is relative to the
|
11
|
+
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
12
|
+
#
|
13
|
+
import os
|
14
|
+
import sys
|
15
|
+
from datetime import datetime
|
16
|
+
|
17
|
+
sys.path.insert(0, os.path.abspath("."))
|
18
|
+
|
19
|
+
|
20
|
+
# -- Project information -----------------------------------------------------
|
21
|
+
project = "dt-sdk"
|
22
|
+
copyright = f"2023–{datetime.now().year}, Dynatrace LLC"
|
23
|
+
author = "Dynatrace"
|
24
|
+
|
25
|
+
# Short version
|
26
|
+
version = "1.0.0"
|
27
|
+
# The full version, including alpha/beta/rc tags
|
28
|
+
release = version
|
29
|
+
|
30
|
+
# The language for content autogenerated by Sphinx. Refer to documentation
|
31
|
+
# for a list of supported languages.
|
32
|
+
#
|
33
|
+
# This is also used if you do content translation via gettext catalogs.
|
34
|
+
# Usually you set "language" from the command line for these cases.
|
35
|
+
language = "en"
|
36
|
+
|
37
|
+
|
38
|
+
# -- General configuration ---------------------------------------------------
|
39
|
+
|
40
|
+
# Add any Sphinx extension module names here, as strings. They can be
|
41
|
+
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
42
|
+
# ones.
|
43
|
+
extensions = [
|
44
|
+
"sphinx.ext.autodoc",
|
45
|
+
"sphinx.ext.napoleon",
|
46
|
+
"sphinx.ext.viewcode",
|
47
|
+
"sphinx.ext.autosectionlabel",
|
48
|
+
"sphinx_wagtail_theme",
|
49
|
+
"sphinxcontrib.programoutput",
|
50
|
+
]
|
51
|
+
|
52
|
+
# Add any paths that contain templates here, relative to this directory.
|
53
|
+
templates_path = ["_templates"]
|
54
|
+
|
55
|
+
# List of patterns, relative to source directory, that match files and
|
56
|
+
# directories to ignore when looking for source files.
|
57
|
+
# This pattern also affects html_static_path and html_extra_path.
|
58
|
+
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
59
|
+
|
60
|
+
# True to prefix each section label with the name of the document it is in,
|
61
|
+
# followed by a colon. For example, index:Introduction for a section called
|
62
|
+
# Introduction that appears in document index.rst. Useful for avoiding
|
63
|
+
# ambiguity when the same section heading appears in different documents.
|
64
|
+
autosectionlabel_prefix_document = True
|
65
|
+
|
66
|
+
# -- Autodoc -----------------------------------------------------------------
|
67
|
+
|
68
|
+
autodoc_default_options = {"member-order": "bysource", "undoc-members": True}
|
69
|
+
|
70
|
+
# -- Options for HTML output -------------------------------------------------
|
71
|
+
|
72
|
+
# The theme to use for HTML and HTML Help pages. See the documentation for
|
73
|
+
# a list of builtin themes.
|
74
|
+
#
|
75
|
+
html_theme = "sphinx_wagtail_theme"
|
76
|
+
html_favicon = "_static/favicon.ico"
|
77
|
+
html_show_copyright = True
|
78
|
+
|
79
|
+
# Add any paths that contain custom static files (such as style sheets) here,
|
80
|
+
# relative to this directory. They are copied after the builtin static files,
|
81
|
+
# so a file named "default.css" will overwrite the builtin "default.css".
|
82
|
+
html_static_path = ["_static"]
|
83
|
+
|
84
|
+
# html_sidebars = {"**": ["search-field.html", "sidebar-nav-bs.html"]}
|
85
|
+
|
86
|
+
html_theme_options = {
|
87
|
+
"project_name": "dt-sdk",
|
88
|
+
"logo": "dt-sdk-logo.png",
|
89
|
+
"logo_alt": "dt-sdk",
|
90
|
+
"logo_url": "/",
|
91
|
+
"github_url": "https://github.com/dynatrace-extensions/dt-extensions-python-sdk",
|
92
|
+
"footer_links": ",".join(
|
93
|
+
[
|
94
|
+
"Dynatrace|https://dynatrace.com/",
|
95
|
+
"Extensions Team|mailto:extenions@dynatrace.com",
|
96
|
+
]
|
97
|
+
),
|
98
|
+
}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dt-extensions-sdk
|
3
|
-
Version: 1.1.
|
4
|
-
Project-URL: Documentation, https://github.com/
|
5
|
-
Project-URL: Issues, https://github.com/
|
6
|
-
Project-URL: Source, https://github.com/
|
3
|
+
Version: 1.1.1
|
4
|
+
Project-URL: Documentation, https://github.com/dynatrace-extensions/dt-extensions-python-sdk#readme
|
5
|
+
Project-URL: Issues, https://github.com/dynatrace-extensions/dt-extensions-python-sdk/issues
|
6
|
+
Project-URL: Source, https://github.com/dynatrace-extensions/dt-extensions-python-sdk
|
7
7
|
Author-email: dlopes7 <davidribeirolopes@gmail.com>
|
8
8
|
License-Expression: MIT
|
9
9
|
License-File: LICENSE.txt
|
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
17
17
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
18
18
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
19
|
-
Requires-Python: >=3.
|
19
|
+
Requires-Python: >=3.10
|
20
20
|
Provides-Extra: cli
|
21
21
|
Requires-Dist: dt-cli==1.6.13; extra == 'cli'
|
22
22
|
Requires-Dist: pyyaml; extra == 'cli'
|
@@ -32,19 +32,55 @@ Description-Content-Type: text/markdown
|
|
32
32
|
|
33
33
|
**Table of Contents**
|
34
34
|
|
35
|
-
- [
|
35
|
+
- [Quick Start](#quick-start)
|
36
36
|
- [License](#license)
|
37
37
|
- [Developing](#developing)
|
38
38
|
|
39
|
-
##
|
39
|
+
## Quick Start
|
40
40
|
|
41
|
-
|
42
|
-
|
41
|
+
### Requirements:
|
42
|
+
|
43
|
+
* Python 3.10+
|
44
|
+
|
45
|
+
### Install the SDK
|
46
|
+
|
47
|
+
```bash
|
48
|
+
pip install dt-extensions-sdk[cli]
|
49
|
+
# Note, on some shells like zsh you may need to escape the brackets - pip install dt-extensions-sdk\[cli\]
|
43
50
|
```
|
44
51
|
|
45
|
-
|
52
|
+
### Create signing certificates
|
53
|
+
|
54
|
+
```bash
|
55
|
+
dt-sdk gencerts
|
56
|
+
```
|
46
57
|
|
47
|
-
|
58
|
+
### Create a new extension
|
59
|
+
|
60
|
+
```bash
|
61
|
+
dt-sdk create my_first_extension
|
62
|
+
```
|
63
|
+
|
64
|
+
### Simulate
|
65
|
+
|
66
|
+
```bash
|
67
|
+
cd my_first_extension
|
68
|
+
dt-sdk run
|
69
|
+
```
|
70
|
+
|
71
|
+
### Build
|
72
|
+
|
73
|
+
```bash
|
74
|
+
dt-sdk build
|
75
|
+
```
|
76
|
+
|
77
|
+
|
78
|
+
### Upload
|
79
|
+
|
80
|
+
```bash
|
81
|
+
# Note, you need to either set environment variables DT_API_URL and DT_API_TOKEN or pass them as arguments
|
82
|
+
dt-sdk upload
|
83
|
+
```
|
48
84
|
|
49
85
|
## Developing
|
50
86
|
|
@@ -64,4 +100,14 @@ hatch run lint:all
|
|
64
100
|
|
65
101
|
```console
|
66
102
|
hatch build
|
67
|
-
```
|
103
|
+
```
|
104
|
+
|
105
|
+
### Building docs
|
106
|
+
|
107
|
+
```console
|
108
|
+
hatch run docs:build
|
109
|
+
```
|
110
|
+
|
111
|
+
## License
|
112
|
+
|
113
|
+
`dt-extensions-sdk` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
docs/conf.py,sha256=YNcAnuTe9rU_2ktEHdDLBgr013WMGuDR7kzcxEuVJNY,3582
|
2
|
+
dynatrace_extension/__about__.py,sha256=PmqLyPzjaUchXdOD4KgX_mnu19HbF9u6_1dod8bXTCA,112
|
2
3
|
dynatrace_extension/__init__.py,sha256=XYHyWducrLWengm6jcCZMYAHzaQwQfoJKzKT4QvhTxE,779
|
3
4
|
dynatrace_extension/cli/__init__.py,sha256=eg2YQkeboIfJ_hcUGp1WFEvT-moa2qGGN-L9RjTbxCM,128
|
4
5
|
dynatrace_extension/cli/main.py,sha256=MbTCwhI3i7l1IcPHMgpbA4DqOZ5kVCtIkouoz5eWYOE,16254
|
@@ -17,16 +18,16 @@ dynatrace_extension/sdk/__init__.py,sha256=sh7MNjmyR0vt-ugkqEHXVqwTNLExfexS0CTK-
|
|
17
18
|
dynatrace_extension/sdk/activation.py,sha256=s1ZToshWNptfmgu5NsZCI_WMsNM3-O8CSzzoauo62Uk,1523
|
18
19
|
dynatrace_extension/sdk/callback.py,sha256=ozMUWjWHRMX9baU2HGhaCEw6ZVjN_z6kRM9OaX85Hvw,6306
|
19
20
|
dynatrace_extension/sdk/communication.py,sha256=xzXXW--0dgvYxmECvZEQ6xI4H1iLCmqbh5p22NSdR40,16486
|
20
|
-
dynatrace_extension/sdk/event.py,sha256=
|
21
|
-
dynatrace_extension/sdk/extension.py,sha256=
|
21
|
+
dynatrace_extension/sdk/event.py,sha256=oyvcm8uTle-A1jKgXIsFwAvl-Ta2RKbFHVZv3sxTPmo,407
|
22
|
+
dynatrace_extension/sdk/extension.py,sha256=jCG3V6xh2hu1zcQKHYw87ogpeDAuLcvFSpiBDcDg1LQ,40759
|
22
23
|
dynatrace_extension/sdk/helper.py,sha256=TyL6aSIN6lhoH2yHZw8NbhtixdvlyV5q6fDh5NPODdc,6753
|
23
|
-
dynatrace_extension/sdk/metric.py,sha256=
|
24
|
+
dynatrace_extension/sdk/metric.py,sha256=QwrfrmFdj-IddZxAZlZrch62TWKDtzrDU88FwBIv30E,3808
|
24
25
|
dynatrace_extension/sdk/runtime.py,sha256=JgP_qVomatVw85ZuAjbR0S-rzrK5U9JwSZXwfQDKNA4,2869
|
25
26
|
dynatrace_extension/sdk/vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
27
|
dynatrace_extension/sdk/vendor/mureq/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
28
|
dynatrace_extension/sdk/vendor/mureq/mureq.py,sha256=gKzGiPmZ2g74Nb8K_6bu0f2coWZHZiZ2aXGzG2Pimlg,15102
|
28
|
-
dt_extensions_sdk-1.1.
|
29
|
-
dt_extensions_sdk-1.1.
|
30
|
-
dt_extensions_sdk-1.1.
|
31
|
-
dt_extensions_sdk-1.1.
|
32
|
-
dt_extensions_sdk-1.1.
|
29
|
+
dt_extensions_sdk-1.1.1.dist-info/METADATA,sha256=X5NaUoYxxzx53TEmj63jjTFTACajkV_JkTpe9esnbDs,2469
|
30
|
+
dt_extensions_sdk-1.1.1.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
|
31
|
+
dt_extensions_sdk-1.1.1.dist-info/entry_points.txt,sha256=pweyOCgENGHjOlT6_kXYaBPOrE3p18K0UettqnNlnoE,55
|
32
|
+
dt_extensions_sdk-1.1.1.dist-info/licenses/LICENSE.txt,sha256=k7kok_OTpJ5sfb5ANni8wu-Q1lXw8OQjNZXdrTGhFKc,1087
|
33
|
+
dt_extensions_sdk-1.1.1.dist-info/RECORD,,
|
dynatrace_extension/__about__.py
CHANGED
dynatrace_extension/sdk/event.py
CHANGED
@@ -71,6 +71,14 @@ class AggregationMode(Enum):
|
|
71
71
|
|
72
72
|
|
73
73
|
class DtEventType(str, Enum):
|
74
|
+
"""Event type.
|
75
|
+
|
76
|
+
Note:
|
77
|
+
Official API v2 documentation:
|
78
|
+
|
79
|
+
https://docs.dynatrace.com/docs/dynatrace-api/environment-api/events-v2/post-event
|
80
|
+
"""
|
81
|
+
|
74
82
|
CUSTOM_INFO = "CUSTOM_INFO"
|
75
83
|
CUSTOM_ALERT = "CUSTOM_ALERT"
|
76
84
|
CUSTOM_ANNOTATION = "CUSTOM_ANNOTATION"
|
@@ -89,40 +97,39 @@ class CountMetricRegistrationEntry(NamedTuple):
|
|
89
97
|
|
90
98
|
@staticmethod
|
91
99
|
def make_list(metric_key: str, dimensions_list: List[str]):
|
92
|
-
"""
|
93
|
-
Get count metric entry for registration that for aggregation uses defined list of dimensions
|
94
|
-
|
95
|
-
:param metric_key: metric key in string
|
96
|
-
:param dimensions_list: list of dimensions ids in string
|
100
|
+
"""Build an entry that uses defined list of dimensions for aggregation.
|
97
101
|
|
102
|
+
Args:
|
103
|
+
metric_key: Metric key in string.
|
104
|
+
dimensions_list: List of dimensions.
|
98
105
|
"""
|
99
106
|
return CountMetricRegistrationEntry(metric_key, AggregationMode.LIST, dimensions_list)
|
100
107
|
|
101
108
|
@staticmethod
|
102
109
|
def make_all(metric_key: str):
|
103
|
-
"""
|
104
|
-
Get count metric entry for registration that for aggregation uses all mint dimensions
|
105
|
-
|
106
|
-
:param metric_key: metric key in string
|
110
|
+
"""Build an entry that uses all mint dimensions for aggregation.
|
107
111
|
|
112
|
+
Args:
|
113
|
+
metric_key: Metric key in string.
|
108
114
|
"""
|
109
115
|
return CountMetricRegistrationEntry(metric_key, AggregationMode.ALL, [])
|
110
116
|
|
111
117
|
@staticmethod
|
112
118
|
def make_none(metric_key: str):
|
113
|
-
"""
|
114
|
-
Get count metric entry for registration that for aggregation uses none of mint dimensions
|
115
|
-
|
116
|
-
:param metric_key: metric key in string
|
119
|
+
"""Build an entry that uses none of mint dimensions for aggregation.
|
117
120
|
|
121
|
+
Args:
|
122
|
+
metric_key: Metric key in string.
|
118
123
|
"""
|
119
124
|
return CountMetricRegistrationEntry(metric_key, AggregationMode.NONE, [])
|
120
125
|
|
121
126
|
def registration_items_dict(self):
|
127
|
+
result = {"aggregation_mode": self.aggregation_mode.value}
|
122
128
|
if self.aggregation_mode == AggregationMode.LIST:
|
123
|
-
|
129
|
+
result["dimensions_list"] = self.dimensions_list
|
130
|
+
return result
|
124
131
|
else:
|
125
|
-
return
|
132
|
+
return result
|
126
133
|
|
127
134
|
|
128
135
|
def _add_sfm_metric(metric: Metric, sfm_metrics: Optional[List[Metric]] = None):
|
@@ -133,6 +140,12 @@ def _add_sfm_metric(metric: Metric, sfm_metrics: Optional[List[Metric]] = None):
|
|
133
140
|
|
134
141
|
|
135
142
|
class Extension:
|
143
|
+
"""Base class for Python extensions.
|
144
|
+
|
145
|
+
Attributes:
|
146
|
+
logger: Embedded logger object for the extension.
|
147
|
+
"""
|
148
|
+
|
136
149
|
_instance: ClassVar = None
|
137
150
|
schedule_decorators: ClassVar = []
|
138
151
|
|
@@ -227,20 +240,33 @@ class Extension:
|
|
227
240
|
|
228
241
|
@property
|
229
242
|
def is_helper(self) -> bool:
|
243
|
+
"""Internal property used by the EEC."""
|
244
|
+
|
230
245
|
return False
|
231
246
|
|
232
247
|
@property
|
233
248
|
def task_id(self) -> str:
|
249
|
+
"""Internal property used by the EEC."""
|
250
|
+
|
234
251
|
return self._task_id
|
235
252
|
|
236
253
|
@property
|
237
254
|
def monitoring_config_id(self) -> str:
|
255
|
+
"""Internal property used by the EEC.
|
256
|
+
|
257
|
+
Represents a unique identifier of the monitoring configuration.
|
258
|
+
that is assigned to this particular extension instance.
|
259
|
+
"""
|
260
|
+
|
238
261
|
return self._monitoring_config_id
|
239
262
|
|
240
263
|
def run(self):
|
241
|
-
"""
|
242
|
-
|
264
|
+
"""Launch the extension instance.
|
265
|
+
|
266
|
+
Calling this method starts the main loop of the extension.
|
267
|
+
|
243
268
|
This method must be invoked once to start the extension,
|
269
|
+
|
244
270
|
if `--fastcheck` is set, the extension will run in fastcheck mode,
|
245
271
|
otherwise the main loop is started, which periodically runs:
|
246
272
|
|
@@ -248,6 +274,7 @@ class Extension:
|
|
248
274
|
* The heartbeat method
|
249
275
|
* The metrics publisher method
|
250
276
|
"""
|
277
|
+
|
251
278
|
self._setup_signal_handlers()
|
252
279
|
if self._is_fastcheck:
|
253
280
|
return self._run_fastcheck()
|
@@ -266,7 +293,8 @@ class Extension:
|
|
266
293
|
sys.exit(0)
|
267
294
|
|
268
295
|
def on_shutdown(self):
|
269
|
-
"""
|
296
|
+
"""Callback method to be invoked when the extension is shutting down.
|
297
|
+
|
270
298
|
Called when extension exits after it has received shutdown signal from EEC
|
271
299
|
This is executed before metrics are flushed to EEC
|
272
300
|
"""
|
@@ -295,15 +323,18 @@ class Extension:
|
|
295
323
|
args: Optional[tuple] = None,
|
296
324
|
activation_type: Optional[ActivationType] = None,
|
297
325
|
) -> None:
|
298
|
-
"""
|
299
|
-
|
300
|
-
|
326
|
+
"""Schedule a method to be executed periodically.
|
327
|
+
|
328
|
+
The callback method will be periodically invoked in a separate thread.
|
301
329
|
The callback method is always immediately scheduled for execution.
|
302
330
|
|
303
|
-
:
|
304
|
-
|
305
|
-
|
306
|
-
|
331
|
+
Args:
|
332
|
+
callback: The callback method to be invoked
|
333
|
+
interval: The time interval between invocations, can be a timedelta object,
|
334
|
+
or an int representing the number of seconds
|
335
|
+
args: Arguments to the callback, if any
|
336
|
+
activation_type: Optional activation type when this callback should run,
|
337
|
+
can be 'ActivationType.LOCAL' or 'ActivationType.REMOTE'
|
307
338
|
"""
|
308
339
|
|
309
340
|
if isinstance(interval, int):
|
@@ -316,14 +347,16 @@ class Extension:
|
|
316
347
|
self._schedule_callback(callback)
|
317
348
|
|
318
349
|
def query(self):
|
319
|
-
"""
|
350
|
+
"""Callback to be executed every minute by default.
|
351
|
+
|
320
352
|
Optional method that can be implemented by subclasses.
|
321
353
|
The query method is always scheduled to run every minute.
|
322
354
|
"""
|
323
355
|
pass
|
324
356
|
|
325
357
|
def initialize(self):
|
326
|
-
"""
|
358
|
+
"""Callback to be executed when the extension starts.
|
359
|
+
|
327
360
|
Called once after the extension starts and the processes arguments are parsed.
|
328
361
|
Sometimes there are tasks the user needs to do that must happen before runtime,
|
329
362
|
but after the activation config has been received, example: Setting the schedule frequency
|
@@ -332,23 +365,27 @@ class Extension:
|
|
332
365
|
pass
|
333
366
|
|
334
367
|
def fastcheck(self) -> Status:
|
335
|
-
"""
|
336
|
-
Called if the extension is run in the `fastcheck` mode
|
368
|
+
"""Callback executed when extension is launched.
|
337
369
|
|
338
|
-
|
370
|
+
Called if the extension is run in the `fastcheck` mode. Only invoked for remote
|
371
|
+
extensions.
|
372
|
+
This method is not called if fastcheck callback was already registered with
|
373
|
+
Extension.register_fastcheck().
|
339
374
|
|
340
|
-
:
|
375
|
+
Returns:
|
376
|
+
Status with optional message whether the fastcheck succeed or failed.
|
341
377
|
"""
|
342
378
|
return Status(StatusValue.OK)
|
343
379
|
|
344
380
|
def register_fastcheck(self, fast_check_callback: Callable[[ActivationConfig, str], Status]):
|
345
|
-
"""
|
346
|
-
Registers fastcheck callback that is executed in the `fastcheck` mode
|
381
|
+
"""Registers fastcheck callback that is executed in the `fastcheck` mode.
|
347
382
|
|
348
383
|
Extension.fastcheck() is not called if fastcheck callback is registered with this method
|
349
384
|
|
350
|
-
:
|
351
|
-
|
385
|
+
Args:
|
386
|
+
fast_check_callback: callable called with ActivationConfig and
|
387
|
+
extension_config arguments. Must return the Status with optional message
|
388
|
+
whether the fastcheck succeed or failed.
|
352
389
|
"""
|
353
390
|
if self._fast_check_callback:
|
354
391
|
api_logger.error("More than one function assigned to fastcheck, last registered one was kept.")
|
@@ -356,10 +393,10 @@ class Extension:
|
|
356
393
|
self._fast_check_callback = fast_check_callback
|
357
394
|
|
358
395
|
def _register_count_metrics(self, *count_metric_entries: CountMetricRegistrationEntry) -> None:
|
359
|
-
"""
|
360
|
-
Sends request to EEC for count metric registration
|
396
|
+
"""Send a count metric registration request to EEC.
|
361
397
|
|
362
|
-
:
|
398
|
+
Args:
|
399
|
+
count_metric_entries: CountMetricRegistrationEntry objects for each count metric to register
|
363
400
|
"""
|
364
401
|
json_pattern = {
|
365
402
|
metric_entry.metric_key: metric_entry.registration_items_dict() for metric_entry in count_metric_entries
|
@@ -367,13 +404,13 @@ class Extension:
|
|
367
404
|
self._client.register_count_metrics(json_pattern)
|
368
405
|
|
369
406
|
def _send_count_delta_signal(self, metric_keys: set[str], force: bool = True) -> None:
|
370
|
-
"""
|
371
|
-
Sends calculate-delta signal to EEC monotonic converter.
|
407
|
+
"""Send calculate-delta signal to EEC monotonic converter.
|
372
408
|
|
373
|
-
:
|
374
|
-
|
375
|
-
|
376
|
-
|
409
|
+
Args:
|
410
|
+
metric_keys: List with metrics for which we want to calculate deltas
|
411
|
+
force: If true, it forces the metrics from cache to be pushed into EEC and then delta signal request is
|
412
|
+
sent. Otherwise, it puts delta signal request in cache and request is sent after nearest (in time) sending
|
413
|
+
metrics to EEC event
|
377
414
|
"""
|
378
415
|
|
379
416
|
with self._metrics_lock:
|
@@ -397,16 +434,20 @@ class Extension:
|
|
397
434
|
timestamp: Optional[datetime] = None,
|
398
435
|
metric_type: MetricType = MetricType.GAUGE,
|
399
436
|
) -> None:
|
400
|
-
"""
|
401
|
-
|
437
|
+
"""Report a metric.
|
438
|
+
|
439
|
+
Metric is sent to EEC using an HTTP request and MINT protocol. EEC then
|
440
|
+
sends the metrics to the tenant.
|
402
441
|
|
442
|
+
By default, it reports a gauge metric.
|
403
443
|
|
404
|
-
:
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
444
|
+
Args:
|
445
|
+
key: The metric key, must follow the MINT specification
|
446
|
+
value: The metric value, can be a simple value or a SummaryStat
|
447
|
+
dimensions: A dictionary of dimensions
|
448
|
+
techrule: The technology rule string set by self.techrule setter.
|
449
|
+
timestamp: The timestamp of the metric, defaults to the current time
|
450
|
+
metric_type: The type of the metric, defaults to MetricType.GAUGE
|
410
451
|
"""
|
411
452
|
|
412
453
|
if techrule:
|
@@ -419,9 +460,15 @@ class Extension:
|
|
419
460
|
self._add_metric(metric)
|
420
461
|
|
421
462
|
def report_mint_lines(self, lines: List[str]) -> None:
|
422
|
-
"""
|
463
|
+
"""Report mint lines using the MINT protocol
|
423
464
|
|
424
|
-
:
|
465
|
+
Examples:
|
466
|
+
Metric lines must comply with the MINT format.
|
467
|
+
|
468
|
+
>>> self.report_mint_lines(["my_metric 1", "my_other_metric 2"])
|
469
|
+
|
470
|
+
Args:
|
471
|
+
lines: A list of mint lines
|
425
472
|
"""
|
426
473
|
self._add_mint_lines(lines)
|
427
474
|
|
@@ -433,13 +480,14 @@ class Extension:
|
|
433
480
|
timestamp: Optional[datetime] = None,
|
434
481
|
severity: Union[Severity, str] = Severity.INFO,
|
435
482
|
) -> None:
|
436
|
-
"""
|
437
|
-
|
438
|
-
:
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
483
|
+
"""Report an event using log ingest.
|
484
|
+
|
485
|
+
Args:
|
486
|
+
title: The title of the event
|
487
|
+
description: The description of the event
|
488
|
+
properties: A dictionary of extra event properties
|
489
|
+
timestamp: The timestamp of the event, defaults to the current time
|
490
|
+
severity: The severity of the event, defaults to Severity.INFO
|
443
491
|
"""
|
444
492
|
if timestamp is None:
|
445
493
|
timestamp = datetime.now(tz=timezone.utc)
|
@@ -469,17 +517,22 @@ class Extension:
|
|
469
517
|
properties: Optional[dict[str, str]] = None,
|
470
518
|
) -> None:
|
471
519
|
"""
|
472
|
-
Reports an event v2
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
:
|
478
|
-
|
479
|
-
|
480
|
-
:
|
481
|
-
|
482
|
-
|
520
|
+
Reports an event using the v2 event ingest API.
|
521
|
+
|
522
|
+
Unlike ``report_event``, this directly raises an event or even a problem
|
523
|
+
based on the specified ``event_type``.
|
524
|
+
|
525
|
+
Note:
|
526
|
+
For reference see: https://www.dynatrace.com/support/help/dynatrace-api/environment-api/events-v2/post-event
|
527
|
+
|
528
|
+
Args:
|
529
|
+
event_type: The event type chosen from type Enum (required)
|
530
|
+
title: The title of the event (required)
|
531
|
+
start_time: The start time of event in UTC ms, if not set, current timestamp (optional)
|
532
|
+
end_time: The end time of event in UTC ms, if not set, current timestamp + timeout (optional)
|
533
|
+
timeout: The timeout of event in minutes, if not set, 15 (optional)
|
534
|
+
entity_selector: The entity selector, if not set, the event is associated with environment entity (optional)
|
535
|
+
properties: A map of event properties (optional)
|
483
536
|
"""
|
484
537
|
event: Dict[str, Any] = {"eventType": event_type, "title": title}
|
485
538
|
if start_time:
|
@@ -496,46 +549,50 @@ class Extension:
|
|
496
549
|
self._send_dt_event(event)
|
497
550
|
|
498
551
|
def report_dt_event_dict(self, event: dict):
|
499
|
-
"""
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
"
|
508
|
-
|
509
|
-
"enum": [
|
510
|
-
"CUSTOM_INFO",
|
511
|
-
"CUSTOM_ANNOTATION",
|
512
|
-
"CUSTOM_CONFIGURATION",
|
513
|
-
"CUSTOM_DEPLOYMENT",
|
514
|
-
"MARKED_FOR_TERMINATION",
|
515
|
-
"ERROR_EVENT",
|
516
|
-
"AVAILABILITY_EVENT",
|
517
|
-
"PERFORMANCE_EVENT",
|
518
|
-
"RESOURCE_CONTENTION_EVENT",
|
519
|
-
"CUSTOM_ALERT"
|
520
|
-
]
|
521
|
-
},
|
522
|
-
"title": {
|
523
|
-
"type": "string",
|
524
|
-
"minLength": 1
|
525
|
-
},
|
526
|
-
"startTime": {"type": "integer"},
|
527
|
-
"endTime": {"type": "integer"},
|
528
|
-
"timeout": {"type": "integer"},
|
529
|
-
"entitySelector": {"type": "string"},
|
552
|
+
"""Report an event using event ingest API with provided dictionary.
|
553
|
+
|
554
|
+
Note:
|
555
|
+
For reference see: https://www.dynatrace.com/support/help/dynatrace-api/environment-api/events-v2/post-event
|
556
|
+
|
557
|
+
Format of the event dictionary::
|
558
|
+
|
559
|
+
{
|
560
|
+
"type": "object",
|
561
|
+
"required": ["eventType", "title"],
|
530
562
|
"properties": {
|
531
|
-
"
|
532
|
-
|
533
|
-
"
|
563
|
+
"eventType": {
|
564
|
+
"type": "string",
|
565
|
+
"enum": [
|
566
|
+
"CUSTOM_INFO",
|
567
|
+
"CUSTOM_ANNOTATION",
|
568
|
+
"CUSTOM_CONFIGURATION",
|
569
|
+
"CUSTOM_DEPLOYMENT",
|
570
|
+
"MARKED_FOR_TERMINATION",
|
571
|
+
"ERROR_EVENT",
|
572
|
+
"AVAILABILITY_EVENT",
|
573
|
+
"PERFORMANCE_EVENT",
|
574
|
+
"RESOURCE_CONTENTION_EVENT",
|
575
|
+
"CUSTOM_ALERT"
|
576
|
+
]
|
577
|
+
},
|
578
|
+
"title": {
|
579
|
+
"type": "string",
|
580
|
+
"minLength": 1
|
581
|
+
},
|
582
|
+
"startTime": {"type": "integer"},
|
583
|
+
"endTime": {"type": "integer"},
|
584
|
+
"timeout": {"type": "integer"},
|
585
|
+
"entitySelector": {"type": "string"},
|
586
|
+
"properties": {
|
587
|
+
"type": "object",
|
588
|
+
"patternProperties": {
|
589
|
+
"^.*$": {"type": "string"}
|
590
|
+
}
|
534
591
|
}
|
535
592
|
}
|
536
593
|
}
|
537
|
-
}
|
538
594
|
"""
|
595
|
+
|
539
596
|
if "eventType" not in event or "title" not in event:
|
540
597
|
raise ValueError('"eventType" not present' if "eventType" not in event else '"title" not present in event')
|
541
598
|
for key, value in event.items():
|
@@ -553,31 +610,40 @@ class Extension:
|
|
553
610
|
self._send_dt_event(event)
|
554
611
|
|
555
612
|
def report_log_event(self, log_event: dict):
|
556
|
-
"""
|
613
|
+
"""Report a custom log event using log ingest.
|
557
614
|
|
558
|
-
:
|
615
|
+
Note:
|
616
|
+
See reference: https://www.dynatrace.com/support/help/shortlink/log-monitoring-log-data-ingestion
|
617
|
+
|
618
|
+
Args:
|
619
|
+
log_event: The log event dictionary.
|
559
620
|
"""
|
560
621
|
self._send_events(log_event)
|
561
622
|
|
562
623
|
def report_log_events(self, log_events: List[dict]):
|
563
|
-
"""
|
624
|
+
"""Report a list of custom log events using log ingest.
|
564
625
|
|
565
|
-
:
|
626
|
+
Args:
|
627
|
+
log_events: The list of log events
|
566
628
|
"""
|
567
629
|
self._send_events(log_events)
|
568
630
|
|
569
631
|
def report_log_lines(self, log_lines: List[Union[str, bytes]]):
|
570
|
-
"""
|
632
|
+
"""Report a list of log lines using log ingest
|
571
633
|
|
572
|
-
:
|
634
|
+
Args:
|
635
|
+
log_lines: The list of log lines
|
573
636
|
"""
|
574
637
|
events = [{"content": line} for line in log_lines]
|
575
638
|
self._send_events(events)
|
576
639
|
|
577
640
|
@property
|
578
641
|
def enabled_feature_sets(self) -> dict[str, list[str]]:
|
579
|
-
"""
|
580
|
-
|
642
|
+
"""Map of enabled feautre sets and corresponding metrics.
|
643
|
+
|
644
|
+
Returns:
|
645
|
+
Dictionary containing enabled feature sets with corresponding
|
646
|
+
metrics defined in ``extension.yaml``.
|
581
647
|
"""
|
582
648
|
return {
|
583
649
|
feature_set_name: metric_keys
|
@@ -587,15 +653,19 @@ class Extension:
|
|
587
653
|
|
588
654
|
@property
|
589
655
|
def enabled_feature_sets_names(self) -> list[str]:
|
590
|
-
"""
|
591
|
-
|
656
|
+
"""Names of enabled feature sets.
|
657
|
+
|
658
|
+
Returns:
|
659
|
+
List containing names of enabled feature sets.
|
592
660
|
"""
|
593
661
|
return self.activation_config.feature_sets
|
594
662
|
|
595
663
|
@property
|
596
664
|
def enabled_feature_sets_metrics(self) -> list[str]:
|
597
|
-
"""
|
598
|
-
|
665
|
+
"""Enabled metrics.
|
666
|
+
|
667
|
+
Returns:
|
668
|
+
List of all metric keys from enabled feature sets
|
599
669
|
"""
|
600
670
|
return list(chain(*self.enabled_feature_sets.values()))
|
601
671
|
|
@@ -651,10 +721,11 @@ class Extension:
|
|
651
721
|
if not self.is_helper:
|
652
722
|
self.schedule(self.query, timedelta(minutes=1))
|
653
723
|
except Exception as e:
|
654
|
-
|
655
|
-
|
656
|
-
self._client.send_status(Status(StatusValue.GENERIC_ERROR,
|
657
|
-
self._initialization_error =
|
724
|
+
msg = f"Error running self.initialize {self}: {e!r}"
|
725
|
+
api_logger.exception(msg)
|
726
|
+
self._client.send_status(Status(StatusValue.GENERIC_ERROR, msg))
|
727
|
+
self._initialization_error = msg
|
728
|
+
raise e
|
658
729
|
|
659
730
|
@property
|
660
731
|
def _metadata(self) -> dict:
|
@@ -750,9 +821,11 @@ class Extension:
|
|
750
821
|
self._metrics = []
|
751
822
|
|
752
823
|
def _prepare_sfm_metrics(self) -> List[str]:
|
824
|
+
"""Prepare self monitoring metrics.
|
825
|
+
|
826
|
+
Builds the list of mint metric lines to send as self monitoring metrics.
|
753
827
|
"""
|
754
|
-
|
755
|
-
"""
|
828
|
+
|
756
829
|
sfm_metrics: List[Metric] = []
|
757
830
|
sfm_dimensions = {"dt.extension.config.id": self.monitoring_config_id}
|
758
831
|
_add_sfm_metric(
|
@@ -926,16 +999,28 @@ class Extension:
|
|
926
999
|
def _send_dt_event(self, event: dict[str, str | int | dict[str, str]]):
|
927
1000
|
self._client.send_dt_event(event)
|
928
1001
|
|
929
|
-
def get_version(self):
|
1002
|
+
def get_version(self) -> str:
|
1003
|
+
"""Return the version of extensions sdk library."""
|
1004
|
+
|
930
1005
|
return __version__
|
931
1006
|
|
932
1007
|
@property
|
933
1008
|
def techrule(self) -> str:
|
1009
|
+
"""Internal property used by the EEC."""
|
1010
|
+
|
934
1011
|
return self._techrule
|
935
1012
|
|
936
1013
|
@techrule.setter
|
937
1014
|
def techrule(self, value):
|
938
1015
|
self._techrule = value
|
939
1016
|
|
940
|
-
def get_activation_config(self):
|
1017
|
+
def get_activation_config(self) -> ActivationConfig:
|
1018
|
+
"""Retrieve the activation config.
|
1019
|
+
|
1020
|
+
Represents activation configuration assigned to this particular
|
1021
|
+
extension instance.
|
1022
|
+
|
1023
|
+
Returns:
|
1024
|
+
ActivationConfig object.
|
1025
|
+
"""
|
941
1026
|
return self.activation_config
|
@@ -61,8 +61,6 @@ class Metric:
|
|
61
61
|
return self._key_and_dimensions() == other._key_and_dimensions()
|
62
62
|
|
63
63
|
def to_mint_line(self) -> str:
|
64
|
-
# https://bitbucket.lab.dynatrace.org/projects/ONE/repos/schemaless-metrics-spec/browse
|
65
|
-
|
66
64
|
# Add key and dimensions
|
67
65
|
line = f"{self._key_and_dimensions()}"
|
68
66
|
|
File without changes
|
File without changes
|
{dt_extensions_sdk-1.1.0.dist-info → dt_extensions_sdk-1.1.1.dist-info}/licenses/LICENSE.txt
RENAMED
File without changes
|