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 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.0
4
- Project-URL: Documentation, https://github.com/unknown/dynatrace-extensions-sdk#readme
5
- Project-URL: Issues, https://github.com/unknown/dynatrace-extensions-sdk/issues
6
- Project-URL: Source, https://github.com/unknown/dynatrace-extensions-sdk
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.7
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
- - [Installation](#installation)
35
+ - [Quick Start](#quick-start)
36
36
  - [License](#license)
37
37
  - [Developing](#developing)
38
38
 
39
- ## Installation
39
+ ## Quick Start
40
40
 
41
- ```console
42
- pip install dt-extensions-sdk
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
- ## License
52
+ ### Create signing certificates
53
+
54
+ ```bash
55
+ dt-sdk gencerts
56
+ ```
46
57
 
47
- `dt-extensions-sdk` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
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
- dynatrace_extension/__about__.py,sha256=88jJscpSyDohq8X8smaiFVx4eiwxXIttJZPQSeA_-tA,112
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=AmMDlbNJTu8EWfcgY1RAwk1pmu7y6-8l33igSjWEdiQ,391
21
- dynatrace_extension/sdk/extension.py,sha256=V8vdH_Jv5duOF3NuiDp9hHkCqh80XNvYzvfieFR9S74,38690
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=9eFap_Zcxlrhn3_xvp8JumRwOpmVcZ4XM1paybqD0NE,3907
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.0.dist-info/METADATA,sha256=u-0zPB4CE2QZpQhBJpD-EFm_ODXdSqRuewVyPJEbFZA,1823
29
- dt_extensions_sdk-1.1.0.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
30
- dt_extensions_sdk-1.1.0.dist-info/entry_points.txt,sha256=pweyOCgENGHjOlT6_kXYaBPOrE3p18K0UettqnNlnoE,55
31
- dt_extensions_sdk-1.1.0.dist-info/licenses/LICENSE.txt,sha256=k7kok_OTpJ5sfb5ANni8wu-Q1lXw8OQjNZXdrTGhFKc,1087
32
- dt_extensions_sdk-1.1.0.dist-info/RECORD,,
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,,
@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2023-present Dynatrace LLC
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "1.1.0"
4
+ __version__ = "1.1.1"
@@ -6,9 +6,7 @@ from enum import Enum
6
6
 
7
7
 
8
8
  class Severity(Enum):
9
- """
10
- Severity of an event.
11
- """
9
+ """Severity of an event ingested through log ingest."""
12
10
 
13
11
  EMERGENCY = "EMERGENCY"
14
12
  ERROR = "ERROR"
@@ -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
- return {"aggregation_mode": self.aggregation_mode.value, "dimensions_list": self.dimensions_list}
129
+ result["dimensions_list"] = self.dimensions_list
130
+ return result
124
131
  else:
125
- return {"aggregation_mode": self.aggregation_mode.value}
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
- Extension main loop.
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
- Schedules a method to be executed periodically,
300
- the callback method will be periodically invoked in a separate thread.
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
- :param callback: The callback method to be invoked
304
- :param interval: The time interval between invocations, can be a timedelta object, or an int representing the number of seconds
305
- :param args: Arguments to the callback, if any
306
- :param activation_type: Optional activation type when this callback should run, can be 'ActivationType.LOCAL' or 'ActivationType.REMOTE'
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
- This method is not called if fastcheck callback was already registered with Extension.register_fastcheck()
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
- :return: status with optional message whether the fastcheck succeed or failed
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
- :param fast_check_callback: callable called with activation_config: ActivationConfig and extension_config: str arguments
351
- must return the Status with optional message whether the fastcheck succeed or failed
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
- :param count_metric_entries: CountMetricRegistrationEntry objects for each count metric to register
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
- :param metric_keys: List with metrics for which we want to calculate deltas
374
- :param force: If true, it forces the metrics from cache to be pushed into EEC and then delta signal request is
375
- sent. Otherwise, it puts delta signal request in cache and request is sent after nearest (in time) sending
376
- metrics to EEC event
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
- """Reports a metric using the MINT protocol
401
- By default, it reports a gauge metric
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
- :param key: The metric key, must follow the MINT specification
405
- :param value: The metric value, can be a simple value or a SummaryStat
406
- :param dimensions: A dictionary of dimensions
407
- :param techrule: The technology rule string set by self.techrule setter.
408
- :param timestamp: The timestamp of the metric, defaults to the current time
409
- :param metric_type: The type of the metric, defaults to MetricType.GAUGE
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
- """Reports mint lines using the MINT protocol
463
+ """Report mint lines using the MINT protocol
423
464
 
424
- :param lines: A list of mint lines, example: ["my_metric 1", "my_other_metric 2"]
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
- """Reports an event using log ingest
437
-
438
- :param title: The title of the event
439
- :param description: The description of the event
440
- :param properties: A dictionary of extra event properties
441
- :param timestamp: The timestamp of the event, defaults to the current time
442
- :param severity: The severity of the event, defaults to Severity.INFO
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 using event ingest
473
-
474
- For reference see: https://www.dynatrace.com/support/help/dynatrace-api/environment-api/events-v2/post-event
475
-
476
- :param event_type: The event type chosen from type Enum (required)
477
- :param title: The title of the event (required)
478
- :param start_time: The start time of event in UTC ms, if not set, current timestamp (optional)
479
- :param end_time: The end time of event in UTC ms, if not set, current timestamp + timeout (optional)
480
- :param timeout: The timeout of event in minutes, if not set, 15 (optional)
481
- :param entity_selector: The entity selector, if not set, the event is associated with environment entity (optional)
482
- :param properties: A map of event properties (optional)
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
- Reports an event v2 using event ingest using provided dictionary resembling required json
501
- For reference see: https://www.dynatrace.com/support/help/dynatrace-api/environment-api/events-v2/post-event
502
- (see schema)
503
- {
504
- "type": "object",
505
- "required": ["eventType", "title"],
506
- "properties": {
507
- "eventType": {
508
- "type": "string",
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
- "type": "object",
532
- "patternProperties": {
533
- "^.*$": {"type": "string"}
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
- """Reports a custom log event using log ingest
613
+ """Report a custom log event using log ingest.
557
614
 
558
- :param log_event: The log event dictionary, reference: https://www.dynatrace.com/support/help/shortlink/log-monitoring-log-data-ingestion
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
- """Reports a list of custom log events using log ingest
624
+ """Report a list of custom log events using log ingest.
564
625
 
565
- :param log_events: The list of log events
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
- """Reports a list of log lines using log ingest
632
+ """Report a list of log lines using log ingest
571
633
 
572
- :param log_lines: The list of log lines
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
- Dictionary containing enabled feature sets with corresponding metrics defined in `extension.yaml`
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
- List containing names of enabled feature sets
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
- List of all metric keys from enabled feature sets
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
- api_logger.exception(f"Error running initialize {self}: {e!r}")
655
- status_message = "Python datasource initialization error: " + repr(e)
656
- self._client.send_status(Status(StatusValue.GENERIC_ERROR, status_message))
657
- self._initialization_error = status_message
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
- Build the list of mint metric lines to send as self monitoring metrics
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