Skip to content

Commit 96804cf

Browse files
authored
Merge pull request #3 from pinecone-io/fix-log-level
Move logger handling out of pinecone.init and switch to standard logging module
2 parents 647b831 + 40d60cb commit 96804cf

File tree

8 files changed

+58
-54
lines changed

8 files changed

+58
-54
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
## [Unreleased]
44

55
### Changed
6-
- `pinecone.init()` can now be used to set the pinecone logger's log level.
7-
- The python client `pinecone.config.OpenApiConfiguration` object now uses the certifi package's SSL CA bundle by default. This should fix HTTPS connection errors in certain environments depending on their default CA bundle, including some Google Colab notebooks.
6+
- Deprecated control via `pinecone.init()` of the pinecone logger's log level and removed the loguru dependency. To control log level now, use the standard library's logging module to manage the level of the "pinecone" logger or its children.
87

98
## [2.0.1] - 2021-10-06
109
### Added
@@ -13,6 +12,7 @@
1312

1413
### Changed
1514
- Updates the default openapi_config object to use the certifice ssl_ca_cert bundle.
15+
- The python client `pinecone.config.OpenApiConfiguration` object now uses the certifi package's SSL CA bundle by default. This should fix HTTPS connection errors in certain environments depending on their default CA bundle, including some Google Colab notebooks.
1616

1717
## [2.0.0] - 2020-10-04
1818
### Added

pinecone/config.py

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
#
22
# Copyright (c) 2020-2021 Pinecone Systems Inc. All right reserved.
33
#
4-
import sys
4+
import logging
55
from typing import NamedTuple
66
import os
77

88
import certifi
9-
from loguru import logger
109
import requests
1110
import sentry_sdk
1211
import configparser
1312

1413
from pinecone.core.client.exceptions import ApiKeyError
1514
from pinecone.core.api_action import ActionAPI, WhoAmIResponse
16-
from pinecone.core.utils.constants import CLIENT_VERSION
15+
from pinecone.core.utils import warn_deprecated
16+
from pinecone.core.utils.constants import CLIENT_VERSION, PARENT_LOGGER_NAME, DEFAULT_PARENT_LOGGER_LEVEL
1717
from pinecone.core.utils.sentry import sentry_decorator as sentry
1818
from pinecone.core.client.configuration import Configuration as OpenApiConfiguration
1919

2020
__all__ = [
21-
"Config", "logger", "init"
21+
"Config", "init"
2222
]
2323

24+
_logger = logging.getLogger(__name__)
25+
_parent_logger = logging.getLogger(PARENT_LOGGER_NAME)
26+
_parent_logger.setLevel(DEFAULT_PARENT_LOGGER_LEVEL)
27+
2428

2529
def _set_sentry_tags(config: dict):
2630
sentry_sdk.set_tag("package_version", CLIENT_VERSION)
@@ -35,7 +39,6 @@ class ConfigBase(NamedTuple):
3539
api_key: str = ""
3640
project_name: str = ""
3741
controller_host: str = ""
38-
log_level: str = ""
3942
openapi_config: OpenApiConfiguration = None
4043

4144

@@ -119,19 +122,6 @@ def reset(self, config_file=None, **kwargs):
119122
config = config._replace(openapi_config=openapi_config)
120123
self._config = config
121124

122-
# Set log level
123-
log_level = (
124-
kwargs.pop("log_level", None)
125-
or os.getenv("PINECONE_LOG_LEVEL")
126-
or os.getenv("PINECONE_LOGGING")
127-
or file_config.pop("log_level", None)
128-
)
129-
if log_level:
130-
logger.remove()
131-
logger.add(sys.stdout, enqueue=True, level=(log_level or "ERROR"))
132-
config = config._replace(log_level=log_level)
133-
self._config = config
134-
135125
# Sentry
136126
_set_sentry_tags({**whoami_response._asdict(), **self._config._asdict()})
137127

@@ -188,7 +178,15 @@ def OPENAPI_CONFIG(self):
188178

189179
@property
190180
def LOG_LEVEL(self):
191-
return self._config.log_level
181+
"""
182+
Deprecated since v2.0.2 [Will be removed in v3.0.0]; use the standard logging module logger "pinecone" instead.
183+
"""
184+
warn_deprecated(
185+
description='LOG_LEVEL is deprecated. Use the standard logging module logger "pinecone" instead.',
186+
deprecated_in='2.0.2',
187+
removal_in='3.0.0'
188+
)
189+
return logging.getLevelName(logging.getLogger('pinecone').level)
192190

193191

194192
@sentry
@@ -201,20 +199,19 @@ def init(api_key: str = None, host: str = None, environment: str = None, project
201199
:param host: Optional. Controller host.
202200
:param environment: Optional. Deployment environment.
203201
:param project_name: Optional. Pinecone project name. Overrides the value that is otherwise looked up and used from the Pinecone backend.
204-
:param log_level: Optional. Set Pinecone log level.
205202
:param openapi_config: Optional. Set OpenAPI client configuration.
206203
:param config: Optional. An INI configuration file.
204+
:param log_level: Deprecated since v2.0.2 [Will be removed in v3.0.0]; use the standard logging module to manage logger "pinecone" instead.
207205
"""
208206
Config.reset(project_name=project_name, api_key=api_key, controller_host=host, environment=environment,
209-
log_level=log_level, openapi_config=openapi_config,
210-
config_file=config, **kwargs)
211-
if not bool(Config.API_KEY):
212-
logger.warning("API key is required.")
213-
207+
openapi_config=openapi_config, config_file=config, **kwargs)
208+
if log_level:
209+
warn_deprecated(
210+
description='log_level is deprecated. Use the standard logging module to manage logger "pinecone" instead.',
211+
deprecated_in='2.0.2',
212+
removal_in='3.0.0'
213+
)
214214

215-
logger.remove()
216-
logger.add(sys.stdout, enqueue=True, level=(
217-
os.getenv("PINECONE_LOG_LEVEL") or os.getenv("PINECONE_LOGGING") or "ERROR"))
218215

219216
Config = _CONFIG()
220217

pinecone/core/grpc/index_grpc.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
#
22
# Copyright (c) 2020-2021 Pinecone Systems Inc. All right reserved.
33
#
4-
4+
import logging
55
from abc import ABC, abstractmethod
66
from functools import wraps
77
from typing import NamedTuple, Optional, Dict
88

99
import grpc
1010

11-
from pinecone import logger
1211
from pinecone.config import Config
1312
from pinecone.core.grpc.protos.vector_column_service_pb2_grpc import VectorColumnServiceStub
1413
from pinecone.core.grpc.protos import vector_service_pb2, vector_column_service_pb2
@@ -19,6 +18,9 @@
1918
from pinecone.core.utils.constants import MAX_MSG_SIZE, REQUEST_ID, CLIENT_VERSION
2019

2120

21+
_logger = logging.getLogger(__name__)
22+
23+
2224
class GRPCClientConfig(NamedTuple):
2325
"""
2426
GRPC client configuration options.
@@ -91,7 +93,7 @@ def _gen_channel(self, options=None):
9193
default_options['grpc.ssl_target_name_override'] = target.split(':')[0]
9294
user_provided_options = options or {}
9395
_options = tuple((k, v) for k, v in {**default_options, **user_provided_options}.items())
94-
logger.debug('creating new channel with endpoint {} options {} and config {}',
96+
_logger.debug('creating new channel with endpoint %s options %s and config %s',
9597
target, _options, self.grpc_client_config)
9698
if not self.grpc_client_config.secure:
9799
channel = grpc.insecure_channel(target, options=_options)

pinecone/core/grpc/retry.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
#
44

55
import abc
6+
import logging
67
import random
78
import time
89
from typing import Optional, Tuple, NamedTuple
910

1011
import grpc
1112

12-
from pinecone import logger
13+
14+
_logger = logging.getLogger(__name__)
1315

1416

1517
class SleepPolicy(abc.ABC):
@@ -31,7 +33,7 @@ def __init__(self, *, init_backoff_ms: int, max_backoff_ms: int, multiplier: int
3133
def sleep(self, try_i: int):
3234
sleep_range = min(self.init_backoff * self.multiplier ** try_i, self.max_backoff)
3335
sleep_ms = random.randint(0, sleep_range)
34-
logger.debug(f"gRPC retry. Sleeping for {sleep_ms}ms")
36+
_logger.debug(f"gRPC retry. Sleeping for {sleep_ms}ms")
3537
time.sleep(sleep_ms / 1000)
3638

3739

pinecone/core/utils/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#
44
import re
55
import uuid
6+
import warnings
67
from pathlib import Path
78
from typing import List
89

@@ -67,3 +68,8 @@ def get_user_agent():
6768
user_agent_details = {'requests': requests.__version__, 'urllib3': urllib3.__version__}
6869
user_agent = '{} ({})'.format(client_id, ', '.join([f'{k}:{v}' for k, v in user_agent_details.items()]))
6970
return user_agent
71+
72+
73+
def warn_deprecated(description: str = '', deprecated_in: str = None, removal_in: str = None):
74+
message = f'DEPRECATED since v{deprecated_in} [Will be removed in v{removal_in}]: {description}'
75+
warnings.warn(message, DeprecationWarning)

pinecone/core/utils/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
from pinecone.core.utils import get_environment, get_version
99

10+
PARENT_LOGGER_NAME = 'pinecone'
11+
DEFAULT_PARENT_LOGGER_LEVEL = 'ERROR'
12+
1013
MAX_MSG_SIZE = 128 * 1024 * 1024
1114

1215
MAX_ID_LENGTH = int(os.environ.get("PINECONE_MAX_ID_LENGTH", default="64"))

pinecone/core/utils/sentry.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#
22
# Copyright (c) 2020-2021 Pinecone Systems Inc. All right reserved.
33
#
4+
import logging
45

56
import dns.resolver
67
import sentry_sdk
@@ -10,7 +11,9 @@
1011
from functools import wraps
1112

1213
from pinecone.core.utils.constants import PACKAGE_ENVIRONMENT, SENTRY_DSN_TXT_RECORD
13-
from pinecone.config import logger
14+
15+
16+
_logger = logging.getLogger(__name__)
1417

1518

1619
def sentry_decorator(func):
@@ -35,7 +38,7 @@ def init_sentry():
3538
The Sentry DSN is stored as a txt record.
3639
"""
3740
if not sentry_sdk.Hub.current.client:
38-
logger.info("Sentry is not initialized.")
41+
_logger.info("Sentry is not initialized.")
3942
# sentry is not initialized
4043
sentry_dsn = None
4144
try:
@@ -44,7 +47,7 @@ def init_sentry():
4447
sentry_dsn = json.loads(res.to_text())
4548
break
4649
except Exception:
47-
logger.warning("Unable to resolve Sentry DSN.")
50+
_logger.warning("Unable to resolve Sentry DSN.")
4851
if sentry_dsn:
4952
debug = os.getenv("SENTRY_DEBUG") == "True"
5053
sentry_sdk.init(dsn=sentry_dsn, debug=debug, environment=PACKAGE_ENVIRONMENT, traces_sample_rate=0.1)

tests/unit/test_config.py

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
11
import pinecone
2-
from pinecone.config import logger, Config
2+
from pinecone.config import Config
33

44

5-
def test_update_log_level():
6-
default_level = 'ERROR'
7-
assert list(logger._core.handlers.values())[0].levelno == logger.level(default_level).no
8-
new_level = 'INFO'
9-
pinecone.init(log_level=new_level)
10-
assert list(logger._core.handlers.values())[0].levelno == logger.level(new_level).no
11-
12-
13-
def test_multi_init():
5+
def _test_multi_init():
146
env = 'test-env'
15-
level = 'INFO'
16-
# first init() sets log level
17-
pinecone.init(log_level=level)
7+
api_key = 'foobar'
8+
# first init() sets api_key
9+
pinecone.init(api_key=api_key)
1810
assert Config.ENVIRONMENT == 'us-west1-gcp'
19-
assert list(logger._core.handlers.values())[0].levelno == logger.level(level).no
20-
# next init() shouldn't clobber log level
11+
# next init() shouldn't clobber api_key
2112
pinecone.init(environment=env)
2213
assert Config.ENVIRONMENT == env
23-
assert list(logger._core.handlers.values())[0].levelno == logger.level(level).no
14+
assert Config.API_KEY == api_key

0 commit comments

Comments
 (0)