Skip to content

Commit 713162e

Browse files
committed
Added status logger
1 parent e0f9cd6 commit 713162e

3 files changed

Lines changed: 325 additions & 0 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See License in the project root for
4+
# license information.
5+
# --------------------------------------------------------------------------
6+
7+
import socket
8+
from json import dumps
9+
from os import getpid, makedirs
10+
from os.path import exists, join
11+
12+
from azure.monitor.opentelemetry.distro._constants import (
13+
_CUSTOMER_IKEY,
14+
_EXTENSION_VERSION,
15+
_IS_DIAGNOSTICS_ENABLED,
16+
_get_log_path
17+
)
18+
from azure.monitor.opentelemetry.distro._version import VERSION
19+
20+
_MACHINE_NAME = socket.gethostname()
21+
_STATUS_LOG_PATH = _get_log_path(status_log_path=True)
22+
23+
24+
def _get_status_json(agent_initialized_successfully, pid, reason=None):
25+
status_json = {
26+
"AgentInitializedSuccessfully": agent_initialized_successfully,
27+
"AppType": "python",
28+
"MachineName": _MACHINE_NAME,
29+
"PID": pid,
30+
"SdkVersion": VERSION,
31+
"Ikey": _CUSTOMER_IKEY,
32+
"ExtensionVersion": _EXTENSION_VERSION,
33+
}
34+
if reason:
35+
status_json["Reason"] = reason
36+
return status_json
37+
38+
39+
def log_status(agent_initialized_successfully, reason=None):
40+
if _IS_DIAGNOSTICS_ENABLED and _STATUS_LOG_PATH :
41+
pid = getpid()
42+
status_json = _get_status_json(
43+
agent_initialized_successfully, pid, reason
44+
)
45+
if not exists(_STATUS_LOG_PATH):
46+
makedirs(_STATUS_LOG_PATH)
47+
# Change to be hostname and pid
48+
status_logger_file_name = f"status_{_MACHINE_NAME}_{pid}.json"
49+
with open(join(_STATUS_LOG_PATH, status_logger_file_name), "w") as f:
50+
f.seek(0)
51+
f.write(dumps(status_json))
52+
f.truncate()

azure-monitor-opentelemetry-distro/azure/monitor/opentelemetry/distro/distro.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
from azure.monitor.opentelemetry.distro._diagnostic_logging import (
1010
AzureDiagnosticLogging,
1111
)
12+
from azure.monitor.opentelemetry.distro._status_logger import (
13+
log_status,
14+
)
1215
from opentelemetry.environment_variables import (
1316
OTEL_METRICS_EXPORTER,
1417
OTEL_TRACES_EXPORTER,
@@ -34,6 +37,7 @@ def _configure(self, **kwargs) -> None:
3437

3538
def _configure_auto_instrumentation() -> None:
3639
try:
40+
log_status(False, "Distro being configured.")
3741
AzureDiagnosticLogging.enable(_logger)
3842
AzureDiagnosticLogging.enable(_opentelemetry_logger)
3943
# TODO: Enabled when duplicate logging issue is solved
@@ -51,10 +55,12 @@ def _configure_auto_instrumentation() -> None:
5155
environ.setdefault(
5256
OTEL_TRACES_EXPORTER, "azure_monitor_opentelemetry_exporter"
5357
)
58+
log_status(True)
5459
_logger.info(
5560
"Azure Monitor OpenTelemetry Distro configured successfully."
5661
)
5762
except Exception as exc:
63+
log_status(False, reason=exc)
5864
_logger.error(
5965
"Azure Monitor OpenTelemetry Distro failed during "
6066
+ f"configuration: {exc}"
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See License in the project root for
4+
# license information.
5+
# --------------------------------------------------------------------------
6+
7+
from json import loads
8+
from os.path import join
9+
from pathlib import Path
10+
from unittest import TestCase
11+
from unittest.mock import patch
12+
13+
from azure.monitor.opentelemetry.distro import status_logger
14+
15+
TEST_LOGGER_PATH = str(Path.home())
16+
TEST_MACHINE_NAME = "TEST_MACHINE_NAME"
17+
TEST_PID = 321
18+
TEST_STATUS_LOGGER_LOCATION = join(
19+
TEST_LOGGER_PATH, f"status_{TEST_MACHINE_NAME}_{TEST_PID}.json"
20+
)
21+
TEST_OPERATION = "TEST_OPERATION"
22+
TEST_OPERATION = "TEST_OPERATION"
23+
TEST_SITE_NAME = "TEST_SITE_NAME"
24+
TEST_CUSTOMER_IKEY = "TEST_CUSTOMER_IKEY"
25+
TEST_EXTENSION_VERSION = "TEST_EXTENSION_VERSION"
26+
TEST_VERSION = "TEST_VERSION"
27+
TEST_SUBSCRIPTION_ID = "TEST_SUBSCRIPTION_ID"
28+
MESSAGE1 = "MESSAGE1"
29+
MESSAGE2 = "MESSAGE2"
30+
31+
32+
def clear_file():
33+
with open(TEST_STATUS_LOGGER_LOCATION, "w") as f:
34+
f.seek(0)
35+
f.truncate()
36+
37+
38+
def check_file_for_messages(agent_initialized_successfully, reason=None):
39+
with open(TEST_STATUS_LOGGER_LOCATION, "r") as f:
40+
f.seek(0)
41+
json = loads(f.readline())
42+
assert (
43+
json["AgentInitializedSuccessfully"]
44+
== agent_initialized_successfully
45+
)
46+
assert json["AppType"] == "python"
47+
assert json["MachineName"] == TEST_MACHINE_NAME
48+
assert json["PID"] == TEST_PID
49+
assert json["SdkVersion"] == TEST_VERSION
50+
assert json["Ikey"] == TEST_CUSTOMER_IKEY
51+
assert json["ExtensionVersion"] == TEST_EXTENSION_VERSION
52+
if reason:
53+
assert json["Reason"] == reason
54+
else:
55+
assert "Reason" not in json
56+
assert not f.read()
57+
58+
59+
def check_file_is_empty():
60+
with open(TEST_STATUS_LOGGER_LOCATION, "r") as f:
61+
f.seek(0)
62+
assert not f.read()
63+
64+
65+
class TestStatusLogger(TestCase):
66+
def setUp(self) -> None:
67+
clear_file()
68+
69+
@patch(
70+
"azure.monitor.opentelemetry.distro.status_logger._STATUS_LOG_PATH",
71+
TEST_LOGGER_PATH,
72+
)
73+
@patch(
74+
"azure.monitor.opentelemetry.distro.status_logger._MACHINE_NAME",
75+
TEST_MACHINE_NAME,
76+
)
77+
@patch(
78+
"azure.monitor.opentelemetry.distro.status_logger._CUSTOMER_IKEY",
79+
TEST_CUSTOMER_IKEY,
80+
)
81+
@patch(
82+
"azure.monitor.opentelemetry.distro.status_logger._EXTENSION_VERSION",
83+
TEST_EXTENSION_VERSION,
84+
)
85+
@patch(
86+
"azure.monitor.opentelemetry.distro.status_logger.VERSION",
87+
TEST_VERSION,
88+
)
89+
@patch(
90+
"azure.monitor.opentelemetry.distro.status_logger._IS_ON_APP_SERVICE",
91+
True,
92+
)
93+
@patch(
94+
"azure.monitor.opentelemetry.distro.status_logger.getpid",
95+
return_value=TEST_PID,
96+
)
97+
def test_app_service_log_status_success(self, mock_getpid):
98+
status_logger.log_status(False, MESSAGE1)
99+
status_logger.log_status(True, MESSAGE2)
100+
check_file_for_messages(True, MESSAGE2)
101+
102+
@patch(
103+
"azure.monitor.opentelemetry.distro.status_logger._STATUS_LOG_PATH",
104+
TEST_LOGGER_PATH,
105+
)
106+
@patch(
107+
"azure.monitor.opentelemetry.distro.status_logger._MACHINE_NAME",
108+
TEST_MACHINE_NAME,
109+
)
110+
@patch(
111+
"azure.monitor.opentelemetry.distro.status_logger._CUSTOMER_IKEY",
112+
TEST_CUSTOMER_IKEY,
113+
)
114+
@patch(
115+
"azure.monitor.opentelemetry.distro.status_logger._EXTENSION_VERSION",
116+
TEST_EXTENSION_VERSION,
117+
)
118+
@patch(
119+
"azure.monitor.opentelemetry.distro.status_logger.VERSION",
120+
TEST_VERSION,
121+
)
122+
@patch(
123+
"azure.monitor.opentelemetry.distro.status_logger._IS_ON_APP_SERVICE",
124+
True,
125+
)
126+
@patch(
127+
"azure.monitor.opentelemetry.distro.status_logger.getpid",
128+
return_value=TEST_PID,
129+
)
130+
def test_app_service_log_status_failed_initialization(self, mock_getpid):
131+
status_logger.log_status(True, MESSAGE1)
132+
status_logger.log_status(False, MESSAGE2)
133+
check_file_for_messages(False, MESSAGE2)
134+
135+
@patch(
136+
"azure.monitor.opentelemetry.distro.status_logger._STATUS_LOG_PATH",
137+
TEST_LOGGER_PATH,
138+
)
139+
@patch(
140+
"azure.monitor.opentelemetry.distro.status_logger._MACHINE_NAME",
141+
TEST_MACHINE_NAME,
142+
)
143+
@patch(
144+
"azure.monitor.opentelemetry.distro.status_logger._CUSTOMER_IKEY",
145+
TEST_CUSTOMER_IKEY,
146+
)
147+
@patch(
148+
"azure.monitor.opentelemetry.distro.status_logger._EXTENSION_VERSION",
149+
TEST_EXTENSION_VERSION,
150+
)
151+
@patch(
152+
"azure.monitor.opentelemetry.distro.status_logger.VERSION",
153+
TEST_VERSION,
154+
)
155+
@patch(
156+
"azure.monitor.opentelemetry.distro.status_logger._IS_ON_APP_SERVICE",
157+
True,
158+
)
159+
@patch(
160+
"azure.monitor.opentelemetry.distro.status_logger.getpid",
161+
return_value=TEST_PID,
162+
)
163+
def test_app_service_log_status_no_reason(self, mock_getpid):
164+
status_logger.log_status(False, MESSAGE1)
165+
status_logger.log_status(True)
166+
check_file_for_messages(True)
167+
168+
@patch(
169+
"azure.monitor.opentelemetry.distro.status_logger._STATUS_LOG_PATH",
170+
TEST_LOGGER_PATH,
171+
)
172+
@patch(
173+
"azure.monitor.opentelemetry.distro.status_logger._MACHINE_NAME",
174+
TEST_MACHINE_NAME,
175+
)
176+
@patch(
177+
"azure.monitor.opentelemetry.distro.status_logger._CUSTOMER_IKEY",
178+
TEST_CUSTOMER_IKEY,
179+
)
180+
@patch(
181+
"azure.monitor.opentelemetry.distro.status_logger._EXTENSION_VERSION",
182+
TEST_EXTENSION_VERSION,
183+
)
184+
@patch(
185+
"azure.monitor.opentelemetry.distro.status_logger.VERSION",
186+
TEST_VERSION,
187+
)
188+
@patch(
189+
"azure.monitor.opentelemetry.distro.status_logger._IS_ON_APP_SERVICE",
190+
False,
191+
)
192+
@patch(
193+
"azure.monitor.opentelemetry.distro.status_logger.getpid",
194+
return_value=TEST_PID,
195+
)
196+
def test_off_app_service_log_status_success(self, mock_getpid):
197+
status_logger.log_status(False, MESSAGE1)
198+
status_logger.log_status(True, MESSAGE2)
199+
check_file_is_empty()
200+
201+
@patch(
202+
"azure.monitor.opentelemetry.distro.status_logger._STATUS_LOG_PATH",
203+
TEST_LOGGER_PATH,
204+
)
205+
@patch(
206+
"azure.monitor.opentelemetry.distro.status_logger._MACHINE_NAME",
207+
TEST_MACHINE_NAME,
208+
)
209+
@patch(
210+
"azure.monitor.opentelemetry.distro.status_logger._CUSTOMER_IKEY",
211+
TEST_CUSTOMER_IKEY,
212+
)
213+
@patch(
214+
"azure.monitor.opentelemetry.distro.status_logger._EXTENSION_VERSION",
215+
TEST_EXTENSION_VERSION,
216+
)
217+
@patch(
218+
"azure.monitor.opentelemetry.distro.status_logger.VERSION",
219+
TEST_VERSION,
220+
)
221+
@patch(
222+
"azure.monitor.opentelemetry.distro.status_logger._IS_ON_APP_SERVICE",
223+
False,
224+
)
225+
@patch(
226+
"azure.monitor.opentelemetry.distro.status_logger.getpid",
227+
return_value=TEST_PID,
228+
)
229+
def test_off_app_service_log_status_failed_initialization(
230+
self, mock_getpid
231+
):
232+
status_logger.log_status(True, MESSAGE1)
233+
status_logger.log_status(False, MESSAGE2)
234+
check_file_is_empty()
235+
236+
@patch(
237+
"azure.monitor.opentelemetry.distro.status_logger._STATUS_LOG_PATH",
238+
TEST_LOGGER_PATH,
239+
)
240+
@patch(
241+
"azure.monitor.opentelemetry.distro.status_logger._MACHINE_NAME",
242+
TEST_MACHINE_NAME,
243+
)
244+
@patch(
245+
"azure.monitor.opentelemetry.distro.status_logger._CUSTOMER_IKEY",
246+
TEST_CUSTOMER_IKEY,
247+
)
248+
@patch(
249+
"azure.monitor.opentelemetry.distro.status_logger._EXTENSION_VERSION",
250+
TEST_EXTENSION_VERSION,
251+
)
252+
@patch(
253+
"azure.monitor.opentelemetry.distro.status_logger.VERSION",
254+
TEST_VERSION,
255+
)
256+
@patch(
257+
"azure.monitor.opentelemetry.distro.status_logger._IS_ON_APP_SERVICE",
258+
False,
259+
)
260+
@patch(
261+
"azure.monitor.opentelemetry.distro.status_logger.getpid",
262+
return_value=TEST_PID,
263+
)
264+
def test_off_app_service_log_status_no_reason(self, mock_getpid):
265+
status_logger.log_status(False, MESSAGE1)
266+
status_logger.log_status(True)
267+
check_file_is_empty()

0 commit comments

Comments
 (0)