snowflake-connector-python 4.4.0__cp314-cp314-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- snowflake/connector/__init__.py +118 -0
- snowflake/connector/_query_context_cache.py +276 -0
- snowflake/connector/_sql_util.py +48 -0
- snowflake/connector/_utils.py +353 -0
- snowflake/connector/aio/README.md +88 -0
- snowflake/connector/aio/__init__.py +163 -0
- snowflake/connector/aio/_azure_storage_client.py +227 -0
- snowflake/connector/aio/_bind_upload_agent.py +69 -0
- snowflake/connector/aio/_connection.py +1216 -0
- snowflake/connector/aio/_cursor.py +1402 -0
- snowflake/connector/aio/_description.py +5 -0
- snowflake/connector/aio/_direct_file_operation_utils.py +88 -0
- snowflake/connector/aio/_file_transfer_agent.py +316 -0
- snowflake/connector/aio/_gcs_storage_client.py +360 -0
- snowflake/connector/aio/_network.py +860 -0
- snowflake/connector/aio/_ocsp_asn1crypto.py +51 -0
- snowflake/connector/aio/_ocsp_snowflake.py +608 -0
- snowflake/connector/aio/_pandas_tools.py +561 -0
- snowflake/connector/aio/_result_batch.py +442 -0
- snowflake/connector/aio/_result_set.py +309 -0
- snowflake/connector/aio/_s3_storage_client.py +460 -0
- snowflake/connector/aio/_session_manager.py +588 -0
- snowflake/connector/aio/_storage_client.py +331 -0
- snowflake/connector/aio/_telemetry.py +97 -0
- snowflake/connector/aio/_time_util.py +57 -0
- snowflake/connector/aio/_wif_util.py +324 -0
- snowflake/connector/aio/auth/__init__.py +52 -0
- snowflake/connector/aio/auth/_auth.py +406 -0
- snowflake/connector/aio/auth/_by_plugin.py +131 -0
- snowflake/connector/aio/auth/_default.py +28 -0
- snowflake/connector/aio/auth/_idtoken.py +54 -0
- snowflake/connector/aio/auth/_keypair.py +60 -0
- snowflake/connector/aio/auth/_no_auth.py +31 -0
- snowflake/connector/aio/auth/_oauth.py +27 -0
- snowflake/connector/aio/auth/_oauth_code.py +117 -0
- snowflake/connector/aio/auth/_oauth_credentials.py +100 -0
- snowflake/connector/aio/auth/_okta.py +247 -0
- snowflake/connector/aio/auth/_pat.py +27 -0
- snowflake/connector/aio/auth/_usrpwdmfa.py +30 -0
- snowflake/connector/aio/auth/_webbrowser.py +405 -0
- snowflake/connector/aio/auth/_workload_identity.py +60 -0
- snowflake/connector/arrow_context.py +211 -0
- snowflake/connector/auth/__init__.py +53 -0
- snowflake/connector/auth/_auth.py +669 -0
- snowflake/connector/auth/_http_server.py +257 -0
- snowflake/connector/auth/_oauth_base.py +472 -0
- snowflake/connector/auth/by_plugin.py +219 -0
- snowflake/connector/auth/default.py +36 -0
- snowflake/connector/auth/idtoken.py +72 -0
- snowflake/connector/auth/keypair.py +225 -0
- snowflake/connector/auth/no_auth.py +39 -0
- snowflake/connector/auth/oauth.py +49 -0
- snowflake/connector/auth/oauth_code.py +490 -0
- snowflake/connector/auth/oauth_credentials.py +71 -0
- snowflake/connector/auth/okta.py +339 -0
- snowflake/connector/auth/pat.py +40 -0
- snowflake/connector/auth/usrpwdmfa.py +69 -0
- snowflake/connector/auth/webbrowser.py +514 -0
- snowflake/connector/auth/workload_identity.py +110 -0
- snowflake/connector/azure_storage_client.py +278 -0
- snowflake/connector/backoff_policies.py +141 -0
- snowflake/connector/bind_upload_agent.py +89 -0
- snowflake/connector/cache.py +696 -0
- snowflake/connector/compat.py +127 -0
- snowflake/connector/config_manager.py +553 -0
- snowflake/connector/connection.py +2671 -0
- snowflake/connector/connection_diagnostic.py +793 -0
- snowflake/connector/constants.py +460 -0
- snowflake/connector/converter.py +809 -0
- snowflake/connector/converter_issue23517.py +87 -0
- snowflake/connector/converter_null.py +14 -0
- snowflake/connector/converter_snowsql.py +205 -0
- snowflake/connector/crl.py +919 -0
- snowflake/connector/crl_cache.py +734 -0
- snowflake/connector/cursor.py +2099 -0
- snowflake/connector/dbapi.py +53 -0
- snowflake/connector/description.py +21 -0
- snowflake/connector/direct_file_operation_utils.py +88 -0
- snowflake/connector/encryption_util.py +220 -0
- snowflake/connector/errorcode.py +94 -0
- snowflake/connector/errors.py +666 -0
- snowflake/connector/externals_utils/__init__.py +0 -0
- snowflake/connector/externals_utils/externals_setup.py +30 -0
- snowflake/connector/feature.py +4 -0
- snowflake/connector/file_compression_type.py +118 -0
- snowflake/connector/file_lock.py +72 -0
- snowflake/connector/file_transfer_agent.py +1244 -0
- snowflake/connector/file_util.py +153 -0
- snowflake/connector/gcs_storage_client.py +476 -0
- snowflake/connector/gzip_decoder.py +85 -0
- snowflake/connector/interval_util.py +26 -0
- snowflake/connector/local_storage_client.py +90 -0
- snowflake/connector/log_configuration.py +62 -0
- snowflake/connector/logging_utils/__init__.py +0 -0
- snowflake/connector/logging_utils/filters.py +72 -0
- snowflake/connector/minicore/__init__.py +0 -0
- snowflake/connector/minicore/aix_ppc64/libsf_mini_core.a +0 -0
- snowflake/connector/minicore/aix_ppc64/libsf_mini_core_static.a +0 -0
- snowflake/connector/minicore/linux_aarch64_glibc/libsf_mini_core.so +0 -0
- snowflake/connector/minicore/linux_aarch64_musl/libsf_mini_core.so +0 -0
- snowflake/connector/minicore/linux_x86_64_glibc/libsf_mini_core.so +0 -0
- snowflake/connector/minicore/linux_x86_64_musl/libsf_mini_core.so +0 -0
- snowflake/connector/minicore/macos_aarch64/libsf_mini_core.dylib +0 -0
- snowflake/connector/minicore/macos_x86_64/libsf_mini_core.dylib +0 -0
- snowflake/connector/minicore/windows_x86_64/sf_mini_core.dll +0 -0
- snowflake/connector/minicore/windows_x86_64/sf_mini_core_static.lib +0 -0
- snowflake/connector/nanoarrow_arrow_iterator.cp314-win_amd64.pyd +0 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +60 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +29 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +19 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +26 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +21 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +23 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +570 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +98 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +125 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +115 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +1140 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +138 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +47 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +46 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.cpp +83 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DecFloatConverter.hpp +35 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +97 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +72 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +73 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +28 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +30 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +35 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +17 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +23 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +45 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.cpp +75 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/IntervalConverter.hpp +57 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +209 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +75 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +30 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +46 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +29 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +8 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +95 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +57 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +36 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +34 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +48 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +19 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +26 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +36 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +31 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +346 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +145 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +14 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +67 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +68 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +101 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +127 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +45 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +1908 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +215 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +125 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +7 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +55 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +148 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +31 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +8 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +144 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +162 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +97 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +239 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +14 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +210 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +84 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +84 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +20 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +51 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +206 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +118 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +19 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +52 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +2 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +25 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +67 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +162 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +898 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +190 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +6 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +52 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +3204 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +3217 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +3618 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +379 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +262 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +512 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +350 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +33273 -0
- snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +397 -0
- snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +100 -0
- snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +49 -0
- snowflake/connector/network.py +1227 -0
- snowflake/connector/ocsp_asn1crypto.py +447 -0
- snowflake/connector/ocsp_snowflake.py +1939 -0
- snowflake/connector/options.py +179 -0
- snowflake/connector/os_details.py +88 -0
- snowflake/connector/pandas_tools.py +734 -0
- snowflake/connector/platform_detection.py +555 -0
- snowflake/connector/proxy.py +28 -0
- snowflake/connector/py.typed +0 -0
- snowflake/connector/result_batch.py +917 -0
- snowflake/connector/result_set.py +340 -0
- snowflake/connector/s3_storage_client.py +614 -0
- snowflake/connector/secret_detector.py +181 -0
- snowflake/connector/session_manager.py +650 -0
- snowflake/connector/sf_dirs.py +64 -0
- snowflake/connector/sfbinaryformat.py +35 -0
- snowflake/connector/sfdatetime.py +345 -0
- snowflake/connector/snow_logging.py +144 -0
- snowflake/connector/sqlstate.py +9 -0
- snowflake/connector/ssd_internal_keys.py +30 -0
- snowflake/connector/ssl_wrap_socket.py +281 -0
- snowflake/connector/storage_client.py +486 -0
- snowflake/connector/telemetry.py +254 -0
- snowflake/connector/telemetry_oob.py +544 -0
- snowflake/connector/test_util.py +30 -0
- snowflake/connector/time_util.py +159 -0
- snowflake/connector/token_cache.py +457 -0
- snowflake/connector/tool/__init__.py +0 -0
- snowflake/connector/tool/dump_certs.py +57 -0
- snowflake/connector/tool/dump_ocsp_response.py +139 -0
- snowflake/connector/tool/dump_ocsp_response_cache.py +194 -0
- snowflake/connector/tool/probe_connection.py +69 -0
- snowflake/connector/url_util.py +55 -0
- snowflake/connector/util_text.py +320 -0
- snowflake/connector/vendored/__init__.py +3 -0
- snowflake/connector/vendored/requests/LICENSE +175 -0
- snowflake/connector/vendored/requests/__init__.py +184 -0
- snowflake/connector/vendored/requests/__version__.py +14 -0
- snowflake/connector/vendored/requests/_internal_utils.py +50 -0
- snowflake/connector/vendored/requests/adapters.py +696 -0
- snowflake/connector/vendored/requests/api.py +157 -0
- snowflake/connector/vendored/requests/auth.py +314 -0
- snowflake/connector/vendored/requests/certs.py +17 -0
- snowflake/connector/vendored/requests/compat.py +106 -0
- snowflake/connector/vendored/requests/cookies.py +561 -0
- snowflake/connector/vendored/requests/exceptions.py +151 -0
- snowflake/connector/vendored/requests/help.py +134 -0
- snowflake/connector/vendored/requests/hooks.py +33 -0
- snowflake/connector/vendored/requests/models.py +1039 -0
- snowflake/connector/vendored/requests/packages.py +23 -0
- snowflake/connector/vendored/requests/sessions.py +831 -0
- snowflake/connector/vendored/requests/status_codes.py +128 -0
- snowflake/connector/vendored/requests/structures.py +99 -0
- snowflake/connector/vendored/requests/utils.py +1086 -0
- snowflake/connector/vendored/urllib3/LICENSE.txt +21 -0
- snowflake/connector/vendored/urllib3/__init__.py +211 -0
- snowflake/connector/vendored/urllib3/_base_connection.py +165 -0
- snowflake/connector/vendored/urllib3/_collections.py +487 -0
- snowflake/connector/vendored/urllib3/_request_methods.py +278 -0
- snowflake/connector/vendored/urllib3/_version.py +34 -0
- snowflake/connector/vendored/urllib3/connection.py +1108 -0
- snowflake/connector/vendored/urllib3/connectionpool.py +1178 -0
- snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/__init__.py +17 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/connection.py +260 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/emscripten_fetch_worker.js +110 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/fetch.py +726 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/request.py +22 -0
- snowflake/connector/vendored/urllib3/contrib/emscripten/response.py +277 -0
- snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +564 -0
- snowflake/connector/vendored/urllib3/contrib/socks.py +228 -0
- snowflake/connector/vendored/urllib3/exceptions.py +335 -0
- snowflake/connector/vendored/urllib3/fields.py +341 -0
- snowflake/connector/vendored/urllib3/filepost.py +89 -0
- snowflake/connector/vendored/urllib3/http2/__init__.py +53 -0
- snowflake/connector/vendored/urllib3/http2/connection.py +356 -0
- snowflake/connector/vendored/urllib3/http2/probe.py +87 -0
- snowflake/connector/vendored/urllib3/poolmanager.py +651 -0
- snowflake/connector/vendored/urllib3/py.typed +2 -0
- snowflake/connector/vendored/urllib3/response.py +1480 -0
- snowflake/connector/vendored/urllib3/util/__init__.py +42 -0
- snowflake/connector/vendored/urllib3/util/connection.py +137 -0
- snowflake/connector/vendored/urllib3/util/proxy.py +43 -0
- snowflake/connector/vendored/urllib3/util/request.py +263 -0
- snowflake/connector/vendored/urllib3/util/response.py +101 -0
- snowflake/connector/vendored/urllib3/util/retry.py +549 -0
- snowflake/connector/vendored/urllib3/util/ssl_.py +527 -0
- snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +159 -0
- snowflake/connector/vendored/urllib3/util/ssltransport.py +271 -0
- snowflake/connector/vendored/urllib3/util/timeout.py +275 -0
- snowflake/connector/vendored/urllib3/util/url.py +469 -0
- snowflake/connector/vendored/urllib3/util/util.py +42 -0
- snowflake/connector/vendored/urllib3/util/wait.py +124 -0
- snowflake/connector/version.py +3 -0
- snowflake/connector/wif_util.py +434 -0
- snowflake_connector_python-4.4.0.dist-info/DELVEWHEEL +2 -0
- snowflake_connector_python-4.4.0.dist-info/METADATA +1591 -0
- snowflake_connector_python-4.4.0.dist-info/RECORD +302 -0
- snowflake_connector_python-4.4.0.dist-info/WHEEL +5 -0
- snowflake_connector_python-4.4.0.dist-info/entry_points.txt +4 -0
- snowflake_connector_python-4.4.0.dist-info/licenses/LICENSE.txt +202 -0
- snowflake_connector_python-4.4.0.dist-info/licenses/NOTICE +8 -0
- snowflake_connector_python-4.4.0.dist-info/top_level.txt +1 -0
- snowflake_connector_python.libs/msvcp140-0f885b509a685d2bbfa652fed26b5fb3.dll +0 -0
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import datetime
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
import uuid
|
|
8
|
+
from collections import namedtuple
|
|
9
|
+
from queue import Queue
|
|
10
|
+
from threading import Lock
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from .compat import OK
|
|
14
|
+
from .description import CLIENT_NAME, SNOWFLAKE_CONNECTOR_VERSION
|
|
15
|
+
from .secret_detector import SecretDetector
|
|
16
|
+
from .telemetry import TelemetryField, generate_telemetry_data_dict
|
|
17
|
+
from .test_util import ENABLE_TELEMETRY_LOG, rt_plain_logger
|
|
18
|
+
from .vendored import requests
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
DEFAULT_BATCH_SIZE = 10
|
|
23
|
+
DEFAULT_NUM_OF_RETRY_TO_TRIGGER_TELEMETRY = 10
|
|
24
|
+
REQUEST_TIMEOUT = 3
|
|
25
|
+
|
|
26
|
+
TelemetryAPI = namedtuple("TelemetryAPI", ["url", "api_key"])
|
|
27
|
+
TelemetryServer = namedtuple("TelemetryServer", ["name", "url", "api_key"])
|
|
28
|
+
TelemetryEventBase = namedtuple(
|
|
29
|
+
"TelemetryEventBase", ["name", "tags", "urgent", "value"]
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TelemetryAPIEndpoint:
|
|
34
|
+
SFCTEST = TelemetryAPI(
|
|
35
|
+
url="https://sfctest.client-telemetry.snowflakecomputing.com/enqueue",
|
|
36
|
+
api_key="rRNY3EPNsB4U89XYuqsZKa7TSxb9QVX93yNM4tS6",
|
|
37
|
+
)
|
|
38
|
+
SFCDEV = TelemetryAPI(
|
|
39
|
+
url="https://sfcdev.client-telemetry.snowflakecomputing.com/enqueue",
|
|
40
|
+
api_key="kyTKLWpEZSaJnrzTZ63I96QXZHKsgfqbaGmAaIWf",
|
|
41
|
+
)
|
|
42
|
+
PROD = TelemetryAPI(
|
|
43
|
+
url="https://client-telemetry.snowflakecomputing.com/enqueue",
|
|
44
|
+
api_key="wLpEKqnLOW9tGNwTjab5N611YQApOb3t9xOnE1rX",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TelemetryServerDeployments:
|
|
49
|
+
DEV = TelemetryServer(
|
|
50
|
+
"dev", TelemetryAPIEndpoint.SFCTEST.url, TelemetryAPIEndpoint.SFCTEST.api_key
|
|
51
|
+
)
|
|
52
|
+
REG = TelemetryServer(
|
|
53
|
+
"reg", TelemetryAPIEndpoint.SFCTEST.url, TelemetryAPIEndpoint.SFCTEST.api_key
|
|
54
|
+
)
|
|
55
|
+
QA1 = TelemetryServer(
|
|
56
|
+
"qa1", TelemetryAPIEndpoint.SFCDEV.url, TelemetryAPIEndpoint.SFCDEV.api_key
|
|
57
|
+
)
|
|
58
|
+
PREPROD3 = TelemetryServer(
|
|
59
|
+
"preprod3", TelemetryAPIEndpoint.SFCDEV.url, TelemetryAPIEndpoint.SFCDEV.api_key
|
|
60
|
+
)
|
|
61
|
+
PROD = TelemetryServer(
|
|
62
|
+
"prod", TelemetryAPIEndpoint.PROD.url, TelemetryAPIEndpoint.PROD.api_key
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
ENABLED_DEPLOYMENTS = (
|
|
67
|
+
TelemetryServerDeployments.DEV.name,
|
|
68
|
+
TelemetryServerDeployments.REG.name,
|
|
69
|
+
TelemetryServerDeployments.QA1.name,
|
|
70
|
+
TelemetryServerDeployments.PREPROD3.name,
|
|
71
|
+
TelemetryServerDeployments.PROD.name,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class TelemetryEvent(TelemetryEventBase):
|
|
76
|
+
"""Base class for log and metric telemetry events.
|
|
77
|
+
|
|
78
|
+
This class has all of the logic except for the 'type' of the telemetry event.
|
|
79
|
+
That must be defined by the child class.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
def get_type(self):
|
|
83
|
+
"""Gets the telemetry event type."""
|
|
84
|
+
raise NotImplementedError
|
|
85
|
+
|
|
86
|
+
def to_dict(self):
|
|
87
|
+
"""Transform this event into a dictionary."""
|
|
88
|
+
event = dict()
|
|
89
|
+
event["Name"] = self.name
|
|
90
|
+
event["Urgent"] = self.urgent
|
|
91
|
+
event["Value"] = self.value
|
|
92
|
+
event["Tags"] = self.generate_tags()
|
|
93
|
+
event.update(
|
|
94
|
+
{
|
|
95
|
+
"UUID": str(uuid.uuid4()),
|
|
96
|
+
"Created_On": datetime.datetime.now(datetime.timezone.utc)
|
|
97
|
+
.replace(tzinfo=None)
|
|
98
|
+
.strftime("%Y-%m-%d %H:%M:%S"),
|
|
99
|
+
"Type": self.get_type(),
|
|
100
|
+
"SchemaVersion": 1,
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
return event
|
|
104
|
+
|
|
105
|
+
def get_deployment(self):
|
|
106
|
+
"""Gets the deployment field specified in tags if it exists."""
|
|
107
|
+
tags = self.tags
|
|
108
|
+
if tags:
|
|
109
|
+
for tag in tags:
|
|
110
|
+
if tag.get("Name", None) == "deployment":
|
|
111
|
+
return tag.get("Value")
|
|
112
|
+
|
|
113
|
+
return "Unknown"
|
|
114
|
+
|
|
115
|
+
def generate_tags(self):
|
|
116
|
+
"""Generates the tags to send as part of the telemetry event. Parts of the tags are user defined."""
|
|
117
|
+
tags = dict()
|
|
118
|
+
# Add in tags that were added to the event
|
|
119
|
+
if self.tags and len(self.tags) > 0:
|
|
120
|
+
for k, v in self.tags.items():
|
|
121
|
+
if v is not None:
|
|
122
|
+
tags[str(k).lower()] = str(v)
|
|
123
|
+
|
|
124
|
+
telemetry = TelemetryService.get_instance()
|
|
125
|
+
# Add telemetry service generated tags
|
|
126
|
+
tags[TelemetryField.KEY_OOB_DRIVER.value] = CLIENT_NAME
|
|
127
|
+
tags[TelemetryField.KEY_OOB_VERSION.value] = str(SNOWFLAKE_CONNECTOR_VERSION)
|
|
128
|
+
tags[TelemetryField.KEY_OOB_TELEMETRY_SERVER_DEPLOYMENT.value] = (
|
|
129
|
+
telemetry.deployment.name
|
|
130
|
+
)
|
|
131
|
+
tags[TelemetryField.KEY_OOB_CONNECTION_STRING.value] = (
|
|
132
|
+
telemetry.get_connection_string()
|
|
133
|
+
)
|
|
134
|
+
if telemetry.context and len(telemetry.context) > 0:
|
|
135
|
+
for k, v in telemetry.context.items():
|
|
136
|
+
if v is not None:
|
|
137
|
+
tags["ctx_" + str(k).lower()] = str(v)
|
|
138
|
+
|
|
139
|
+
return tags
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class TelemetryLogEvent(TelemetryEvent):
|
|
143
|
+
def get_type(self) -> str:
|
|
144
|
+
return "Log"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class TelemetryMetricEvent(TelemetryEvent):
|
|
148
|
+
def get_type(self) -> str:
|
|
149
|
+
return "Metric"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class TelemetryService:
|
|
153
|
+
__instance = None
|
|
154
|
+
# prevents race condition from multiple threads creating Snowflake connections
|
|
155
|
+
__lock_init = Lock()
|
|
156
|
+
|
|
157
|
+
@classmethod
|
|
158
|
+
def get_instance(cls) -> TelemetryService:
|
|
159
|
+
"""Static access method."""
|
|
160
|
+
with cls.__lock_init:
|
|
161
|
+
if cls.__instance is None:
|
|
162
|
+
cls()
|
|
163
|
+
return cls.__instance
|
|
164
|
+
|
|
165
|
+
def __init__(self) -> None:
|
|
166
|
+
"""Virtually private constructor."""
|
|
167
|
+
if TelemetryService.__instance is not None:
|
|
168
|
+
raise Exception("This class is a singleton!")
|
|
169
|
+
else:
|
|
170
|
+
TelemetryService.__instance = self
|
|
171
|
+
self._enabled = False
|
|
172
|
+
self._queue = Queue()
|
|
173
|
+
self.batch_size = DEFAULT_BATCH_SIZE
|
|
174
|
+
self.num_of_retry_to_trigger_telemetry = (
|
|
175
|
+
DEFAULT_NUM_OF_RETRY_TO_TRIGGER_TELEMETRY
|
|
176
|
+
)
|
|
177
|
+
self.context = dict()
|
|
178
|
+
self.connection_params = dict()
|
|
179
|
+
self.deployment = TelemetryServerDeployments.PROD
|
|
180
|
+
|
|
181
|
+
def __del__(self) -> None:
|
|
182
|
+
"""Tries to flush all events left in the queue. Ignores all exceptions."""
|
|
183
|
+
try:
|
|
184
|
+
self.close()
|
|
185
|
+
except Exception:
|
|
186
|
+
pass
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def enabled(self) -> bool:
|
|
190
|
+
"""Whether the Telemetry service is enabled or not."""
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
def enable(self) -> None:
|
|
194
|
+
"""Enable Telemetry Service."""
|
|
195
|
+
self._enabled = False
|
|
196
|
+
|
|
197
|
+
def disable(self) -> None:
|
|
198
|
+
"""Disable Telemetry Service."""
|
|
199
|
+
self._enabled = False
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def queue(self):
|
|
203
|
+
"""Get the queue that holds all of the telemetry events."""
|
|
204
|
+
return self._queue
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def context(self) -> dict[str, Any]:
|
|
208
|
+
"""Returns the context of the current connection."""
|
|
209
|
+
return self._context
|
|
210
|
+
|
|
211
|
+
@context.setter
|
|
212
|
+
def context(self, value) -> None:
|
|
213
|
+
"""Sets the context of the current connection."""
|
|
214
|
+
self._context = value
|
|
215
|
+
|
|
216
|
+
@property
|
|
217
|
+
def connection_params(self) -> dict[str, Any]:
|
|
218
|
+
"""Returns the connection parameters from the current connection."""
|
|
219
|
+
return self._connection_params
|
|
220
|
+
|
|
221
|
+
@connection_params.setter
|
|
222
|
+
def connection_params(self, value) -> None:
|
|
223
|
+
"""Sets the connection parameters from the current connection."""
|
|
224
|
+
self._connection_params = value
|
|
225
|
+
|
|
226
|
+
@property
|
|
227
|
+
def batch_size(self):
|
|
228
|
+
"""Returns the batch size for uploading results."""
|
|
229
|
+
return self._batch_size
|
|
230
|
+
|
|
231
|
+
@batch_size.setter
|
|
232
|
+
def batch_size(self, value) -> None:
|
|
233
|
+
"""Sets the batch size for uploading results."""
|
|
234
|
+
self._batch_size = value
|
|
235
|
+
|
|
236
|
+
@property
|
|
237
|
+
def num_of_retry_to_trigger_telemetry(self) -> int:
|
|
238
|
+
"""Returns the number of HTTP retries before we submit a telemetry event."""
|
|
239
|
+
return self._num_of_retry_to_trigger_telemetry
|
|
240
|
+
|
|
241
|
+
@num_of_retry_to_trigger_telemetry.setter
|
|
242
|
+
def num_of_retry_to_trigger_telemetry(self, value) -> None:
|
|
243
|
+
"""Sets the number of HTTP retries before we submit a telemetry event."""
|
|
244
|
+
self._num_of_retry_to_trigger_telemetry = value
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def deployment(self: TelemetryServer) -> Any | None:
|
|
248
|
+
"""Returns the deployment that we are sending the telemetry information to."""
|
|
249
|
+
return self._deployment
|
|
250
|
+
|
|
251
|
+
@deployment.setter
|
|
252
|
+
def deployment(self, value) -> None:
|
|
253
|
+
"""Sets the deployment that we are sending the telemetry information to."""
|
|
254
|
+
self._deployment = value
|
|
255
|
+
|
|
256
|
+
def is_deployment_enabled(self) -> bool:
|
|
257
|
+
"""Returns whether or not this deployment is enabled."""
|
|
258
|
+
return self.deployment.name in ENABLED_DEPLOYMENTS
|
|
259
|
+
|
|
260
|
+
def get_connection_string(self):
|
|
261
|
+
"""Returns the URL used to connect to Snowflake."""
|
|
262
|
+
return (
|
|
263
|
+
self.connection_params.get("protocol", "")
|
|
264
|
+
+ "://"
|
|
265
|
+
+ self.connection_params.get("host", "")
|
|
266
|
+
+ ":"
|
|
267
|
+
+ str(self.connection_params.get("port", ""))
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
def add(self, event) -> None:
|
|
271
|
+
"""Adds a telemetry event to the queue. If the event is urgent, upload all telemetry events right away."""
|
|
272
|
+
if not self.enabled:
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
self.queue.put(event)
|
|
276
|
+
if self.queue.qsize() > self.batch_size or event.urgent:
|
|
277
|
+
payload = self.export_queue_to_string()
|
|
278
|
+
if payload is None:
|
|
279
|
+
return
|
|
280
|
+
self._upload_payload(payload)
|
|
281
|
+
|
|
282
|
+
def flush(self) -> None:
|
|
283
|
+
"""Flushes all telemetry events in the queue and submit them to the back-end."""
|
|
284
|
+
if not self.enabled:
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
if not self.queue.empty():
|
|
288
|
+
payload = self.export_queue_to_string()
|
|
289
|
+
if payload is None:
|
|
290
|
+
return
|
|
291
|
+
self._upload_payload(payload)
|
|
292
|
+
|
|
293
|
+
def update_context(self, connection_params) -> None:
|
|
294
|
+
"""Updates the telemetry service context. Remove any passwords or credentials."""
|
|
295
|
+
self.configure_deployment(connection_params)
|
|
296
|
+
self.context = dict()
|
|
297
|
+
|
|
298
|
+
for key, value in connection_params.items():
|
|
299
|
+
if (
|
|
300
|
+
"password" not in key
|
|
301
|
+
and "passcode" not in key
|
|
302
|
+
and "privateKey" not in key
|
|
303
|
+
):
|
|
304
|
+
self.context[key] = value
|
|
305
|
+
|
|
306
|
+
def configure_deployment(self, connection_params) -> None:
|
|
307
|
+
"""Determines which deployment we are sending Telemetry OOB messages to."""
|
|
308
|
+
self.connection_params = connection_params
|
|
309
|
+
account = (
|
|
310
|
+
self.connection_params.get("account")
|
|
311
|
+
if self.connection_params.get("account")
|
|
312
|
+
else ""
|
|
313
|
+
)
|
|
314
|
+
host = (
|
|
315
|
+
self.connection_params.get("host")
|
|
316
|
+
if self.connection_params.get("host")
|
|
317
|
+
else ""
|
|
318
|
+
)
|
|
319
|
+
port = self.connection_params.get("port", None)
|
|
320
|
+
|
|
321
|
+
# Set as PROD by default
|
|
322
|
+
deployment = TelemetryServerDeployments.PROD
|
|
323
|
+
if "reg" in host or "local" in host:
|
|
324
|
+
deployment = TelemetryServerDeployments.REG
|
|
325
|
+
if port == 8080:
|
|
326
|
+
deployment = TelemetryServerDeployments.DEV
|
|
327
|
+
elif "qa1" in host or "qa1" in account:
|
|
328
|
+
deployment = TelemetryServerDeployments.QA1
|
|
329
|
+
elif "preprod3" in host:
|
|
330
|
+
deployment = TelemetryServerDeployments.PREPROD3
|
|
331
|
+
|
|
332
|
+
self.deployment = deployment
|
|
333
|
+
|
|
334
|
+
def log_ocsp_exception(
|
|
335
|
+
self,
|
|
336
|
+
event_type,
|
|
337
|
+
telemetry_data,
|
|
338
|
+
exception=None,
|
|
339
|
+
stack_trace=None,
|
|
340
|
+
tags=None,
|
|
341
|
+
urgent: bool = False,
|
|
342
|
+
) -> None:
|
|
343
|
+
"""Logs an OCSP Exception and adds it to the queue to be uploaded."""
|
|
344
|
+
if tags is None:
|
|
345
|
+
tags = dict()
|
|
346
|
+
try:
|
|
347
|
+
if self.enabled:
|
|
348
|
+
event_name = "OCSPException"
|
|
349
|
+
if exception is not None:
|
|
350
|
+
telemetry_data[TelemetryField.KEY_OOB_EXCEPTION_MESSAGE.value] = (
|
|
351
|
+
str(exception)
|
|
352
|
+
)
|
|
353
|
+
if stack_trace is not None:
|
|
354
|
+
telemetry_data[
|
|
355
|
+
TelemetryField.KEY_OOB_EXCEPTION_STACK_TRACE.value
|
|
356
|
+
] = stack_trace
|
|
357
|
+
|
|
358
|
+
if tags is None:
|
|
359
|
+
tags = dict()
|
|
360
|
+
|
|
361
|
+
tags[TelemetryField.KEY_OOB_EVENT_TYPE.value] = event_type
|
|
362
|
+
|
|
363
|
+
log_event = TelemetryLogEvent(
|
|
364
|
+
name=event_name, tags=tags, urgent=urgent, value=telemetry_data
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
self.add(log_event)
|
|
368
|
+
except Exception:
|
|
369
|
+
# Do nothing on exception, just log
|
|
370
|
+
logger.debug("Failed to log OCSP exception", exc_info=True)
|
|
371
|
+
|
|
372
|
+
def log_http_request_error(
|
|
373
|
+
self,
|
|
374
|
+
event_name,
|
|
375
|
+
url,
|
|
376
|
+
method,
|
|
377
|
+
sqlstate,
|
|
378
|
+
errno,
|
|
379
|
+
response=None,
|
|
380
|
+
retry_timeout=None,
|
|
381
|
+
retry_count=None,
|
|
382
|
+
exception=None,
|
|
383
|
+
stack_trace=None,
|
|
384
|
+
tags=None,
|
|
385
|
+
urgent: bool = False,
|
|
386
|
+
) -> None:
|
|
387
|
+
"""Logs an HTTP Request error and adds it to the queue to be uploaded."""
|
|
388
|
+
if tags is None:
|
|
389
|
+
tags = dict()
|
|
390
|
+
try:
|
|
391
|
+
if self.enabled:
|
|
392
|
+
response_status_code = -1
|
|
393
|
+
# This mimics the output of HttpRequestBase.toString() from JBDC
|
|
394
|
+
telemetry_data = generate_telemetry_data_dict(
|
|
395
|
+
from_dict={
|
|
396
|
+
TelemetryField.KEY_OOB_REQUEST.value: f"{method} {url}",
|
|
397
|
+
TelemetryField.KEY_OOB_SQL_STATE.value: sqlstate,
|
|
398
|
+
TelemetryField.KEY_OOB_ERROR_CODE.value: errno,
|
|
399
|
+
},
|
|
400
|
+
is_oob_telemetry=True,
|
|
401
|
+
)
|
|
402
|
+
if response:
|
|
403
|
+
telemetry_data[TelemetryField.KEY_OOB_RESPONSE.value] = (
|
|
404
|
+
response.json()
|
|
405
|
+
)
|
|
406
|
+
telemetry_data[
|
|
407
|
+
TelemetryField.KEY_OOB_RESPONSE_STATUS_LINE.value
|
|
408
|
+
] = str(response.reason)
|
|
409
|
+
if response.status_code:
|
|
410
|
+
response_status_code = str(response.status_code)
|
|
411
|
+
telemetry_data[
|
|
412
|
+
TelemetryField.KEY_OOB_RESPONSE_STATUS_CODE.value
|
|
413
|
+
] = response_status_code
|
|
414
|
+
if retry_timeout:
|
|
415
|
+
telemetry_data[TelemetryField.KEY_OOB_RETRY_TIMEOUT.value] = str(
|
|
416
|
+
retry_timeout
|
|
417
|
+
)
|
|
418
|
+
if retry_count:
|
|
419
|
+
telemetry_data[TelemetryField.KEY_OOB_RETRY_COUNT.value] = str(
|
|
420
|
+
retry_count
|
|
421
|
+
)
|
|
422
|
+
if exception:
|
|
423
|
+
telemetry_data[TelemetryField.KEY_OOB_EXCEPTION_MESSAGE.value] = (
|
|
424
|
+
str(exception)
|
|
425
|
+
)
|
|
426
|
+
if stack_trace:
|
|
427
|
+
telemetry_data[
|
|
428
|
+
TelemetryField.KEY_OOB_EXCEPTION_STACK_TRACE.value
|
|
429
|
+
] = stack_trace
|
|
430
|
+
|
|
431
|
+
if tags is None:
|
|
432
|
+
tags = dict()
|
|
433
|
+
|
|
434
|
+
tags[TelemetryField.KEY_OOB_RESPONSE_STATUS_CODE.value] = (
|
|
435
|
+
response_status_code
|
|
436
|
+
)
|
|
437
|
+
tags[TelemetryField.KEY_OOB_SQL_STATE.value] = str(sqlstate)
|
|
438
|
+
tags[TelemetryField.KEY_OOB_ERROR_CODE.value] = errno
|
|
439
|
+
|
|
440
|
+
log_event = TelemetryLogEvent(
|
|
441
|
+
name=event_name, tags=tags, value=telemetry_data, urgent=urgent
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
self.add(log_event)
|
|
445
|
+
except Exception:
|
|
446
|
+
# Do nothing on exception, just log
|
|
447
|
+
logger.debug("Failed to log HTTP request error", exc_info=True)
|
|
448
|
+
|
|
449
|
+
def log_general_exception(
|
|
450
|
+
self,
|
|
451
|
+
event_name: str,
|
|
452
|
+
telemetry_data: dict,
|
|
453
|
+
tags: dict | None = None,
|
|
454
|
+
urgent: bool | None = False,
|
|
455
|
+
) -> None:
|
|
456
|
+
"""Sends any type of exception through OOB telemetry."""
|
|
457
|
+
if tags is None:
|
|
458
|
+
tags = dict()
|
|
459
|
+
try:
|
|
460
|
+
if self.enabled:
|
|
461
|
+
log_event = TelemetryLogEvent(
|
|
462
|
+
name=event_name, tags=tags, value=telemetry_data, urgent=urgent
|
|
463
|
+
)
|
|
464
|
+
self.add(log_event)
|
|
465
|
+
except Exception:
|
|
466
|
+
# Do nothing on exception, just log
|
|
467
|
+
logger.debug("Failed to log general exception", exc_info=True)
|
|
468
|
+
|
|
469
|
+
def _upload_payload(self, payload) -> None:
|
|
470
|
+
"""Uploads the JSON-formatted string payload to the telemetry backend.
|
|
471
|
+
|
|
472
|
+
Ignore any exceptions that may arise.
|
|
473
|
+
"""
|
|
474
|
+
success = True
|
|
475
|
+
response = None
|
|
476
|
+
try:
|
|
477
|
+
if not self.is_deployment_enabled():
|
|
478
|
+
logger.debug("Skip the disabled deployment: %s", self.deployment.name)
|
|
479
|
+
return
|
|
480
|
+
logger.debug(f"Sending OOB telemetry data. Payload: {payload}")
|
|
481
|
+
if ENABLE_TELEMETRY_LOG:
|
|
482
|
+
# This logger guarantees the payload won't be masked. Testing purpose.
|
|
483
|
+
rt_plain_logger.debug(f"OOB telemetry data being sent is {payload}")
|
|
484
|
+
|
|
485
|
+
# TODO(SNOW-2259522): Telemetry OOB is currently disabled. If Telemetry OOB is to be re-enabled, this HTTP call must be routed through the connection_argument.session_manager.use_session(use_pooling) (so the SessionManager instance attached to the connection which initialization's fail most likely triggered this telemetry log). It would allow to pick up proxy configuration & custom headers (see tickets SNOW-694457 and SNOW-2203079).
|
|
486
|
+
with requests.Session() as session:
|
|
487
|
+
headers = {
|
|
488
|
+
"Content-type": "application/json",
|
|
489
|
+
"x-api-key": self.deployment.api_key,
|
|
490
|
+
}
|
|
491
|
+
response = session.post(
|
|
492
|
+
self.deployment.url,
|
|
493
|
+
data=payload,
|
|
494
|
+
headers=headers,
|
|
495
|
+
timeout=REQUEST_TIMEOUT,
|
|
496
|
+
)
|
|
497
|
+
if (
|
|
498
|
+
response.status_code == OK
|
|
499
|
+
and json.loads(response.text).get("statusCode", 0) == OK
|
|
500
|
+
):
|
|
501
|
+
logger.debug(
|
|
502
|
+
"telemetry server request success: %d", response.status_code
|
|
503
|
+
)
|
|
504
|
+
else:
|
|
505
|
+
logger.debug(
|
|
506
|
+
"telemetry server request error: %d", response.status_code
|
|
507
|
+
)
|
|
508
|
+
success = False
|
|
509
|
+
except Exception as e:
|
|
510
|
+
logger.debug(
|
|
511
|
+
"Telemetry request failed, Exception response: %s, exception: %s",
|
|
512
|
+
response,
|
|
513
|
+
str(e),
|
|
514
|
+
)
|
|
515
|
+
success = False
|
|
516
|
+
finally:
|
|
517
|
+
logger.debug("Telemetry request success=%s", success)
|
|
518
|
+
|
|
519
|
+
def export_queue_to_string(self):
|
|
520
|
+
"""Exports all events in the queue into a JSON formatted string with secrets masked."""
|
|
521
|
+
logs = list()
|
|
522
|
+
while not self._queue.empty():
|
|
523
|
+
logs.append(self._queue.get().to_dict())
|
|
524
|
+
# We may get an exception trying to serialize a python object to JSON
|
|
525
|
+
try:
|
|
526
|
+
payload = json.dumps(logs)
|
|
527
|
+
except Exception:
|
|
528
|
+
logger.debug(
|
|
529
|
+
"Failed to generate a JSON dump from the passed in telemetry OOB events. String representation of logs: %s"
|
|
530
|
+
% str(logs),
|
|
531
|
+
exc_info=True,
|
|
532
|
+
)
|
|
533
|
+
payload = None
|
|
534
|
+
_, masked_text, _ = SecretDetector.mask_secrets(payload)
|
|
535
|
+
return masked_text
|
|
536
|
+
|
|
537
|
+
def close(self) -> None:
|
|
538
|
+
"""Closes the telemetry service."""
|
|
539
|
+
self.flush()
|
|
540
|
+
self.disable()
|
|
541
|
+
|
|
542
|
+
def size(self):
|
|
543
|
+
"""Returns the size of the queue."""
|
|
544
|
+
return self.queue.qsize()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import platform
|
|
7
|
+
from typing import cast
|
|
8
|
+
|
|
9
|
+
IS_LINUX = platform.system() == "Linux"
|
|
10
|
+
RUNNING_ON_JENKINS = os.getenv("JENKINS_HOME") is not None
|
|
11
|
+
REGRESSION_TEST_LOG_DIR = os.getenv("CLIENT_LOG_DIR_PATH_DOCKER")
|
|
12
|
+
ENABLE_TELEMETRY_LOG = RUNNING_ON_JENKINS and REGRESSION_TEST_LOG_DIR and IS_LINUX
|
|
13
|
+
rt_plain_logger = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if ENABLE_TELEMETRY_LOG:
|
|
17
|
+
rt_plain_logger = logging.getLogger("regression.test.plain.logger")
|
|
18
|
+
rt_plain_logger.setLevel(logging.DEBUG)
|
|
19
|
+
ch = logging.FileHandler(
|
|
20
|
+
os.path.join(
|
|
21
|
+
cast(str, REGRESSION_TEST_LOG_DIR), "snowflake_ssm_rt_telemetry.log"
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
ch.setLevel(logging.DEBUG)
|
|
25
|
+
ch.setFormatter(
|
|
26
|
+
logging.Formatter(
|
|
27
|
+
"%(asctime)s - %(threadName)s %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s - %(message)s"
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
rt_plain_logger.addHandler(ch)
|