dt-extensions-sdk 1.7.1__tar.gz → 1.7.3__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.
- dt_extensions_sdk-1.7.3/.github/workflows/build-package.yml +40 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/.github/workflows/publish.yml +6 -34
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/PKG-INFO +1 -1
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/__about__.py +1 -1
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/callback.py +4 -4
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/communication.py +1 -1
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/extension.py +19 -18
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/status.py +19 -15
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_extension.py +5 -5
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_status.py +19 -18
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/.github/workflows/gh-pages-docs.yml +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/.gitignore +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/LICENSE.txt +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/README.md +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/dt-sdk-header.png +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/dt-sdk-logo.png +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/favicon.ico +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-01-new-extension.png +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-02-type.png +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-03-import.png +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-04-import-remote.png +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-05-activation.png +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-06-activation-config.png +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/api/events/event_severity.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/api/events/event_type.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/api/events/index.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/api/extension.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/api/metrics/index.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/api/metrics/metric.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/api/metrics/metric_type.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/assemble.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/build.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/create.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/gencerts.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/help.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/run.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/sign.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/upload.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/cli/wheel.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/conf.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/guides/building.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/guides/extension_structure.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/guides/installation.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/guides/migration.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/index.rst +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/requirements.txt +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/create.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/.gitignore.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/README.md.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/activation.json.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/extension/activationSchema.json.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/extension/extension.yaml.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/extension_name/__init__.py.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/extension_name/__main__.py.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/ruff.toml.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/secrets.json.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/extension_template/setup.py.template +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/main.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/schema.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/activation.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/event.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/helper.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/metric.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/runtime.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/snapshot.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/throttled_logger.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/vendor/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/vendor/mureq/LICENSE +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/vendor/mureq/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/vendor/mureq/mureq.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/pyproject.toml +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/cli/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/cli/test_dt_sdk.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/cli/test_templates.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/cli/test_types.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/data/snapshot.json +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/__init__.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_activation.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_callback.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_communication.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_endpoints_sfm.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_metric.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_runtime_properties.py +0 -0
- {dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/tests/sdk/test_snapshot.py +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Build distribution 📦
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-package:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Set up Python
|
|
15
|
+
uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.10"
|
|
18
|
+
|
|
19
|
+
- name: Install hatch
|
|
20
|
+
run: |
|
|
21
|
+
pip install hatch --user
|
|
22
|
+
|
|
23
|
+
- name: Run tests
|
|
24
|
+
run: |
|
|
25
|
+
python3 -m hatch run test
|
|
26
|
+
|
|
27
|
+
- name: Run linting
|
|
28
|
+
run: |
|
|
29
|
+
python3 -m hatch run lint:all
|
|
30
|
+
|
|
31
|
+
- name: Build a wheel and a source tarball
|
|
32
|
+
run: |
|
|
33
|
+
python3 -m hatch build
|
|
34
|
+
|
|
35
|
+
- name: Upload built distributions
|
|
36
|
+
uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: package
|
|
39
|
+
path: dist/*
|
|
40
|
+
|
|
@@ -2,49 +2,21 @@ name: Publish to PyPI
|
|
|
2
2
|
on:
|
|
3
3
|
workflow_dispatch:
|
|
4
4
|
|
|
5
|
-
jobs:
|
|
6
|
-
|
|
7
|
-
name: Build distribution 📦
|
|
5
|
+
jobs:
|
|
6
|
+
check-tag:
|
|
8
7
|
runs-on: ubuntu-latest
|
|
9
|
-
|
|
10
8
|
steps:
|
|
11
9
|
- id: check_ref
|
|
12
10
|
run: echo "::set-output name=match::$(echo '${{ github.ref }}' | grep -Pq '^refs/tags/v\d+\.\d+\.\d+$' && echo true || echo false)"
|
|
13
11
|
shell: bash
|
|
14
|
-
|
|
15
12
|
- name: Check if tag is valid
|
|
16
13
|
if: steps.check_ref.outputs.match != 'true'
|
|
17
14
|
run: exit 1
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
with:
|
|
24
|
-
python-version: "3.10"
|
|
25
|
-
|
|
26
|
-
- name: Install hatch
|
|
27
|
-
run: |
|
|
28
|
-
pip install hatch --user
|
|
29
|
-
|
|
30
|
-
- name: Run tests
|
|
31
|
-
run: |
|
|
32
|
-
python3 -m hatch run test
|
|
33
|
-
|
|
34
|
-
- name: Run linting
|
|
35
|
-
run: |
|
|
36
|
-
python3 -m hatch run lint:all
|
|
37
|
-
|
|
38
|
-
- name: Build a wheel and a source tarball
|
|
39
|
-
run: |
|
|
40
|
-
python3 -m hatch build
|
|
41
|
-
|
|
42
|
-
- name: Store the distribution packages
|
|
43
|
-
uses: actions/upload-artifact@v4
|
|
44
|
-
with:
|
|
45
|
-
name: package
|
|
46
|
-
path: |
|
|
47
|
-
dist/*
|
|
16
|
+
build-package:
|
|
17
|
+
needs:
|
|
18
|
+
- check-tag
|
|
19
|
+
uses: ./.github/workflows/build-package.yml
|
|
48
20
|
|
|
49
21
|
github-release:
|
|
50
22
|
name: Create GitHub release
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dt-extensions-sdk
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.3
|
|
4
4
|
Project-URL: Documentation, https://github.com/dynatrace-extensions/dt-extensions-python-sdk#readme
|
|
5
5
|
Project-URL: Issues, https://github.com/dynatrace-extensions/dt-extensions-python-sdk/issues
|
|
6
6
|
Project-URL: Source, https://github.com/dynatrace-extensions/dt-extensions-python-sdk
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
import random
|
|
7
|
+
import time
|
|
7
8
|
from collections.abc import Callable
|
|
8
9
|
from datetime import datetime, timedelta
|
|
9
10
|
from timeit import default_timer as timer
|
|
@@ -39,6 +40,7 @@ class WrappedCallback:
|
|
|
39
40
|
self.duration = 0 # global counter
|
|
40
41
|
self.duration_interval_total = 0 # counter per interval = 1 min by default
|
|
41
42
|
self.cluster_time_diff = 0
|
|
43
|
+
self.start_timestamp_monotonic = time.monotonic()
|
|
42
44
|
self.start_timestamp = self.get_current_time_with_cluster_diff()
|
|
43
45
|
self.running_in_sim = running_in_sim
|
|
44
46
|
self.activation_type = activation_type
|
|
@@ -147,8 +149,6 @@ class WrappedCallback:
|
|
|
147
149
|
"""
|
|
148
150
|
Get the timestamp for the next execution of the callback
|
|
149
151
|
This is done using execution total, the interval and the start timestamp
|
|
150
|
-
:return:
|
|
152
|
+
:return: float
|
|
151
153
|
"""
|
|
152
|
-
return (
|
|
153
|
-
self.start_timestamp + timedelta(seconds=self.interval.total_seconds() * (self.iterations or 1))
|
|
154
|
-
).timestamp()
|
|
154
|
+
return self.start_timestamp_monotonic + self.interval.total_seconds() * (self.iterations or 1)
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/communication.py
RENAMED
|
@@ -343,7 +343,7 @@ class DebugClient(CommunicationClient):
|
|
|
343
343
|
def get_feature_sets(self) -> dict[str, list[str]]:
|
|
344
344
|
# This is only called from dt-sdk run, where PyYaml is installed because of dt-cli
|
|
345
345
|
# Do NOT move this to the top of the file
|
|
346
|
-
import yaml #
|
|
346
|
+
import yaml # noqa: PLC0415
|
|
347
347
|
|
|
348
348
|
# Grab the feature sets from the extension.yaml file
|
|
349
349
|
extension_yaml = yaml.safe_load(self.extension_config)
|
|
@@ -28,10 +28,11 @@ from .snapshot import Snapshot
|
|
|
28
28
|
from .status import EndpointStatuses, EndpointStatusesMap, IgnoreStatus, Status, StatusValue
|
|
29
29
|
from .throttled_logger import StrictThrottledHandler, ThrottledHandler
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
# Intervals defined in seconds for internal callbacks
|
|
32
|
+
HEARTBEAT_INTERVAL = 50
|
|
33
|
+
METRIC_SENDING_INTERVAL = 30
|
|
34
|
+
SFM_METRIC_SENDING_INTERVAL = 60
|
|
35
|
+
TIME_DIFF_INTERVAL = 60
|
|
35
36
|
|
|
36
37
|
CALLBACKS_THREAD_POOL_SIZE = 100
|
|
37
38
|
INTERNAL_THREAD_POOL_SIZE = 20
|
|
@@ -180,11 +181,11 @@ class Extension:
|
|
|
180
181
|
"""
|
|
181
182
|
|
|
182
183
|
_instance: ClassVar = None
|
|
183
|
-
schedule_decorators: ClassVar = []
|
|
184
|
+
schedule_decorators: ClassVar[list[tuple[Callable, timedelta | int, tuple | None, ActivationType | None]]] = []
|
|
184
185
|
|
|
185
186
|
def __new__(cls, *args, **kwargs): # noqa: ARG004
|
|
186
187
|
if Extension._instance is None:
|
|
187
|
-
Extension._instance = super(
|
|
188
|
+
Extension._instance = super().__new__(cls)
|
|
188
189
|
return Extension._instance
|
|
189
190
|
|
|
190
191
|
def __init__(self, name: str = "") -> None:
|
|
@@ -240,15 +241,15 @@ class Extension:
|
|
|
240
241
|
self._running_callbacks: dict[int, WrappedCallback] = {}
|
|
241
242
|
self._running_callbacks_lock: Lock = Lock()
|
|
242
243
|
|
|
243
|
-
self._scheduler = sched.scheduler(time.
|
|
244
|
+
self._scheduler = sched.scheduler(time.monotonic, time.sleep)
|
|
244
245
|
|
|
245
246
|
# Timestamps for scheduling of internal callbacks
|
|
246
|
-
self._next_internal_callbacks_timestamps: dict[str,
|
|
247
|
-
"timediff":
|
|
248
|
-
"heartbeat":
|
|
249
|
-
"metrics":
|
|
250
|
-
"events":
|
|
251
|
-
"sfm_metrics":
|
|
247
|
+
self._next_internal_callbacks_timestamps: dict[str, float] = {
|
|
248
|
+
"timediff": time.monotonic() + TIME_DIFF_INTERVAL,
|
|
249
|
+
"heartbeat": time.monotonic() + HEARTBEAT_INTERVAL,
|
|
250
|
+
"metrics": time.monotonic() + METRIC_SENDING_INTERVAL,
|
|
251
|
+
"events": time.monotonic() + METRIC_SENDING_INTERVAL,
|
|
252
|
+
"sfm_metrics": time.monotonic() + SFM_METRIC_SENDING_INTERVAL,
|
|
252
253
|
}
|
|
253
254
|
|
|
254
255
|
# Executors for the callbacks and internal methods
|
|
@@ -412,7 +413,7 @@ class Extension:
|
|
|
412
413
|
else:
|
|
413
414
|
self._schedule_callback(callback)
|
|
414
415
|
|
|
415
|
-
def query(self):
|
|
416
|
+
def query(self) -> Any:
|
|
416
417
|
"""Callback to be executed every minute by default.
|
|
417
418
|
|
|
418
419
|
Optional method that can be implemented by subclasses.
|
|
@@ -683,7 +684,7 @@ class Extension:
|
|
|
683
684
|
msg = f"Event type must be a DtEventType enum value, got: {value}"
|
|
684
685
|
raise ValueError(msg)
|
|
685
686
|
if key == "properties":
|
|
686
|
-
for prop_key, prop_val in
|
|
687
|
+
for prop_key, prop_val in value.items():
|
|
687
688
|
if not isinstance(prop_key, str) or not isinstance(prop_val, str):
|
|
688
689
|
msg = f'invalid "properties" member: {prop_key}: {prop_val}, required: "str": str'
|
|
689
690
|
raise ValueError(msg)
|
|
@@ -777,7 +778,7 @@ class Extension:
|
|
|
777
778
|
parser.add_argument("--secrets", required=False, default="secrets.json")
|
|
778
779
|
parser.add_argument("--no-print-metrics", required=False, action="store_true")
|
|
779
780
|
|
|
780
|
-
args,
|
|
781
|
+
args, _ = parser.parse_known_args()
|
|
781
782
|
self._is_fastcheck = args.fastcheck
|
|
782
783
|
if args.dsid is None:
|
|
783
784
|
# DEV mode
|
|
@@ -1169,10 +1170,10 @@ class Extension:
|
|
|
1169
1170
|
def _send_dt_event(self, event: dict[str, str | int | dict[str, str]]):
|
|
1170
1171
|
self._client.send_dt_event(event)
|
|
1171
1172
|
|
|
1172
|
-
def _get_and_set_next_internal_callback_timestamp(self, callback_name: str, interval:
|
|
1173
|
+
def _get_and_set_next_internal_callback_timestamp(self, callback_name: str, interval: float) -> float:
|
|
1173
1174
|
next_timestamp = self._next_internal_callbacks_timestamps[callback_name]
|
|
1174
1175
|
self._next_internal_callbacks_timestamps[callback_name] += interval
|
|
1175
|
-
return next_timestamp
|
|
1176
|
+
return next_timestamp
|
|
1176
1177
|
|
|
1177
1178
|
def get_version(self) -> str:
|
|
1178
1179
|
"""Return the extension version."""
|
|
@@ -114,6 +114,9 @@ class EndpointStatus:
|
|
|
114
114
|
def __eq__(self, other):
|
|
115
115
|
return isinstance(other, EndpointStatus) and self.__dict__ == other.__dict__
|
|
116
116
|
|
|
117
|
+
def __hash__(self):
|
|
118
|
+
return hash(tuple(sorted(self.__dict__.items())))
|
|
119
|
+
|
|
117
120
|
|
|
118
121
|
class EndpointStatuses:
|
|
119
122
|
def __init__(self, total_endpoints_number=None) -> None:
|
|
@@ -227,33 +230,34 @@ class EndpointStatusesMap:
|
|
|
227
230
|
with self._lock:
|
|
228
231
|
# Summarize all statuses
|
|
229
232
|
ok_count = 0
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
+
warning_count = 0
|
|
234
|
+
error_count = 0
|
|
235
|
+
messages_to_report = []
|
|
233
236
|
|
|
234
237
|
for ep_record in self._ep_records.values():
|
|
235
238
|
ep_status = ep_record.ep_status
|
|
236
|
-
if ep_status.status.is_warning():
|
|
237
|
-
has_warning_status = True
|
|
238
239
|
|
|
239
|
-
if ep_status.status.
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
if ep_status.status.is_warning():
|
|
241
|
+
warning_count += 1
|
|
242
|
+
messages_to_report.append(f"{ep_status.endpoint} - {ep_status.status.value} {ep_status.message}")
|
|
243
|
+
elif ep_status.status.is_error():
|
|
244
|
+
error_count += 1
|
|
245
|
+
messages_to_report.append(f"{ep_status.endpoint} - {ep_status.status.value} {ep_status.message}")
|
|
242
246
|
else:
|
|
243
247
|
ok_count += 1
|
|
244
248
|
|
|
249
|
+
status_msg = f"Endpoints OK: {ok_count} WARNING: {warning_count} ERROR: {error_count}"
|
|
250
|
+
|
|
245
251
|
# Early return if all OK
|
|
246
|
-
if
|
|
247
|
-
return Status(StatusValue.OK,
|
|
252
|
+
if error_count == 0 and warning_count == 0:
|
|
253
|
+
return Status(StatusValue.OK, status_msg)
|
|
248
254
|
|
|
249
255
|
# Build final status if some errors present
|
|
250
|
-
|
|
251
|
-
all_endpoints_faulty = ok_count == 0
|
|
256
|
+
status_msg += f" Unhealthy endpoints: {', '.join(messages_to_report)}"
|
|
252
257
|
|
|
253
|
-
if
|
|
258
|
+
if ok_count == 0 and warning_count == 0:
|
|
254
259
|
status_value = StatusValue.GENERIC_ERROR
|
|
255
260
|
else:
|
|
256
261
|
status_value = StatusValue.WARNING
|
|
257
262
|
|
|
258
|
-
|
|
259
|
-
return Status(status=status_value, message=message)
|
|
263
|
+
return Status(status=status_value, message=status_msg)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import threading
|
|
2
2
|
import time
|
|
3
3
|
import unittest
|
|
4
|
-
from datetime import
|
|
4
|
+
from datetime import timedelta
|
|
5
5
|
from unittest.mock import MagicMock, mock_open, patch
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
@@ -27,7 +27,7 @@ class TestExtension(unittest.TestCase):
|
|
|
27
27
|
extension = Extension()
|
|
28
28
|
extension.logger = MagicMock()
|
|
29
29
|
extension._running_in_sim = True
|
|
30
|
-
extension._next_heartbeat =
|
|
30
|
+
extension._next_heartbeat = time.monotonic()
|
|
31
31
|
extension._heartbeat_iteration()
|
|
32
32
|
extension._heartbeat.assert_called()
|
|
33
33
|
|
|
@@ -387,15 +387,15 @@ class TestExtension(unittest.TestCase):
|
|
|
387
387
|
extension._client = MagicMock()
|
|
388
388
|
|
|
389
389
|
fastcheck = MagicMock()
|
|
390
|
-
fastcheck.side_effect =
|
|
390
|
+
fastcheck.side_effect = ImportError("SomeException")
|
|
391
391
|
extension.register_fastcheck(fastcheck)
|
|
392
|
-
self.assertRaises(
|
|
392
|
+
self.assertRaises(ImportError, extension._run_fastcheck)
|
|
393
393
|
|
|
394
394
|
fastcheck.assert_called_once()
|
|
395
395
|
extension._client.send_status.assert_called_once()
|
|
396
396
|
self.assertEqual(extension._client.send_status.call_args[0][0].status, StatusValue.GENERIC_ERROR)
|
|
397
397
|
self.assertIn(
|
|
398
|
-
"Python datasource fastcheck error:
|
|
398
|
+
"Python datasource fastcheck error: ImportError('SomeException')",
|
|
399
399
|
extension._client.send_status.call_args[0][0].message,
|
|
400
400
|
)
|
|
401
401
|
|
|
@@ -305,7 +305,7 @@ class TestStatus(unittest.TestCase):
|
|
|
305
305
|
|
|
306
306
|
status = ext._build_current_status()
|
|
307
307
|
self.assertEqual(status.status, StatusValue.OK)
|
|
308
|
-
self.assertIn("OK: 3
|
|
308
|
+
self.assertIn("OK: 3 WARNING: 0 ERROR: 0", status.message)
|
|
309
309
|
|
|
310
310
|
def test_endpoint_status_some_faulty_endpoints(self):
|
|
311
311
|
ext = Extension()
|
|
@@ -334,8 +334,8 @@ class TestStatus(unittest.TestCase):
|
|
|
334
334
|
status = ext._build_current_status()
|
|
335
335
|
self.assertEqual(status.status, StatusValue.WARNING)
|
|
336
336
|
self.assertIn(
|
|
337
|
-
"OK: 1
|
|
338
|
-
"Invalid authorization scheme 2, 6.7.8.9:80 - DEVICE_CONNECTION_ERROR Invalid authorization scheme 3",
|
|
337
|
+
"Endpoints OK: 1 WARNING: 0 ERROR: 2 Unhealthy endpoints: "
|
|
338
|
+
"4.5.6.7:80 - DEVICE_CONNECTION_ERROR Invalid authorization scheme 2, 6.7.8.9:80 - DEVICE_CONNECTION_ERROR Invalid authorization scheme 3",
|
|
339
339
|
status.message,
|
|
340
340
|
)
|
|
341
341
|
|
|
@@ -368,9 +368,8 @@ class TestStatus(unittest.TestCase):
|
|
|
368
368
|
status = ext._build_current_status()
|
|
369
369
|
self.assertEqual(status.status, StatusValue.GENERIC_ERROR)
|
|
370
370
|
self.assertIn(
|
|
371
|
-
"OK: 0
|
|
372
|
-
"Invalid authorization scheme
|
|
373
|
-
"Invalid authorization scheme 5, 6.7.8.9:80 - DEVICE_CONNECTION_ERROR Invalid authorization scheme 6",
|
|
371
|
+
"Endpoints OK: 0 WARNING: 0 ERROR: 3 Unhealthy endpoints: 1.2.3.4:80 - AUTHENTICATION_ERROR Invalid authorization scheme 4, "
|
|
372
|
+
"4.5.6.7:80 - DEVICE_CONNECTION_ERROR Invalid authorization scheme 5, 6.7.8.9:80 - DEVICE_CONNECTION_ERROR Invalid authorization scheme 6",
|
|
374
373
|
status.message,
|
|
375
374
|
)
|
|
376
375
|
|
|
@@ -391,7 +390,7 @@ class TestStatus(unittest.TestCase):
|
|
|
391
390
|
|
|
392
391
|
status = ext._build_current_status()
|
|
393
392
|
self.assertEqual(status.status, StatusValue.OK)
|
|
394
|
-
self.assertNotIn("
|
|
393
|
+
self.assertNotIn("Endpoints", status.message)
|
|
395
394
|
|
|
396
395
|
def test_endpoint_status_single_warning(self):
|
|
397
396
|
ext = Extension()
|
|
@@ -414,7 +413,8 @@ class TestStatus(unittest.TestCase):
|
|
|
414
413
|
status = ext._build_current_status()
|
|
415
414
|
self.assertEqual(status.status, StatusValue.WARNING)
|
|
416
415
|
self.assertIn(
|
|
417
|
-
"OK: 0
|
|
416
|
+
"Endpoints OK: 0 WARNING: 1 ERROR: 0 Unhealthy endpoints: 1.2.3.4:80 - WARNING Invalid authorization scheme A",
|
|
417
|
+
status.message,
|
|
418
418
|
)
|
|
419
419
|
|
|
420
420
|
def test_endpoint_status_single_error(self):
|
|
@@ -438,7 +438,7 @@ class TestStatus(unittest.TestCase):
|
|
|
438
438
|
status = ext._build_current_status()
|
|
439
439
|
self.assertEqual(status.status, StatusValue.GENERIC_ERROR)
|
|
440
440
|
self.assertIn(
|
|
441
|
-
"OK: 0
|
|
441
|
+
"OK: 0 WARNING: 0 ERROR: 1 Unhealthy endpoints: 1.2.3.4:80 - AUTHENTICATION_ERROR Invalid authorization scheme",
|
|
442
442
|
status.message,
|
|
443
443
|
)
|
|
444
444
|
|
|
@@ -467,7 +467,7 @@ class TestStatus(unittest.TestCase):
|
|
|
467
467
|
|
|
468
468
|
status = ext._build_current_status()
|
|
469
469
|
self.assertEqual(status.status, StatusValue.OK)
|
|
470
|
-
self.assertIn("OK: 3
|
|
470
|
+
self.assertIn("OK: 3 WARNING: 0 ERROR: 0", status.message)
|
|
471
471
|
|
|
472
472
|
def test_endpoint_merge_error(self):
|
|
473
473
|
def callback_ep_status_1():
|
|
@@ -494,7 +494,7 @@ class TestStatus(unittest.TestCase):
|
|
|
494
494
|
status = ext._build_current_status()
|
|
495
495
|
self.assertEqual(status.status, StatusValue.GENERIC_ERROR)
|
|
496
496
|
self.assertIn(
|
|
497
|
-
"OK: 0
|
|
497
|
+
"OK: 0 WARNING: 0 ERROR: 2 Unhealthy endpoints: EP_HINT_1 - AUTHENTICATION_ERROR EP1 MSG, EP_HINT_2 - INVALID_CONFIG_ERROR EP2 MSG",
|
|
498
498
|
status.message,
|
|
499
499
|
)
|
|
500
500
|
|
|
@@ -522,7 +522,7 @@ class TestStatus(unittest.TestCase):
|
|
|
522
522
|
|
|
523
523
|
status = ext._build_current_status()
|
|
524
524
|
self.assertEqual(status.status, StatusValue.WARNING)
|
|
525
|
-
self.assertIn("OK: 1
|
|
525
|
+
self.assertIn("OK: 1 WARNING: 1 ERROR: 0 Unhealthy endpoints: EP_HINT_2 - WARNING EP2 MSG", status.message)
|
|
526
526
|
|
|
527
527
|
def test_overall_status_error(self):
|
|
528
528
|
def callback_ep_status():
|
|
@@ -554,7 +554,7 @@ class TestStatus(unittest.TestCase):
|
|
|
554
554
|
status = ext._build_current_status()
|
|
555
555
|
self.assertEqual(status.status, StatusValue.GENERIC_ERROR)
|
|
556
556
|
self.assertIn(
|
|
557
|
-
"Endpoints OK: 0
|
|
557
|
+
"Endpoints OK: 0 WARNING: 0 ERROR: 1 Unhealthy endpoints: EP_HINT - UNKNOWN_ERROR EP MSG"
|
|
558
558
|
"\ncallback_multistatus: GENERIC_ERROR - MULTI MSG\ncallback_status: EEC_CONNECTION_ERROR - STATUS MSG",
|
|
559
559
|
status.message,
|
|
560
560
|
)
|
|
@@ -588,7 +588,7 @@ class TestStatus(unittest.TestCase):
|
|
|
588
588
|
|
|
589
589
|
status = ext._build_current_status()
|
|
590
590
|
self.assertEqual(status.status, StatusValue.OK)
|
|
591
|
-
self.assertIn("Endpoints OK: 1
|
|
591
|
+
self.assertIn("Endpoints OK: 1 WARNING: 0 ERROR: 0\ncallback_status: OK - STATUS MSG", status.message)
|
|
592
592
|
|
|
593
593
|
def test_overall_status_warning_1(self):
|
|
594
594
|
def callback_ep_status():
|
|
@@ -620,7 +620,7 @@ class TestStatus(unittest.TestCase):
|
|
|
620
620
|
status = ext._build_current_status()
|
|
621
621
|
self.assertEqual(status.status, StatusValue.WARNING)
|
|
622
622
|
self.assertIn(
|
|
623
|
-
"Endpoints OK: 0
|
|
623
|
+
"Endpoints OK: 0 WARNING: 1 ERROR: 0 Unhealthy endpoints: EP_HINT - WARNING EP MSG\ncallback_multistatus: OK - MULTI MSG",
|
|
624
624
|
status.message,
|
|
625
625
|
)
|
|
626
626
|
|
|
@@ -654,8 +654,9 @@ class TestStatus(unittest.TestCase):
|
|
|
654
654
|
status = ext._build_current_status()
|
|
655
655
|
self.assertEqual(status.status, StatusValue.WARNING)
|
|
656
656
|
self.assertIn(
|
|
657
|
-
"Endpoints OK: 0
|
|
658
|
-
"\ncallback_multistatus: GENERIC_ERROR -
|
|
657
|
+
"Endpoints OK: 0 WARNING: 0 ERROR: 1 Unhealthy endpoints: EP_HINT - INVALID_CONFIG_ERROR "
|
|
658
|
+
"\ncallback_multistatus: GENERIC_ERROR - "
|
|
659
|
+
"\ncallback_status: WARNING - ",
|
|
659
660
|
status.message,
|
|
660
661
|
)
|
|
661
662
|
|
|
@@ -711,7 +712,7 @@ class TestStatus(unittest.TestCase):
|
|
|
711
712
|
self.assertEqual(status.status, StatusValue.GENERIC_ERROR)
|
|
712
713
|
self.assertIn(
|
|
713
714
|
(
|
|
714
|
-
"Endpoints OK: 0
|
|
715
|
+
"Endpoints OK: 0 WARNING: 0 ERROR: 2 Unhealthy endpoints: "
|
|
715
716
|
"skipped_callback - GENERIC_ERROR skipped_callback_msg, regular_callback - UNKNOWN_ERROR regular_callback_msg"
|
|
716
717
|
),
|
|
717
718
|
status.message,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-01-new-extension.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-04-import-remote.png
RENAMED
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/docs/_static/img/migrate-05-activation.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/__init__.py
RENAMED
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/cli/create/create.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/throttled_logger.py
RENAMED
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/vendor/__init__.py
RENAMED
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/vendor/mureq/LICENSE
RENAMED
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/vendor/mureq/__init__.py
RENAMED
|
File without changes
|
{dt_extensions_sdk-1.7.1 → dt_extensions_sdk-1.7.3}/dynatrace_extension/sdk/vendor/mureq/mureq.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|