Skip to content

Commit 9378978

Browse files
authored
ODSC-41193: Adds API section to the telemetry. (#140)
2 parents 7060f70 + 64c99a8 commit 9378978

File tree

3 files changed

+107
-34
lines changed

3 files changed

+107
-34
lines changed

ads/config.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
OCI_ODSC_SERVICE_ENDPOINT = os.environ.get("OCI_ODSC_SERVICE_ENDPOINT")
1515
OCI_IDENTITY_SERVICE_ENDPOINT = os.environ.get("OCI_IDENTITY_SERVICE_ENDPOINT")
1616
NB_SESSION_COMPARTMENT_OCID = os.environ.get("NB_SESSION_COMPARTMENT_OCID")
17-
PROJECT_OCID = os.environ.get("PROJECT_OCID")
17+
PROJECT_OCID = os.environ.get("PROJECT_OCID") or os.environ.get("PIPELINE_PROJECT_OCID")
1818
NB_SESSION_OCID = os.environ.get("NB_SESSION_OCID")
1919
USER_OCID = os.environ.get("USER_OCID")
2020
OCI_RESOURCE_PRINCIPAL_VERSION = os.environ.get("OCI_RESOURCE_PRINCIPAL_VERSION")
@@ -24,17 +24,26 @@
2424
OCI_REGION_METADATA = os.environ.get("OCI_REGION_METADATA")
2525
JOB_RUN_OCID = os.environ.get("JOB_RUN_OCID")
2626
JOB_RUN_COMPARTMENT_OCID = os.environ.get("JOB_RUN_COMPARTMENT_OCID")
27+
PIPELINE_RUN_OCID = os.environ.get("PIPELINE_RUN_OCID")
28+
PIPELINE_RUN_COMPARTMENT_OCID = os.environ.get("PIPELINE_RUN_COMPARTMENT_OCID")
29+
PIPELINE_COMPARTMENT_OCID = os.environ.get("PIPELINE_COMPARTMENT_OCID")
30+
2731
CONDA_BUCKET_NAME = os.environ.get("CONDA_BUCKET_NAME", "service-conda-packs")
2832
CONDA_BUCKET_NS = os.environ.get("CONDA_BUCKET_NS", "id19sfcrra6z")
2933
OCI_RESOURCE_PRINCIPAL_RPT_ENDPOINT = os.environ.get(
3034
"OCI_RESOURCE_PRINCIPAL_RPT_ENDPOINT"
3135
)
32-
COMPARTMENT_OCID = NB_SESSION_COMPARTMENT_OCID or JOB_RUN_COMPARTMENT_OCID
36+
COMPARTMENT_OCID = (
37+
NB_SESSION_COMPARTMENT_OCID
38+
or JOB_RUN_COMPARTMENT_OCID
39+
or PIPELINE_RUN_COMPARTMENT_OCID
40+
)
3341
MD_OCID = os.environ.get("MD_OCID")
3442
DATAFLOW_RUN_OCID = os.environ.get("DATAFLOW_RUN_ID")
43+
3544
RESOURCE_OCID = (
36-
NB_SESSION_OCID or JOB_RUN_OCID or MD_OCID
37-
) # We can add DATAFLOW_RUN_OCID here. Needs impact analysis
45+
NB_SESSION_OCID or JOB_RUN_OCID or MD_OCID or PIPELINE_RUN_OCID or DATAFLOW_RUN_OCID
46+
)
3847
NO_CONTAINER = os.environ.get("NO_CONTAINER")
3948

4049

ads/telemetry/telemetry.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8; -*-
2+
# -*- coding: utf-8 -*--
33

4-
# Copyright (c) 2022 Oracle and/or its affiliates.
4+
# Copyright (c) 2022, 2023 Oracle and/or its affiliates.
55
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
6-
from ads import __version__
6+
7+
import os
78
from enum import Enum, auto
9+
from typing import Any, Dict, Optional
810

911
import ads.config
12+
from ads import __version__
13+
from ads.common import logger
1014

15+
LIBRARY = "Oracle-ads"
1116
EXTRA_USER_AGENT_INFO = "EXTRA_USER_AGENT_INFO"
1217
USER_AGENT_KEY = "additional_user_agent"
13-
ENV_MD_OCID = "MD_OCID"
1418
UNKNOWN = "UNKNOWN"
1519

1620

1721
class Surface(Enum):
1822
"""
19-
An Enum class for labeling the surface where ADS is being used
23+
An Enum class for labeling the surface where ADS is being used.
2024
"""
2125

2226
WORKSTATION = auto()
@@ -25,6 +29,7 @@ class Surface(Enum):
2529
DATASCIENCE_MODEL_DEPLOYMENT = auto()
2630
DATAFLOW = auto()
2731
OCI_SERVICE = auto()
32+
DATASCIENCE_PIPELINE = auto()
2833

2934
@classmethod
3035
def surface(cls):
@@ -43,12 +48,33 @@ def surface(cls):
4348
surface = cls.DATASCIENCE_MODEL_DEPLOYMENT
4449
elif ads.config.DATAFLOW_RUN_OCID:
4550
surface = cls.DATAFLOW
51+
elif ads.config.PIPELINE_RUN_OCID:
52+
surface = cls.DATASCIENCE_PIPELINE
4653
return surface
4754

4855

49-
def update_oci_client_config(config={}):
50-
if not config.get(USER_AGENT_KEY):
51-
config[
52-
USER_AGENT_KEY
53-
] = f"Oracle-ads/version={__version__}/surface={Surface.surface().name}" # To be enabled in future - /api={os.environ.get(EXTRA_USER_AGENT_INFO,UNKNOWN)}"
56+
def update_oci_client_config(config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
57+
"""Adds user agent information to the config if it is not setup yet.
58+
59+
Returns
60+
-------
61+
Dict
62+
The updated configuration.
63+
"""
64+
65+
try:
66+
config = config or {}
67+
if not config.get(USER_AGENT_KEY):
68+
config.update(
69+
{
70+
USER_AGENT_KEY: (
71+
f"{LIBRARY}/version={__version__}/"
72+
f"surface={Surface.surface().name}/"
73+
f"api={os.environ.get(EXTRA_USER_AGENT_INFO,UNKNOWN) or UNKNOWN}"
74+
)
75+
}
76+
)
77+
except Exception as ex:
78+
logger.debug(ex)
79+
5480
return config

tests/unitary/default_setup/telemetry/test_agent.py

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@
33
# Copyright (c) 2022, 2023 Oracle and/or its affiliates.
44
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
55

6+
import importlib
67
from unittest.mock import patch
8+
79
import pytest
8-
from pytest import MonkeyPatch
9-
import importlib
10+
# from pytest import MonkeyPatch
1011

1112
import ads
13+
from ads.telemetry.telemetry import (
14+
EXTRA_USER_AGENT_INFO,
15+
LIBRARY,
16+
UNKNOWN,
17+
USER_AGENT_KEY,
18+
)
1219

1320

1421
class TestUserAgent:
@@ -31,47 +38,77 @@ def test_user_agent_api_keys_using_test_profile(self, mock_signer):
3138
auth_info = ads.auth.api_keys("test_path", "TEST_PROFILE")
3239
assert (
3340
auth_info["config"].get("additional_user_agent")
34-
== f"Oracle-ads/version={ads.__version__}/surface=WORKSTATION"
41+
== f"{LIBRARY}/version={ads.__version__}/surface=WORKSTATION/api={UNKNOWN}"
3542
)
3643

3744
@patch("oci.auth.signers.get_resource_principals_signer")
38-
def test_user_agent_rp(self, mock_signer):
45+
def test_user_agent_rp(self, mock_signer, monkeypatch):
46+
monkeypatch.delenv("OCI_RESOURCE_PRINCIPAL_VERSION", raising=False)
3947
importlib.reload(ads.config)
4048
importlib.reload(ads.telemetry)
4149
auth_info = ads.auth.resource_principal()
4250
assert (
4351
auth_info["config"].get("additional_user_agent")
44-
== f"Oracle-ads/version={ads.__version__}/surface=WORKSTATION"
52+
== f"{LIBRARY}/version={ads.__version__}/surface=WORKSTATION/api={UNKNOWN}"
4553
)
4654

4755
@patch("oci.signer.load_private_key_from_file")
48-
def test_user_agent_default_signer(self, mock_load_key_file):
49-
monkeypatch = MonkeyPatch()
56+
def test_user_agent_default_signer(self, mock_load_key_file, monkeypatch):
57+
# monkeypatch = MonkeyPatch()
5058
monkeypatch.delenv("OCI_RESOURCE_PRINCIPAL_VERSION", raising=False)
5159
importlib.reload(ads.config)
5260
with patch("oci.config.from_file", return_value=self.test_config):
5361
auth_info = ads.auth.default_signer()
5462
assert (
5563
auth_info["config"].get("additional_user_agent")
56-
== f"Oracle-ads/version={ads.__version__}/surface=WORKSTATION"
64+
== f"{LIBRARY}/version={ads.__version__}/surface=WORKSTATION/api={UNKNOWN}"
5765
)
5866

5967
@pytest.mark.parametrize(
60-
"RESOURCE_KEY, USER_AGENT_VALUE",
68+
"INPUT_DATA, EXPECTED_RESULT",
6169
[
62-
("MD_OCID", "DATASCIENCE_MODEL_DEPLOYMENT"),
63-
("JOB_RUN_OCID", "DATASCIENCE_JOB"),
64-
("NB_SESSION_OCID", "DATASCIENCE_NOTEBOOK"),
65-
("DATAFLOW_RUN_ID", "DATAFLOW"),
70+
(
71+
{"RESOURCE_KEY": "MD_OCID", EXTRA_USER_AGENT_INFO: ""},
72+
{
73+
"USER_AGENT_VALUE": "DATASCIENCE_MODEL_DEPLOYMENT",
74+
EXTRA_USER_AGENT_INFO: UNKNOWN,
75+
},
76+
),
77+
(
78+
{"RESOURCE_KEY": "JOB_RUN_OCID", EXTRA_USER_AGENT_INFO: "test_api"},
79+
{
80+
"USER_AGENT_VALUE": "DATASCIENCE_JOB",
81+
EXTRA_USER_AGENT_INFO: "test_api",
82+
},
83+
),
84+
(
85+
{"RESOURCE_KEY": "NB_SESSION_OCID", EXTRA_USER_AGENT_INFO: None},
86+
{
87+
"USER_AGENT_VALUE": "DATASCIENCE_NOTEBOOK",
88+
EXTRA_USER_AGENT_INFO: UNKNOWN,
89+
},
90+
),
91+
(
92+
{
93+
"RESOURCE_KEY": "DATAFLOW_RUN_ID",
94+
EXTRA_USER_AGENT_INFO: "some_class&some_method",
95+
},
96+
{
97+
"USER_AGENT_VALUE": "DATAFLOW",
98+
EXTRA_USER_AGENT_INFO: "some_class&some_method",
99+
},
100+
),
66101
],
67102
)
68103
@patch("oci.signer.load_private_key_from_file")
69104
def test_user_agent_default_signer_known_resources(
70-
self, mock_load_key_file, RESOURCE_KEY, USER_AGENT_VALUE
105+
self,mock_load_key_file, monkeypatch, INPUT_DATA, EXPECTED_RESULT
71106
):
72-
monkeypatch = MonkeyPatch()
107+
# monkeypatch = MonkeyPatch()
73108
monkeypatch.setenv("OCI_RESOURCE_PRINCIPAL_VERSION", "1.1")
74-
monkeypatch.setenv(RESOURCE_KEY, "1234")
109+
monkeypatch.setenv(INPUT_DATA["RESOURCE_KEY"], "1234")
110+
if INPUT_DATA[EXTRA_USER_AGENT_INFO] is not None:
111+
monkeypatch.setenv(EXTRA_USER_AGENT_INFO, INPUT_DATA[EXTRA_USER_AGENT_INFO])
75112

76113
importlib.reload(ads.config)
77114
importlib.reload(ads)
@@ -82,17 +119,18 @@ def test_user_agent_default_signer_known_resources(
82119
auth_info = ads.auth.default_signer()
83120
assert (
84121
auth_info["config"].get("additional_user_agent")
85-
== f"Oracle-ads/version={ads.__version__}/surface={USER_AGENT_VALUE}"
122+
== f"{LIBRARY}/version={ads.__version__}/surface={EXPECTED_RESULT['USER_AGENT_VALUE']}/api={EXPECTED_RESULT[EXTRA_USER_AGENT_INFO]}"
86123
)
87124
monkeypatch.delenv("OCI_RESOURCE_PRINCIPAL_VERSION", raising=False)
88-
monkeypatch.delenv(RESOURCE_KEY, raising=False)
125+
monkeypatch.delenv(INPUT_DATA["RESOURCE_KEY"], raising=False)
126+
monkeypatch.delenv(EXTRA_USER_AGENT_INFO, raising=False)
89127

90128
@patch("oci.signer.Signer")
91129
def test_user_agent_default_singer_ociservice(
92130
self,
93131
mock_signer,
132+
monkeypatch
94133
):
95-
monkeypatch = MonkeyPatch()
96134
monkeypatch.setenv("OCI_RESOURCE_PRINCIPAL_VERSION", "1.1")
97135

98136
importlib.reload(ads.config)
@@ -102,6 +140,6 @@ def test_user_agent_default_singer_ociservice(
102140
auth_info = ads.auth.default_signer()
103141
assert (
104142
auth_info["config"].get("additional_user_agent")
105-
== f"Oracle-ads/version={ads.__version__}/surface=OCI_SERVICE"
143+
== f"{LIBRARY}/version={ads.__version__}/surface=OCI_SERVICE/api={UNKNOWN}"
106144
)
107145
monkeypatch.delenv("OCI_RESOURCE_PRINCIPAL_VERSION", raising=False)

0 commit comments

Comments
 (0)