Skip to content

Commit 345f8b5

Browse files
committed
ODSC-41193: Adds API section to the telemetry.
1 parent 230cde6 commit 345f8b5

File tree

3 files changed

+107
-33
lines changed

3 files changed

+107
-33
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 & 19 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,7 +38,7 @@ 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")
@@ -41,37 +48,66 @@ def test_user_agent_rp(self, mock_signer):
4148
auth_info = ads.auth.resource_principal()
4249
assert (
4350
auth_info["config"].get("additional_user_agent")
44-
== f"Oracle-ads/version={ads.__version__}/surface=WORKSTATION"
51+
== f"{LIBRARY}/version={ads.__version__}/surface=WORKSTATION/api={UNKNOWN}"
4552
)
4653

4754
@patch("oci.signer.load_private_key_from_file")
48-
def test_user_agent_default_signer(self, mock_load_key_file):
49-
monkeypatch = MonkeyPatch()
55+
def test_user_agent_default_signer(self, mock_load_key_file, monkeypatch):
56+
# monkeypatch = MonkeyPatch()
5057
monkeypatch.delenv("OCI_RESOURCE_PRINCIPAL_VERSION", raising=False)
5158
importlib.reload(ads.config)
5259
with patch("oci.config.from_file", return_value=self.test_config):
5360
auth_info = ads.auth.default_signer()
5461
assert (
5562
auth_info["config"].get("additional_user_agent")
56-
== f"Oracle-ads/version={ads.__version__}/surface=WORKSTATION"
63+
== f"{LIBRARY}/version={ads.__version__}/surface=WORKSTATION/api={UNKNOWN}"
5764
)
5865

5966
@pytest.mark.parametrize(
60-
"RESOURCE_KEY, USER_AGENT_VALUE",
67+
"INPUT_DATA, EXPECTED_RESULT",
6168
[
62-
("MD_OCID", "DATASCIENCE_MODEL_DEPLOYMENT"),
63-
("JOB_RUN_OCID", "DATASCIENCE_JOB"),
64-
("NB_SESSION_OCID", "DATASCIENCE_NOTEBOOK"),
65-
("DATAFLOW_RUN_ID", "DATAFLOW"),
69+
(
70+
{"RESOURCE_KEY": "MD_OCID", EXTRA_USER_AGENT_INFO: ""},
71+
{
72+
"USER_AGENT_VALUE": "DATASCIENCE_MODEL_DEPLOYMENT",
73+
EXTRA_USER_AGENT_INFO: UNKNOWN,
74+
},
75+
),
76+
(
77+
{"RESOURCE_KEY": "JOB_RUN_OCID", EXTRA_USER_AGENT_INFO: "test_api"},
78+
{
79+
"USER_AGENT_VALUE": "DATASCIENCE_JOB",
80+
EXTRA_USER_AGENT_INFO: "test_api",
81+
},
82+
),
83+
(
84+
{"RESOURCE_KEY": "NB_SESSION_OCID", EXTRA_USER_AGENT_INFO: None},
85+
{
86+
"USER_AGENT_VALUE": "DATASCIENCE_NOTEBOOK",
87+
EXTRA_USER_AGENT_INFO: UNKNOWN,
88+
},
89+
),
90+
(
91+
{
92+
"RESOURCE_KEY": "DATAFLOW_RUN_ID",
93+
EXTRA_USER_AGENT_INFO: "some_class&some_method",
94+
},
95+
{
96+
"USER_AGENT_VALUE": "DATAFLOW",
97+
EXTRA_USER_AGENT_INFO: "some_class&some_method",
98+
},
99+
),
66100
],
67101
)
68102
@patch("oci.signer.load_private_key_from_file")
69103
def test_user_agent_default_signer_known_resources(
70-
self, mock_load_key_file, RESOURCE_KEY, USER_AGENT_VALUE
104+
self,mock_load_key_file, monkeypatch, INPUT_DATA, EXPECTED_RESULT
71105
):
72-
monkeypatch = MonkeyPatch()
106+
# monkeypatch = MonkeyPatch()
73107
monkeypatch.setenv("OCI_RESOURCE_PRINCIPAL_VERSION", "1.1")
74-
monkeypatch.setenv(RESOURCE_KEY, "1234")
108+
monkeypatch.setenv(INPUT_DATA["RESOURCE_KEY"], "1234")
109+
if INPUT_DATA[EXTRA_USER_AGENT_INFO] is not None:
110+
monkeypatch.setenv(EXTRA_USER_AGENT_INFO, INPUT_DATA[EXTRA_USER_AGENT_INFO])
75111

76112
importlib.reload(ads.config)
77113
importlib.reload(ads)
@@ -82,17 +118,20 @@ def test_user_agent_default_signer_known_resources(
82118
auth_info = ads.auth.default_signer()
83119
assert (
84120
auth_info["config"].get("additional_user_agent")
85-
== f"Oracle-ads/version={ads.__version__}/surface={USER_AGENT_VALUE}"
121+
== f"{LIBRARY}/version={ads.__version__}/surface={EXPECTED_RESULT['USER_AGENT_VALUE']}/api={EXPECTED_RESULT[EXTRA_USER_AGENT_INFO]}"
86122
)
87123
monkeypatch.delenv("OCI_RESOURCE_PRINCIPAL_VERSION", raising=False)
88-
monkeypatch.delenv(RESOURCE_KEY, raising=False)
124+
monkeypatch.delenv(INPUT_DATA["RESOURCE_KEY"], raising=False)
125+
monkeypatch.delenv(EXTRA_USER_AGENT_INFO, raising=False)
89126

90127
@patch("oci.signer.Signer")
91128
def test_user_agent_default_singer_ociservice(
92129
self,
93130
mock_signer,
131+
monkeypatch
94132
):
95-
monkeypatch = MonkeyPatch()
133+
#monkeypatch = MonkeyPatch()
134+
monkeypatch.setenv("OCI_RESOURCE_PRINCIPAL_VERSION", "1.1")
96135
monkeypatch.setenv("OCI_RESOURCE_PRINCIPAL_VERSION", "1.1")
97136

98137
importlib.reload(ads.config)
@@ -102,6 +141,6 @@ def test_user_agent_default_singer_ociservice(
102141
auth_info = ads.auth.default_signer()
103142
assert (
104143
auth_info["config"].get("additional_user_agent")
105-
== f"Oracle-ads/version={ads.__version__}/surface=OCI_SERVICE"
144+
== f"{LIBRARY}/version={ads.__version__}/surface=OCI_SERVICE/api={UNKNOWN}"
106145
)
107146
monkeypatch.delenv("OCI_RESOURCE_PRINCIPAL_VERSION", raising=False)

0 commit comments

Comments
 (0)