-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow clients to tag requests with a source_tag (#324)
## Problem Need to allow clients to include a `source_tag` to identify the source of their requests. ## Solution Allow clients to specify a `source_tag` field in the client constructor, that will be used to identify the traffic source, if applicable. Example: ```python from pinecone import Pinecone pc = Pinecone(api_key='foo', source_tag='bar') pc.list_indexes() ``` This would cause the user-agent to get a value like: ``` User-Agent: 'python-client-3.1.0 (urllib3:2.0.7); source_tag=bar' ``` ## Type of Change - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) ## Testing - [ ] Tests are passing - [ ] Verify source_tag included in user-agent in control plane and data plane (REST and gRPC)
- Loading branch information
Showing
13 changed files
with
137 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,29 @@ | ||
import urllib3 | ||
|
||
from .version import __version__ | ||
from .constants import SOURCE_TAG | ||
import re | ||
|
||
def get_user_agent(): | ||
client_id = f"python-client-{__version__}" | ||
def _build_source_tag_field(source_tag): | ||
# normalize source tag | ||
# 1. Lowercase | ||
# 2. Limit charset to [a-z0-9_ ] | ||
# 3. Trim left/right whitespace | ||
# 4. Condense multiple spaces to one, and replace with underscore | ||
tag = source_tag.lower() | ||
tag = re.sub(r'[^a-z0-9_ ]', '', tag) | ||
tag = tag.strip() | ||
tag = "_".join(tag.split()) | ||
return f"{SOURCE_TAG}={tag}" | ||
|
||
def _get_user_agent(client_id, config): | ||
user_agent_details = {"urllib3": urllib3.__version__} | ||
user_agent = "{} ({})".format(client_id, ", ".join([f"{k}:{v}" for k, v in user_agent_details.items()])) | ||
return user_agent | ||
user_agent += f"; {_build_source_tag_field(config.source_tag)}" if config.source_tag else "" | ||
return user_agent | ||
|
||
def get_user_agent(config): | ||
return _get_user_agent(f"python-client-{__version__}", config) | ||
|
||
def get_user_agent_grpc(config): | ||
return _get_user_agent(f"python-client[grpc]-{__version__}", config) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import re | ||
from pinecone.config import ConfigBuilder | ||
from pinecone.core.client.api.manage_indexes_api import ManageIndexesApi | ||
from pinecone.utils.setup_openapi_client import setup_openapi_client | ||
|
||
class TestSetupOpenAPIClient(): | ||
def test_setup_openapi_client(self): | ||
"" | ||
# config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host") | ||
# api_client = setup_openapi_client(ManageIndexesApi, config=config, pool_threads=2) | ||
# # assert api_client.user_agent == "pinecone-python-client/0.0.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,47 @@ | ||
import re | ||
from pinecone.utils.user_agent import get_user_agent | ||
from pinecone.utils.user_agent import get_user_agent, get_user_agent_grpc | ||
from pinecone.config import ConfigBuilder | ||
|
||
class TestUserAgent(): | ||
def test_user_agent(self): | ||
useragent = get_user_agent() | ||
config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host") | ||
useragent = get_user_agent(config) | ||
assert re.search(r"python-client-\d+\.\d+\.\d+", useragent) is not None | ||
assert re.search(r"urllib3:\d+\.\d+\.\d+", useragent) is not None | ||
assert re.search(r"urllib3:\d+\.\d+\.\d+", useragent) is not None | ||
|
||
def test_user_agent_with_source_tag(self): | ||
config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host", source_tag="my_source_tag") | ||
useragent = get_user_agent(config) | ||
assert re.search(r"python-client-\d+\.\d+\.\d+", useragent) is not None | ||
assert re.search(r"urllib3:\d+\.\d+\.\d+", useragent) is not None | ||
assert re.search(r"source_tag=my_source_tag", useragent) is not None | ||
|
||
def test_source_tag_is_normalized(self): | ||
config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host", source_tag="my source tag!!!!") | ||
useragent = get_user_agent(config) | ||
assert re.search(r"source_tag=my_source_tag", useragent) is not None | ||
|
||
config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host", source_tag="My Source Tag") | ||
useragent = get_user_agent(config) | ||
assert re.search(r"source_tag=my_source_tag", useragent) is not None | ||
|
||
config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host", source_tag=" My Source Tag 123 ") | ||
useragent = get_user_agent(config) | ||
assert re.search(r"source_tag=my_source_tag_123", useragent) is not None | ||
|
||
config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host", source_tag=" My Source Tag 123 #### !! ") | ||
useragent = get_user_agent(config) | ||
assert re.search(r"source_tag=my_source_tag_123", useragent) is not None | ||
|
||
def test_user_agent_grpc(self): | ||
config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host") | ||
useragent = get_user_agent_grpc(config) | ||
assert re.search(r"python-client\[grpc\]-\d+\.\d+\.\d+", useragent) is not None | ||
assert re.search(r"urllib3:\d+\.\d+\.\d+", useragent) is not None | ||
|
||
def test_user_agent_grpc_with_source_tag(self): | ||
config = ConfigBuilder.build(api_key="my-api-key", host="https://my-controller-host", source_tag="my_source_tag") | ||
useragent = get_user_agent_grpc(config) | ||
assert re.search(r"python-client\[grpc\]-\d+\.\d+\.\d+", useragent) is not None | ||
assert re.search(r"urllib3:\d+\.\d+\.\d+", useragent) is not None | ||
assert re.search(r"source_tag=my_source_tag", useragent) is not None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters