Skip to content

Commit 2edeed2

Browse files
authored
implement azure app service cloud metadata collection (#1122)
* implement azure app service cloud metadata collection Spec: https://github.com/elastic/apm/blob/master/specs/agents/metadata.md#azure-app-services-optional closes #990
1 parent ece6ba5 commit 2edeed2

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

elasticapm/utils/cloud.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,30 @@ def azure_metadata():
164164
return ret
165165

166166
except Exception:
167-
# Not on an Azure box
167+
# Not on an Azure box, maybe an azure app service?
168+
return azure_app_service_metadata()
169+
170+
171+
def azure_app_service_metadata():
172+
ret = {"provider": "azure"}
173+
website_owner_name = os.environ.get("WEBSITE_OWNER_NAME")
174+
website_instance_id = os.environ.get("WEBSITE_INSTANCE_ID")
175+
website_site_name = os.environ.get("WEBSITE_SITE_NAME")
176+
website_resource_group = os.environ.get("WEBSITE_RESOURCE_GROUP")
177+
if not all((website_owner_name, website_instance_id, website_site_name, website_resource_group)):
178+
return {}
179+
# Format of website_owner_name: {subscription id}+{app service plan resource group}-{region}webspace{.*}
180+
if "+" not in website_owner_name:
181+
return {}
182+
try:
183+
account_id, website_owner_name = website_owner_name.split("+")
184+
ret["account"] = {"id": account_id}
185+
region, _ = website_owner_name.split("webspace")
186+
ret["region"] = region.rsplit("-", 1)[1]
187+
except Exception:
168188
return {}
189+
190+
ret["instance"] = {"id": website_instance_id, "name": website_site_name}
191+
ret["project"] = {"name": website_resource_group}
192+
193+
return ret

tests/utils/cloud_tests.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030

31+
import os
32+
3133
import mock
3234
import urllib3
3335

@@ -131,3 +133,63 @@ def request(self, *args, **kwargs):
131133
"provider": "azure",
132134
"region": "westus2",
133135
}
136+
137+
138+
def test_azure_app_service_metadata():
139+
env_template = {
140+
"WEBSITE_RESOURCE_GROUP": "resource_group",
141+
"WEBSITE_SITE_NAME": "site_name",
142+
"WEBSITE_INSTANCE_ID": "instance_id",
143+
}
144+
for owner_name in (
145+
"f5940f10-2e30-3e4d-a259-63451ba6dae4+elastic-apm-AustraliaEastwebspace",
146+
"f5940f10-2e30-3e4d-a259-63451ba6dae4+appsvc_linux_australiaeast-AustraliaEastwebspace-Linux",
147+
):
148+
env = env_template.copy()
149+
env["WEBSITE_OWNER_NAME"] = owner_name
150+
with mock.patch.dict(os.environ, env):
151+
metadata = elasticapm.utils.cloud.azure_app_service_metadata()
152+
assert metadata == {
153+
"account": {"id": "f5940f10-2e30-3e4d-a259-63451ba6dae4"},
154+
"instance": {"id": "instance_id", "name": "site_name"},
155+
"project": {"name": "resource_group"},
156+
"provider": "azure",
157+
"region": "AustraliaEast",
158+
}
159+
160+
161+
def test_azure_app_service_metadata_wrong_format():
162+
env = {
163+
# the - before "elastic" is faulty
164+
"WEBSITE_OWNER_NAME": "f5940f10-2e30-3e4d-a259-63451ba6dae4-elastic-apm-AustraliaEastwebspace",
165+
"WEBSITE_RESOURCE_GROUP": "resource_group",
166+
"WEBSITE_SITE_NAME": "site_name",
167+
"WEBSITE_INSTANCE_ID": "instance_id",
168+
}
169+
with mock.patch.dict(os.environ, env):
170+
metadata = elasticapm.utils.cloud.azure_app_service_metadata()
171+
assert metadata == {}
172+
173+
174+
def test_azure_app_service_metadata_empty():
175+
with mock.patch.dict(os.environ, {}):
176+
metadata = elasticapm.utils.cloud.azure_app_service_metadata()
177+
assert metadata == {}
178+
179+
180+
def test_azure_app_service_metadata_not_complete():
181+
env_template = {
182+
"WEBSITE_OWNER_NAME": "f5940f10-2e30-3e4d-a259-63451ba6dae4+elastic-apm-AustraliaEastwebspace",
183+
"WEBSITE_RESOURCE_GROUP": "resource_group",
184+
"WEBSITE_SITE_NAME": "site_name",
185+
"WEBSITE_INSTANCE_ID": "instance_id",
186+
}
187+
for k in env_template.keys():
188+
env = env_template.copy()
189+
with mock.patch.dict(os.environ, env):
190+
os.environ[k] = ""
191+
metadata = elasticapm.utils.cloud.azure_app_service_metadata()
192+
assert metadata == {}
193+
del os.environ[k]
194+
metadata = elasticapm.utils.cloud.azure_app_service_metadata()
195+
assert metadata == {}

0 commit comments

Comments
 (0)