feat: send events to Google Analytics 4 in python version

This commit is contained in:
lilong.129
2023-07-21 19:29:34 +08:00
parent 2c280a6bf4
commit ab0b7e14c8
5 changed files with 99 additions and 17 deletions
+2 -2
View File
@@ -9,7 +9,7 @@ from loguru import logger
from httprunner import __description__, __version__ from httprunner import __description__, __version__
from httprunner.compat import ensure_cli_args from httprunner.compat import ensure_cli_args
from httprunner.make import init_make_parser, main_make from httprunner.make import init_make_parser, main_make
from httprunner.utils import ga_client, init_logger, init_sentry_sdk from httprunner.utils import ga4_client, init_logger, init_sentry_sdk
init_sentry_sdk() init_sentry_sdk()
@@ -22,7 +22,7 @@ def init_parser_run(subparsers):
def main_run(extra_args) -> enum.IntEnum: def main_run(extra_args) -> enum.IntEnum:
ga_client.track_event("RunAPITests", "hrun") ga4_client.send_event("hrun")
# keep compatibility with v2 # keep compatibility with v2
extra_args = ensure_cli_args(extra_args) extra_args = ensure_cli_args(extra_args)
+2 -2
View File
@@ -22,7 +22,7 @@ from httprunner.loader import (
load_testcase, load_testcase,
) )
from httprunner.response import uniform_validator from httprunner.response import uniform_validator
from httprunner.utils import ga_client, is_support_multiprocessing from httprunner.utils import ga4_client, is_support_multiprocessing
""" cache converted pytest files, avoid duplicate making """ cache converted pytest files, avoid duplicate making
""" """
@@ -541,7 +541,7 @@ def main_make(tests_paths: List[Text]) -> List[Text]:
if not tests_paths: if not tests_paths:
return [] return []
ga_client.track_event("ConvertTests", "hmake") ga4_client.send_event("hmake")
for tests_path in tests_paths: for tests_path in tests_paths:
tests_path = ensure_path_sep(tests_path) tests_path = ensure_path_sep(tests_path)
+2 -1
View File
@@ -27,7 +27,7 @@ from httprunner.models import (
VariablesMapping, VariablesMapping,
) )
from httprunner.parser import Parser from httprunner.parser import Parser
from httprunner.utils import LOGGER_FORMAT, merge_variables from httprunner.utils import LOGGER_FORMAT, merge_variables, ga4_client
class SessionRunner(object): class SessionRunner(object):
@@ -210,6 +210,7 @@ class SessionRunner(object):
def test_start(self, param: Dict = None) -> "SessionRunner": def test_start(self, param: Dict = None) -> "SessionRunner":
"""main entrance, discovered by pytest""" """main entrance, discovered by pytest"""
ga4_client.send_event("test_start")
print("\n") print("\n")
self.__init() self.__init()
self.__parse_config(param) self.__parse_config(param)
+83 -11
View File
@@ -5,7 +5,9 @@ import json
import os import os
import os.path import os.path
import platform import platform
import random
import sys import sys
import time
import uuid import uuid
from multiprocessing import Queue from multiprocessing import Queue
from typing import Any, Dict, List, Text from typing import Any, Dict, List, Text
@@ -18,6 +20,16 @@ from httprunner import __version__, exceptions
from httprunner.models import VariablesMapping from httprunner.models import VariablesMapping
def get_platform():
return {
"httprunner_version": __version__,
"python_version": "{} {}".format(
platform.python_implementation(), platform.python_version()
),
"platform": platform.platform(),
}
def init_sentry_sdk(): def init_sentry_sdk():
if os.getenv("DISABLE_SENTRY") == "true": if os.getenv("DISABLE_SENTRY") == "true":
return return
@@ -30,8 +42,78 @@ def init_sentry_sdk():
scope.set_user({"id": uuid.getnode()}) scope.set_user({"id": uuid.getnode()})
class GAClient(object): class GA4Client(object):
def __init__(
self, measurement_id: str, api_secret: str, debug: bool = False
) -> None:
self.http_client = requests.Session()
self.debug = debug
if debug:
uri = "https://www.google-analytics.com/debug/mp/collect"
else:
uri = "https://www.google-analytics.com/mp/collect"
self.uri = f"{uri}?measurement_id={measurement_id}&api_secret={api_secret}"
self.user_id = str(uuid.getnode())
self.common_event_params = get_platform()
# do not send GA events in CI environment
self.__is_ci = os.getenv("DISABLE_GA") == "true"
def send_event(self, name: str, event_params: dict = None) -> None:
if self.__is_ci:
return
event_params = event_params or {}
event_params.update(self.common_event_params)
event = {
"name": name,
"params": event_params,
}
payload = {
"client_id": f"{random.randint(-2147483648, 2147483647)}.{int(time.time())}",
"user_id": self.user_id,
"timestamp_micros": int(time.time() * 10**6),
"events": [event],
}
if self.debug:
logger.debug(f"send GA4 event, uri: {self.uri}, payload: {payload}")
try:
resp = self.http_client.post(self.uri, json=payload, timeout=5)
except Exception as err: # ProxyError, SSLError, ConnectionError
logger.error(f"request GA4 failed, error: {err}")
return
if resp.status_code >= 300:
logger.error(
f"validation response got unexpected status: {resp.status_code}"
)
return
if not self.debug:
return
try:
resp_body = resp.json()
logger.debug(
"get GA4 validation response, "
f"status code: {resp.status_code}, body: {resp_body}"
)
except Exception:
pass
GA4_MEASUREMENT_ID = "G-9KHR3VC2LN"
GA4_API_SECRET = "w7lKNQIrQsKNS4ikgMPp0Q"
ga4_client = GA4Client(GA4_MEASUREMENT_ID, GA4_API_SECRET, False)
class GAClient(object):
version = "1" # GA API Version version = "1" # GA API Version
report_url = "https://www.google-analytics.com/collect" report_url = "https://www.google-analytics.com/collect"
report_debug_url = ( report_debug_url = (
@@ -219,16 +301,6 @@ def omit_long_data(body, omit_len=512):
return omitted_body + appendix_str return omitted_body + appendix_str
def get_platform():
return {
"httprunner_version": __version__,
"python_version": "{} {}".format(
platform.python_implementation(), platform.python_version()
),
"platform": platform.platform(),
}
def sort_dict_by_custom_order(raw_dict: Dict, custom_order: List): def sort_dict_by_custom_order(raw_dict: Dict, custom_order: List):
def get_index_from_list(lst: List, item: Any): def get_index_from_list(lst: List, item: Any):
try: try:
+10 -1
View File
@@ -7,7 +7,7 @@ from pathlib import Path
import toml import toml
from httprunner import __version__, loader, utils from httprunner import __version__, loader, utils
from httprunner.utils import ExtendJSONEncoder, merge_variables from httprunner.utils import ExtendJSONEncoder, merge_variables, ga4_client
class TestUtils(unittest.TestCase): class TestUtils(unittest.TestCase):
@@ -160,3 +160,12 @@ class TestUtils(unittest.TestCase):
pyproject = toml.loads(open(str(path)).read()) pyproject = toml.loads(open(str(path)).read())
pyproject_version = pyproject["tool"]["poetry"]["version"] pyproject_version = pyproject["tool"]["poetry"]["version"]
self.assertEqual(pyproject_version, __version__) self.assertEqual(pyproject_version, __version__)
def test_ga4_send_event(self):
ga4_client.send_event(
"httprunner_debug_event",
{
"a": 123,
"b": 456,
},
)