Skip to content
This repository has been archived by the owner on Sep 3, 2024. It is now read-only.

Third party timeouts #103

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ad981e3
Ping extension improvements
dlopes7 Nov 9, 2022
7f8d04c
Port extension improvements
dlopes7 Nov 9, 2022
84dfa81
Ping - validate hostname
dlopes7 Jan 25, 2023
3e26ae0
Ping - validate hostname
dlopes7 Jan 25, 2023
111a724
Merge remote-tracking branch 'origin/master'
dlopes7 Jan 25, 2023
478b19d
Port - validate hostname
dlopes7 Jan 26, 2023
9bc6f3c
Recompile with lower charset-normalizer version for compatibility
dlopes7 Jan 26, 2023
281b679
timeout on report call for ping
Dynatrace-James-Kitson Mar 6, 2023
ef59364
charset normalizer pinned for ping
Dynatrace-James-Kitson Mar 7, 2023
e01c6ea
timeout on reporting call
Dynatrace-James-Kitson Mar 7, 2023
aadac5b
timouts, consistency changes
Dynatrace-James-Kitson Mar 7, 2023
70da29d
timeouts for reporting call
Dynatrace-James-Kitson Mar 7, 2023
1015382
fix which logger has level set from config
Dynatrace-James-Kitson Apr 18, 2023
fa948db
Timeout is always set to 2 even if incorrectly set to 0
dlopes7 Apr 21, 2023
eb54524
merges dlopes changes
Dynatrace-James-Kitson Apr 24, 2023
772d08c
update and build v1.021
Dynatrace-James-Kitson Apr 24, 2023
806c808
update and build v1.021
Dynatrace-James-Kitson Apr 24, 2023
cb4563d
update and build v1.021
Dynatrace-James-Kitson Apr 24, 2023
2a5d8db
update and build v.1.021
Dynatrace-James-Kitson Apr 24, 2023
95ea553
update and build v.1.021
Dynatrace-James-Kitson Apr 24, 2023
b6301d9
fix logging
Dynatrace-James-Kitson Apr 25, 2023
984cfe5
fix logging
Dynatrace-James-Kitson Apr 25, 2023
dd976bb
Merge branch 'third-party-timeouts' of https://github.com/Dynatrace-J…
Dynatrace-James-Kitson Apr 25, 2023
2903720
ensure proper build
Dynatrace-James-Kitson Apr 25, 2023
ebd3d46
rename sftp to match supported version
Dynatrace-James-Kitson Apr 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# IntelliJ IDE files
.idea/
*.iml
*.iml
__pycache__
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
from dynatrace import Dynatrace
from dynatrace.environment_v1.synthetic_third_party import SYNTHETIC_EVENT_TYPE_OUTAGE

from dns_imports.environment import get_api_url

log = logging.getLogger(__name__)

DT_TIMEOUT_SECONDS = 10

class DNSExtension(RemoteBasePlugin):
def initialize(self, **kwargs):
# The Dynatrace API client
self.dt_client = Dynatrace(self.config.get("api_url"), self.config.get("api_token"), log=log, proxies=self.build_proxy_url())
self.api_url = get_api_url()
self.dt_client = Dynatrace(self.api_url, self.config.get("api_token"), log=log, proxies=self.build_proxy_url(), timeout=DT_TIMEOUT_SECONDS)
self.executions = 0
self.failures_detected = 0

Expand Down Expand Up @@ -59,31 +63,34 @@ def query(self, **kwargs) -> None:
else:
self.failures_detected = 0

self.dt_client.third_part_synthetic_tests.report_simple_thirdparty_synthetic_test(
engine_name="DNS",
timestamp=datetime.now(),
location_id=location_id,
location_name=location,
test_id=self.activation.entity_id,
test_title=test_title,
step_title=step_title,
schedule_interval=frequency * 60,
success=success,
response_time=response_time,
edit_link=f"#settings/customextension;id={self.plugin_info.name}",
icon_url="https://raw.githubusercontent.com/Dynatrace/dynatrace-api/master/third-party-synthetic/active-gate-extensions/extension-third-party-dns/dns.png",
)

self.dt_client.third_part_synthetic_tests.report_simple_thirdparty_synthetic_test_event(
test_id=self.activation.entity_id,
name=f"DNS lookup failed for {step_title}",
location_id=location_id,
timestamp=datetime.now(),
state="open" if not success else "resolved",
event_type=SYNTHETIC_EVENT_TYPE_OUTAGE,
reason=f"DNS lookup failed for {step_title}",
engine_name="DNS",
)
try:
self.dt_client.third_part_synthetic_tests.report_simple_thirdparty_synthetic_test(
engine_name="DNS",
timestamp=datetime.now(),
location_id=location_id,
location_name=location,
test_id=self.activation.entity_id,
test_title=test_title,
step_title=step_title,
schedule_interval=frequency * 60,
success=success,
response_time=response_time,
edit_link=f"#settings/customextension;id={self.plugin_info.name}",
icon_url="https://raw.githubusercontent.com/Dynatrace/dynatrace-api/master/third-party-synthetic/active-gate-extensions/extension-third-party-dns/dns.png",
)

self.dt_client.third_part_synthetic_tests.report_simple_thirdparty_synthetic_test_event(
test_id=self.activation.entity_id,
name=f"DNS lookup failed for {step_title}",
location_id=location_id,
timestamp=datetime.now(),
state="open" if not success else "resolved",
event_type=SYNTHETIC_EVENT_TYPE_OUTAGE,
reason=f"DNS lookup failed for {step_title}",
engine_name="DNS",
)
except Exception as e:
self.logger.error(f"Error reporting third party test results to {self.api_url}: '{e}'")

self.executions += 1

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import os
import re
from pathlib import Path
import logging

log = logging.getLogger(__name__)

tenant_regex = re.compile(r"\[(.*)\]")


def get_api_url() -> str:
endpoint = ""
environment = ""

base_path = Path(__file__)

# Only true if running from simulator
if "remotepluginmodule" not in str(base_path):
base_path = "/opt" if os.name != "nt" else "C:/Program Files"
base_path = Path(base_path) / "dynatrace" / "remotepluginmodule" / "agent"

# Go up one level until the directory name is remotepluginmodule
while True:
base_path = base_path.parent
if base_path.name == "remotepluginmodule":
extensions_conf = base_path / "agent" / "conf" / "extensions.conf"
with open(extensions_conf, "r", errors="replace") as f:
for line in f:
if line.startswith("Server "):
endpoint = line.split(" ")[1].strip()
endpoint = endpoint.replace("/communication", "")
if line.startswith("Tenant "):
environment = line.split(" ")[1].strip()
if endpoint and environment:
api_url = f"{endpoint}/e/{environment}"
log.info(f"Found API URL: '{api_url}' in '{extensions_conf}'")
return api_url
else:
raise Exception(f"Could not find API URL after reading {extensions_conf}")
# End of the line
if base_path.parent == base_path:
raise Exception("Could not find config directory")
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "custom.remote.python.thirdparty_dns",
"version": "1.015",
"version": "1.020",
"type": "python",
"entity": "CUSTOM_DEVICE",
"technologies": [
Expand All @@ -12,15 +12,12 @@
"className": "DNSExtension",
"install_requires": [
"dnspython3",
"dt"
"dt>=1.1.58",
"charset-normalizer<3"
],
"activation": "Remote"
},
"properties": [
{
"key": "api_url",
"type": "String"
},
{
"key": "api_token",
"type": "Password"
Expand Down Expand Up @@ -75,70 +72,64 @@
"configUI": {
"displayName": "DNS",
"properties": [
{
"key": "api_url",
"displayName": "Tenant URL",
"displayHint": "https://localhost:9999/e/<environment_id> or https://<my.managed.host>/e/<environment_id> or https://<environment_id>.live.dynatrace.com",
"displayOrder": 1
},
{
"key": "api_token",
"displayName": "API Token",
"displayHint": "Requires \"Create and read synthetic monitors, locations, and nodes\" permission",
"displayOrder": 2
"displayOrder": 20
},
{
"key": "test_name",
"displayName": "(Optional) Synthetic monitor name",
"displayOrder": 5
"displayOrder": 30
},
{
"key": "dns_server",
"displayName": "DNS server",
"displayHint": "IP address or hostname",
"displayOrder": 3
"displayOrder": 40
},
{
"key": "host",
"displayName": "Test target host",
"displayOrder": 4
"displayOrder": 50
},
{
"key": "frequency",
"displayName": "(Optional) Frequency",
"displayHint": "Frequency in minutes, default: 15",
"displayOrder": 6
"displayOrder": 60
},
{
"key": "test_location",
"displayName": "(Optional) Location name",
"displayHint": "Default: ActiveGate",
"displayOrder": 7
"displayOrder": 70
},
{
"key": "proxy_address",
"displayName": "(Optional) Proxy Address",
"displayOrder": 8
"displayOrder": 80
},
{
"key": "proxy_username",
"displayName": "(Optional) Proxy Username",
"displayOrder": 9
"displayOrder": 90
},
{
"key": "proxy_password",
"displayName": "(Optional) Proxy Password",
"displayOrder": 10
"displayOrder": 100
},
{
"key": "log_level",
"displayName": "Log level",
"displayOrder": 11
"displayOrder": 110
},
{
"key": "failure_count",
"displayName": "Failure count",
"displayOrder": 12,
"displayOrder": 120,
"displayHint": "Number of consecutive failures before reporting error"
}
]
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import os
import re
from pathlib import Path
import logging

log = logging.getLogger(__name__)

tenant_regex = re.compile(r"\[(.*)\]")


def get_api_url() -> str:
endpoint = ""
environment = ""

base_path = Path(__file__)

# Only true if running from simulator
if "remotepluginmodule" not in str(base_path):
base_path = "/opt" if os.name != "nt" else "C:/Program Files"
base_path = Path(base_path) / "dynatrace" / "remotepluginmodule" / "agent"

# Go up one level until the directory name is remotepluginmodule
while True:
base_path = base_path.parent
if base_path.name == "remotepluginmodule":
extensions_conf = base_path / "agent" / "conf" / "extensions.conf"
with open(extensions_conf, "r", errors="replace") as f:
for line in f:
if line.startswith("Server "):
endpoint = line.split(" ")[1].strip()
endpoint = endpoint.replace("/communication", "")
if line.startswith("Tenant "):
environment = line.split(" ")[1].strip()
if endpoint and environment:
api_url = f"{endpoint}/e/{environment}"
log.info(f"Found API URL: '{api_url}' in '{extensions_conf}'")
return api_url
else:
raise Exception(f"Could not find API URL after reading {extensions_conf}")
# End of the line
if base_path.parent == base_path:
raise Exception("Could not find config directory")
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
from dynatrace import Dynatrace
from dynatrace.environment_v1.synthetic_third_party import SYNTHETIC_EVENT_TYPE_OUTAGE

from commands_imports.environment import get_api_url

log = logging.getLogger(__name__)
DT_TIMEOUT_SECONDS = 10
ENGINE_NAME = "SSH"

log = logging.getLogger(__name__)

class LinuxCommandsExtension(RemoteBasePlugin):
def initialize(self, **kwargs):
self.dt_client = Dynatrace(self.config.get("api_url"), self.config.get("api_token"), log=log, proxies=self.build_proxy_url())
self.api_url = get_api_url()
self.dt_client = Dynatrace(self.api_url, self.config.get("api_token"), log=log, proxies=self.build_proxy_url(), timeout=DT_TIMEOUT_SECONDS)
self.executions = 0
self.failures_detected = 0

Expand Down Expand Up @@ -89,30 +92,33 @@ def query(self, **kwargs):
else:
self.failures_detected = 0

self.dt_client.third_part_synthetic_tests.report_simple_thirdparty_synthetic_test(
engine_name=ENGINE_NAME,
timestamp=datetime.now(),
location_id=location_id,
location_name=location,
test_id=self.activation.entity_id,
test_title=test_title,
step_title=step_title,
schedule_interval=frequency * 60,
success=success,
response_time=response_time,
edit_link=f"#settings/customextension;id={self.plugin_info.name}",
icon_url="https://raw.githubusercontent.com/Dynatrace/dynatrace-api/master/third-party-synthetic/active-gate-extensions/extension-third-party-linux-commands/linux_commands.png"
)
try:
self.dt_client.third_part_synthetic_tests.report_simple_thirdparty_synthetic_test(
engine_name=ENGINE_NAME,
timestamp=datetime.now(),
location_id=location_id,
location_name=location,
test_id=self.activation.entity_id,
test_title=test_title,
step_title=step_title,
schedule_interval=frequency * 60,
success=success,
response_time=response_time,
edit_link=f"#settings/customextension;id={self.plugin_info.name}",
icon_url="https://raw.githubusercontent.com/Dynatrace/dynatrace-api/master/third-party-synthetic/active-gate-extensions/extension-third-party-linux-commands/linux_commands.png"
)

self.dt_client.third_part_synthetic_tests.report_simple_thirdparty_synthetic_test_event(
test_id=self.activation.entity_id,
name=f"Command execution failed for {step_title}",
location_id=location_id,
timestamp=datetime.now(),
state="open" if not success else "resolved",
event_type=SYNTHETIC_EVENT_TYPE_OUTAGE,
reason=reason,
engine_name=ENGINE_NAME,
)
self.dt_client.third_part_synthetic_tests.report_simple_thirdparty_synthetic_test_event(
test_id=self.activation.entity_id,
name=f"Command execution failed for {step_title}",
location_id=location_id,
timestamp=datetime.now(),
state="open" if not success else "resolved",
event_type=SYNTHETIC_EVENT_TYPE_OUTAGE,
reason=reason,
engine_name=ENGINE_NAME,
)
except Exception as e:
self.logger.error(f"Error reporting third party test results to {self.api_url}: '{e}'")

self.executions += 1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "custom.remote.python.thirdparty_linux_commands",
"version": "1.018",
"version": "1.020",
"type": "python",
"entity": "CUSTOM_DEVICE",
"technologies": [
Expand All @@ -12,15 +12,13 @@
"className": "LinuxCommandsExtension",
"install_requires": [
"paramiko",
"dt"
"dt>=1.1.58",
"charset-normalizer<3",
"cryptography<=37.0.4"
]
},
"activation": "Remote",
"properties": [
{
"key": "api_url",
"type": "String"
},
{
"key": "api_token",
"type": "Password"
Expand Down Expand Up @@ -143,12 +141,6 @@
"displayHint": "Custom test name. Defaults to \"<hostname> (<command>)\"",
"displayOrder": 1
},
{
"key": "api_url",
"displayName": "Dynatrace tenant URL",
"displayHint": "https://localhost:9999/e/<environment_id> or https://<my.managed.host>/e/<environment_id> or https://<environment_id>.live.dynatrace.com",
"displayOrder": 2
},
{
"key": "api_token",
"displayName": "Dynatrace API Token",
Expand Down
Binary file not shown.
Loading