dt-extensions-sdk 1.1.14__tar.gz → 1.1.16__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.1.14 → dt_extensions_sdk-1.1.16}/PKG-INFO +1 -1
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/conf.py +1 -1
- dt_extensions_sdk-1.1.16/docs/guides/building.rst +129 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/guides/extension_structure.rst +2 -2
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/index.rst +1 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/__about__.py +1 -1
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/extension_template/extension/extension.yaml.template +3 -3
- dt_extensions_sdk-1.1.16/dynatrace_extension/cli/create/extension_template/setup.py.template +28 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/communication.py +64 -14
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/extension.py +16 -13
- dt_extensions_sdk-1.1.16/test.py +23 -0
- dt_extensions_sdk-1.1.16/test.txt +1 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/cli/test_types.py +3 -3
- dt_extensions_sdk-1.1.14/dynatrace_extension/cli/create/extension_template/setup.py.template +0 -12
- dt_extensions_sdk-1.1.14/extension.pkl +0 -0
- dt_extensions_sdk-1.1.14/test.py +0 -19
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/.github/workflows/gh-pages-docs.yml +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/.github/workflows/publish.yml +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/.gitignore +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/LICENSE.txt +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/README.md +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/dt-sdk-header.png +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/dt-sdk-logo.png +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/favicon.ico +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-01-new-extension.png +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-02-type.png +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-03-import.png +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-04-import-remote.png +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-05-activation.png +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-06-activation-config.png +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/api/events/event_severity.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/api/events/event_type.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/api/events/index.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/api/extension.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/api/metrics/index.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/api/metrics/metric.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/api/metrics/metric_type.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/assemble.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/build.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/create.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/gencerts.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/help.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/run.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/sign.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/upload.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/cli/wheel.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/guides/installation.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/guides/migration.rst +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/requirements.txt +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/create.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/extension_template/.gitignore.template +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/extension_template/README.md.template +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/extension_template/activation.json.template +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/extension_template/extension/activationSchema.json.template +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/extension_template/extension_name/__init__.py.template +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/extension_template/extension_name/__main__.py.template +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/main.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/schema.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/activation.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/callback.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/event.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/helper.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/metric.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/runtime.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/vendor/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/vendor/mureq/LICENSE +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/vendor/mureq/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/vendor/mureq/mureq.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/pyproject.toml +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/cli/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/cli/test_dt_sdk.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/cli/test_templates.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/sdk/__init__.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/sdk/test_activation.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/sdk/test_callback.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/sdk/test_communication.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/sdk/test_extension.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/sdk/test_metric.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/sdk/test_runtime_properties.py +0 -0
- {dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/tests/sdk/test_status.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: dt-extensions-sdk
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.16
|
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
|
@@ -88,7 +88,7 @@ html_theme_options = {
|
|
88
88
|
"logo": "dt-sdk-logo.png",
|
89
89
|
"logo_alt": "dt-sdk",
|
90
90
|
"logo_url": "/",
|
91
|
-
"github_url": "https://github.com/dynatrace-extensions/dt-extensions-python-sdk",
|
91
|
+
"github_url": "https://github.com/dynatrace-extensions/dt-extensions-python-sdk/tree/main/docs/",
|
92
92
|
"footer_links": ",".join(
|
93
93
|
[
|
94
94
|
"Dynatrace|https://dynatrace.com/",
|
@@ -0,0 +1,129 @@
|
|
1
|
+
Building Extensions
|
2
|
+
###################
|
3
|
+
|
4
|
+
| This guide provides some best practices on:
|
5
|
+
|
|
6
|
+
|
7
|
+
* Building extensions
|
8
|
+
* Python dependencies
|
9
|
+
* CI systems, offline installs
|
10
|
+
|
11
|
+
Native dependencies
|
12
|
+
===================
|
13
|
+
|
14
|
+
| Some python libraries require "native" dependencies, they are not written in pure python and usually contain C, C++, Rust or other compiled languages code.
|
15
|
+
| This means that they might be compiled for a very specific version of python, or for a specific operating system.
|
16
|
+
|
|
17
|
+
|
18
|
+
| Examples:
|
19
|
+
|
|
20
|
+
|
21
|
+
* **requests** requires **charset_normalizer**, a **native dependency**
|
22
|
+
|
23
|
+
|
24
|
+
| If you navigate to the `charset-normalizer pypi page`_ you will see dozens of different wheel files.
|
25
|
+
| Each one of these files is compiled for a different version of python, and for a different operating system.
|
26
|
+
|
|
27
|
+
| Your extension will run on a Dynatrace **Activegate** or **OneAgent**, which is a Linux or Windows machine, and it has a specific version of python.
|
28
|
+
| This means that your extension must be built on a machine that has the same version of python as the Activegate.
|
29
|
+
|
|
30
|
+
| At this time, Dynatrace extensions run on **python 3.10**.
|
31
|
+
|
|
32
|
+
| When you build the extension with **dt-sdk build**, it downloads the dependencies **whl** files and places them in the lib folder of the extension.
|
33
|
+
| To obtain whl files for different a operating system than what the build machine is, the SDK provides the **--extra-platform** flag.
|
34
|
+
|
|
35
|
+
| In summary, when building from Windows, you should use:
|
36
|
+
|
|
37
|
+
|
38
|
+
.. code-block:: bash
|
39
|
+
|
40
|
+
dt-sdk build --extra-platform manylinux2014_x86_64
|
41
|
+
|
42
|
+
|
43
|
+
| To get the correct extra wheel files for linux. Note, **manylinux2014_x86_64** works for several packages, but not all of them.
|
44
|
+
| You need to investigate the dependencies of your extension to find the correct extra platform if that is the case.
|
45
|
+
|
|
46
|
+
| When building from Linux, you should use:
|
47
|
+
|
|
48
|
+
|
49
|
+
|
50
|
+
.. code-block:: bash
|
51
|
+
|
52
|
+
dt-sdk build --extra-platform win_amd64
|
53
|
+
|
54
|
+
|
55
|
+
| To get the correct extra wheel files for Windows.
|
56
|
+
|
|
57
|
+
|
58
|
+
PyPI Access
|
59
|
+
===========
|
60
|
+
|
61
|
+
| When building extensions, the SDK downloads the dependencies from PyPI.
|
62
|
+
|
|
63
|
+
| In some organizations, you are not allowed to access the internet from the build machine.
|
64
|
+
| In most cases you will have either:
|
65
|
+
|
|
66
|
+
|
67
|
+
* A local PyPI mirror
|
68
|
+
* A directory with all the wheel files present
|
69
|
+
|
70
|
+
|
|
71
|
+
| Both of these solutions can be used with the SDK.
|
72
|
+
|
|
73
|
+
|
74
|
+
PyPI Mirror
|
75
|
+
"""""""""""
|
76
|
+
|
77
|
+
| Suppose you have a local PyPi server running on http://my-pypi-server:8080.
|
78
|
+
|
|
79
|
+
| To use it with the SDK, run the build command as:
|
80
|
+
|
|
81
|
+
|
82
|
+
.. code-block:: bash
|
83
|
+
|
84
|
+
PIP_INDEX_URL=http://my-pypi-server:8080/simple PIP_TRUSTED_HOST=my-pypi-server dt-sdk build
|
85
|
+
|
86
|
+
|
87
|
+
| This will tell the SDK to use the local PyPI server to download the dependencies.
|
88
|
+
| The SDK uses **pip** under the covers, so all the environment variables that **pip** supports can be used with the SDK.
|
89
|
+
|
|
90
|
+
| Note, that assumes the build machine is a linux machine. If you are building from Windows on Powershell, you can use:
|
91
|
+
|
|
92
|
+
|
93
|
+
.. code-block:: bash
|
94
|
+
|
95
|
+
$ENV:PIP_INDEX_URL="http://my-pypi-server:8080/simple"; $ENV:PIP_TRUSTED_HOST="my-pypi-server"; dt-sdk build
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
Local Directory
|
102
|
+
"""""""""""""""
|
103
|
+
|
104
|
+
|
105
|
+
| Another option is to manually download the different whl files you need, and place them in a directory on the build machine.
|
106
|
+
| In that case, that directory can be used as the source for the dependencies.
|
107
|
+
|
|
108
|
+
|
109
|
+
.. code-block:: bash
|
110
|
+
|
111
|
+
dt-sdk build --find-links /path/to/whl/files
|
112
|
+
|
113
|
+
|
114
|
+
| This will tell the SDK to use the directory as the source for the dependencies.
|
115
|
+
|
|
116
|
+
|
117
|
+
Musl vs libc
|
118
|
+
============
|
119
|
+
|
120
|
+
| Extensions run on `libc`_ based systems, like Ubuntu, CentOS, Windows, etc.
|
121
|
+
| You should not use a `musl`_ based system, like Alpine, to build extensions.
|
122
|
+
|
|
123
|
+
| This means that if you are using a docker container to build the extension, you should use the **python:3.10** image, or any other image that is based on a `libc`_ system.
|
124
|
+
|
|
125
|
+
| The reason for this is that a **musl** based system will download native whl files that are not compatible with **libc** based systems.
|
126
|
+
|
127
|
+
.. _charset-normalizer pypi page: https://pypi.org/project/charset-normalizer/#files
|
128
|
+
.. _musl: https://musl.libc.org/
|
129
|
+
.. _libc: https://en.wikipedia.org/wiki/C_standard_library
|
@@ -33,7 +33,7 @@ Here is what a sample extension definition looks like:
|
|
33
33
|
|
34
34
|
name: custom:my-extension
|
35
35
|
version: 0.0.1
|
36
|
-
minDynatraceVersion: "1.
|
36
|
+
minDynatraceVersion: "1.285"
|
37
37
|
author:
|
38
38
|
name: "Dynatrace"
|
39
39
|
|
@@ -41,7 +41,7 @@ Here is what a sample extension definition looks like:
|
|
41
41
|
runtime:
|
42
42
|
module: my_extension
|
43
43
|
version:
|
44
|
-
min: "3.
|
44
|
+
min: "3.10"
|
45
45
|
|
46
46
|
activation:
|
47
47
|
remote:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
name: %extension-prefix%%extension-name%
|
2
2
|
version: 0.0.1
|
3
|
-
minDynatraceVersion: "1.
|
3
|
+
minDynatraceVersion: "1.285"
|
4
4
|
author:
|
5
5
|
name: "Dynatrace"
|
6
6
|
|
@@ -8,10 +8,10 @@ python:
|
|
8
8
|
runtime:
|
9
9
|
module: %extension_name%
|
10
10
|
version:
|
11
|
-
min: "3.
|
11
|
+
min: "3.10"
|
12
12
|
|
13
13
|
activation:
|
14
14
|
remote:
|
15
15
|
path: activationSchema.json
|
16
16
|
local:
|
17
|
-
path: activationSchema.json
|
17
|
+
path: activationSchema.json
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from setuptools import setup, find_packages
|
3
|
+
|
4
|
+
|
5
|
+
def find_version() -> str:
|
6
|
+
version = "0.0.1"
|
7
|
+
extension_yaml_path = Path(__file__).parent / "extension" / "extension.yaml"
|
8
|
+
try:
|
9
|
+
with open(extension_yaml_path, encoding="utf-8") as f:
|
10
|
+
for line in f:
|
11
|
+
if line.startswith("version"):
|
12
|
+
version = line.split(" ")[-1].strip("\"")
|
13
|
+
break
|
14
|
+
except Exception:
|
15
|
+
pass
|
16
|
+
return version
|
17
|
+
|
18
|
+
|
19
|
+
setup(name="%extension_name%",
|
20
|
+
version=find_version(),
|
21
|
+
description="%Extension_Name% python EF2 extension",
|
22
|
+
author="Dynatrace",
|
23
|
+
packages=find_packages(),
|
24
|
+
python_requires=">=3.10",
|
25
|
+
include_package_data=True,
|
26
|
+
install_requires=["dt-extensions-sdk"],
|
27
|
+
extras_require={"dev": ["dt-extensions-sdk[cli]"]},
|
28
|
+
)
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/communication.py
RENAMED
@@ -10,11 +10,12 @@ import random
|
|
10
10
|
import sys
|
11
11
|
import time
|
12
12
|
from abc import ABC, abstractmethod
|
13
|
+
from collections import deque
|
13
14
|
from dataclasses import dataclass
|
14
15
|
from enum import Enum
|
15
16
|
from itertools import islice
|
16
17
|
from pathlib import Path
|
17
|
-
from typing import Any, Iterable, List, TypeVar
|
18
|
+
from typing import Any, Dict, Iterable, List, TypeVar, Union
|
18
19
|
|
19
20
|
from .vendor.mureq.mureq import HTTPException, Response, request
|
20
21
|
|
@@ -22,6 +23,8 @@ CONTENT_TYPE_JSON = "application/json;charset=utf-8"
|
|
22
23
|
CONTENT_TYPE_PLAIN = "text/plain;charset=utf-8"
|
23
24
|
COUNT_METRIC_ITEMS_DICT = TypeVar("COUNT_METRIC_ITEMS_DICT", str, List[str])
|
24
25
|
MAX_MINT_LINES_PER_REQUEST = 1000
|
26
|
+
MAX_LOG_EVENTS_PER_REQUEST = 50_000
|
27
|
+
MAX_LOG_REQUEST_SIZE = 5_000_000
|
25
28
|
HTTP_BAD_REQUEST = 400
|
26
29
|
|
27
30
|
|
@@ -94,7 +97,7 @@ class CommunicationClient(ABC):
|
|
94
97
|
pass
|
95
98
|
|
96
99
|
@abstractmethod
|
97
|
-
def send_events(self, event: dict | list[dict], eec_enrichment: bool) -> dict | None:
|
100
|
+
def send_events(self, event: dict | list[dict], eec_enrichment: bool) -> list[Union[dict | None]]:
|
98
101
|
pass
|
99
102
|
|
100
103
|
@abstractmethod
|
@@ -283,19 +286,26 @@ class HttpClient(CommunicationClient):
|
|
283
286
|
responses.append(mint_response)
|
284
287
|
return responses
|
285
288
|
|
286
|
-
def send_events(self, events: dict | list[dict], eec_enrichment: bool = True) -> dict | None:
|
289
|
+
def send_events(self, events: dict | list[dict], eec_enrichment: bool = True) -> list[dict | None]:
|
287
290
|
self.logger.debug(f"Sending log events: {events}")
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
291
|
+
|
292
|
+
responses = []
|
293
|
+
batches = divide_logs_into_batches([events] if isinstance(events, dict) else events)
|
294
|
+
|
295
|
+
for batch in batches:
|
296
|
+
try:
|
297
|
+
encoded_batch = json.dumps(batch).encode("utf-8")
|
298
|
+
eec_response = self._make_request(
|
299
|
+
self._events_url,
|
300
|
+
"POST",
|
301
|
+
encoded_batch,
|
302
|
+
extra_headers={"Content-Type": CONTENT_TYPE_JSON, "eec-enrichment": str(eec_enrichment).lower()},
|
303
|
+
).json()
|
304
|
+
responses.append(eec_response)
|
305
|
+
except json.JSONDecodeError:
|
306
|
+
responses.append(None)
|
307
|
+
|
308
|
+
return responses
|
299
309
|
|
300
310
|
def send_sfm_metrics(self, mint_lines: list[str]) -> MintResponse:
|
301
311
|
mint_data = "\n".join(mint_lines).encode("utf-8")
|
@@ -448,6 +458,46 @@ def divide_into_chunks(iterable: Iterable, chunk_size: int) -> Iterable:
|
|
448
458
|
return
|
449
459
|
yield subset
|
450
460
|
|
461
|
+
def divide_logs_into_batches(logs: list[dict]):
|
462
|
+
"""
|
463
|
+
Yield successive batches from a list of log events, according to sizing limitations
|
464
|
+
imposed by the EEC: 5 MB payload, 50,000 events
|
465
|
+
|
466
|
+
:param logs: The list of log events
|
467
|
+
"""
|
468
|
+
events_left = len(logs)
|
469
|
+
events = deque(logs)
|
470
|
+
|
471
|
+
batch = []
|
472
|
+
batch_size = 0
|
473
|
+
batch_items = 0
|
474
|
+
|
475
|
+
while events_left > 0:
|
476
|
+
if batch_items == MAX_LOG_EVENTS_PER_REQUEST:
|
477
|
+
yield batch
|
478
|
+
batch = []
|
479
|
+
batch_size = 0
|
480
|
+
batch_items = 0
|
481
|
+
continue
|
482
|
+
|
483
|
+
event = events.popleft()
|
484
|
+
events_left -= 1
|
485
|
+
|
486
|
+
if event is not None:
|
487
|
+
event = json.dumps(event).encode("utf-8")
|
488
|
+
event_size = len(event)
|
489
|
+
|
490
|
+
if batch_size + event_size >= MAX_LOG_REQUEST_SIZE:
|
491
|
+
yield batch
|
492
|
+
batch = [event]
|
493
|
+
batch_size = event_size
|
494
|
+
batch_items = 1
|
495
|
+
else:
|
496
|
+
batch.append(event)
|
497
|
+
batch_size += event_size
|
498
|
+
batch_items += 1
|
499
|
+
else:
|
500
|
+
yield batch
|
451
501
|
|
452
502
|
@dataclass
|
453
503
|
class MintResponse:
|
@@ -9,6 +9,7 @@ import sys
|
|
9
9
|
import threading
|
10
10
|
import time
|
11
11
|
from argparse import ArgumentParser
|
12
|
+
from collections import deque
|
12
13
|
from concurrent.futures import ThreadPoolExecutor
|
13
14
|
from datetime import datetime, timedelta, timezone
|
14
15
|
from enum import Enum
|
@@ -79,14 +80,15 @@ class DtEventType(str, Enum):
|
|
79
80
|
https://docs.dynatrace.com/docs/dynatrace-api/environment-api/events-v2/post-event
|
80
81
|
"""
|
81
82
|
|
83
|
+
AVAILABILITY_EVENT = "AVAILABILITY_EVENT"
|
82
84
|
CUSTOM_INFO = "CUSTOM_INFO"
|
83
85
|
CUSTOM_ALERT = "CUSTOM_ALERT"
|
84
86
|
CUSTOM_ANNOTATION = "CUSTOM_ANNOTATION"
|
85
87
|
CUSTOM_CONFIGURATION = "CUSTOM_CONFIGURATION"
|
86
88
|
CUSTOM_DEPLOYMENT = "CUSTOM_DEPLOYMENT"
|
87
|
-
MARKED_FOR_TERMINATION = "MARKED_FOR_TERMINATION"
|
88
89
|
ERROR_EVENT = "ERROR_EVENT"
|
89
|
-
|
90
|
+
MARKED_FOR_TERMINATION = "MARKED_FOR_TERMINATION"
|
91
|
+
PERFORMANCE_EVENT = "PERFORMANCE_EVENT"
|
90
92
|
RESOURCE_CONTENTION_EVENT = "RESOURCE_CONTENTION_EVENT"
|
91
93
|
|
92
94
|
|
@@ -995,14 +997,16 @@ class Extension:
|
|
995
997
|
self._metrics.extend(lines)
|
996
998
|
|
997
999
|
def _send_events_internal(self, events: Union[dict, List[dict]]):
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1000
|
+
responses = self._client.send_events(events, self.log_event_enrichment)
|
1001
|
+
|
1002
|
+
for response in responses:
|
1003
|
+
with self._internal_callbacks_results_lock:
|
1004
|
+
self._internal_callbacks_results[self._send_events.__name__] = Status(StatusValue.OK)
|
1005
|
+
if not response or "error" not in response or "message" not in response["error"]:
|
1006
|
+
return
|
1007
|
+
self._internal_callbacks_results[self._send_events.__name__] = Status(
|
1008
|
+
StatusValue.GENERIC_ERROR, response["error"]["message"]
|
1009
|
+
)
|
1006
1010
|
|
1007
1011
|
def _send_events(self, events: Union[dict, List[dict]]):
|
1008
1012
|
self._internal_executor.submit(self._send_events_internal, events)
|
@@ -1011,9 +1015,8 @@ class Extension:
|
|
1011
1015
|
self._client.send_dt_event(event)
|
1012
1016
|
|
1013
1017
|
def get_version(self) -> str:
|
1014
|
-
"""Return the version
|
1015
|
-
|
1016
|
-
return __version__
|
1018
|
+
"""Return the extension version."""
|
1019
|
+
return self.activation_config.version
|
1017
1020
|
|
1018
1021
|
@property
|
1019
1022
|
def techrule(self) -> str:
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import os
|
2
|
+
import time
|
3
|
+
from concurrent.futures import ProcessPoolExecutor
|
4
|
+
|
5
|
+
from dynatrace_extension import Extension
|
6
|
+
|
7
|
+
|
8
|
+
class Mass(Extension):
|
9
|
+
def initialize(self):
|
10
|
+
with ProcessPoolExecutor(max_workers=4) as metric_executor:
|
11
|
+
f = metric_executor.submit(self.thing)
|
12
|
+
print(f.result())
|
13
|
+
|
14
|
+
@staticmethod
|
15
|
+
def thing():
|
16
|
+
time.sleep(5)
|
17
|
+
current_pid = os.getpid()
|
18
|
+
with open(r"D:\workspace\repos\github\dt-extensions-python-sdk\test.txt", "w") as f:
|
19
|
+
f.write(f"Hello, world! {current_pid}")
|
20
|
+
|
21
|
+
if __name__ == "__main__":
|
22
|
+
m = Mass()
|
23
|
+
m.run()
|
@@ -0,0 +1 @@
|
|
1
|
+
Hello, world! 21160
|
@@ -8,7 +8,7 @@ from dynatrace_extension.cli.schema import ExtensionYaml
|
|
8
8
|
VALID_YAML = """
|
9
9
|
name: custom:mulesoft-cloudhub
|
10
10
|
version: 0.0.1
|
11
|
-
minDynatraceVersion: "1.
|
11
|
+
minDynatraceVersion: "1.285"
|
12
12
|
author:
|
13
13
|
name: "Dynatrace"
|
14
14
|
|
@@ -16,7 +16,7 @@ python:
|
|
16
16
|
runtime:
|
17
17
|
module: mulesoft_cloudhub
|
18
18
|
version:
|
19
|
-
min: "3.
|
19
|
+
min: "3.10"
|
20
20
|
|
21
21
|
activation:
|
22
22
|
remote:
|
@@ -38,7 +38,7 @@ class TestTypes(TestCase):
|
|
38
38
|
assert extension.min_dynatrace_version == "1.902"
|
39
39
|
assert extension.author.name == "Dynatrace"
|
40
40
|
assert extension.python.runtime.module == "mulesoft_cloudhub"
|
41
|
-
assert extension.python.runtime.version.min_version == "3.
|
41
|
+
assert extension.python.runtime.version.min_version == "3.10"
|
42
42
|
assert extension.python.activation.remote.path == "activationSchema.json"
|
43
43
|
assert extension.python.activation.local is None
|
44
44
|
|
dt_extensions_sdk-1.1.14/dynatrace_extension/cli/create/extension_template/setup.py.template
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
from setuptools import setup, find_packages
|
2
|
-
|
3
|
-
setup(name="%extension_name%",
|
4
|
-
version="0.0.1",
|
5
|
-
description="%Extension_Name% python EF2 extension",
|
6
|
-
author="Dynatrace",
|
7
|
-
packages=find_packages(),
|
8
|
-
python_requires=">=3.10",
|
9
|
-
include_package_data=True,
|
10
|
-
install_requires=["dt-extensions-sdk"],
|
11
|
-
extras_require={"dev": ["dt-extensions-sdk[cli]"]},
|
12
|
-
)
|
File without changes
|
dt_extensions_sdk-1.1.14/test.py
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
import time
|
2
|
-
from concurrent.futures import ProcessPoolExecutor
|
3
|
-
from datetime import timedelta
|
4
|
-
|
5
|
-
from dynatrace_extension import Extension
|
6
|
-
from dynatrace_extension.sdk.callback import WrappedCallback
|
7
|
-
|
8
|
-
|
9
|
-
class Mass(Extension):
|
10
|
-
def initialize(self):
|
11
|
-
with ProcessPoolExecutor(max_workers=4) as metric_executor:
|
12
|
-
metric_executor.submit(self.thing)
|
13
|
-
|
14
|
-
def thing(self):
|
15
|
-
print("EITA PORRA")
|
16
|
-
|
17
|
-
if __name__ == "__main__":
|
18
|
-
m = Mass()
|
19
|
-
m.run()
|
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.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-01-new-extension.png
RENAMED
File without changes
|
File without changes
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-03-import.png
RENAMED
File without changes
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/docs/_static/img/migrate-04-import-remote.png
RENAMED
File without changes
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/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
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/cli/create/__init__.py
RENAMED
File without changes
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/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
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/vendor/__init__.py
RENAMED
File without changes
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/dynatrace_extension/sdk/vendor/mureq/LICENSE
RENAMED
File without changes
|
File without changes
|
{dt_extensions_sdk-1.1.14 → dt_extensions_sdk-1.1.16}/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
|