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

View File

@@ -9,7 +9,7 @@ from loguru import logger
from httprunner import __description__, __version__
from httprunner.compat import ensure_cli_args
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()
@@ -22,7 +22,7 @@ def init_parser_run(subparsers):
def main_run(extra_args) -> enum.IntEnum:
ga_client.track_event("RunAPITests", "hrun")
ga4_client.send_event("hrun")
# keep compatibility with v2
extra_args = ensure_cli_args(extra_args)

View File

@@ -22,7 +22,7 @@ from httprunner.loader import (
load_testcase,
)
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
"""
@@ -541,7 +541,7 @@ def main_make(tests_paths: List[Text]) -> List[Text]:
if not tests_paths:
return []
ga_client.track_event("ConvertTests", "hmake")
ga4_client.send_event("hmake")
for tests_path in tests_paths:
tests_path = ensure_path_sep(tests_path)

View File

@@ -27,7 +27,7 @@ from httprunner.models import (
VariablesMapping,
)
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):
@@ -210,6 +210,7 @@ class SessionRunner(object):
def test_start(self, param: Dict = None) -> "SessionRunner":
"""main entrance, discovered by pytest"""
ga4_client.send_event("test_start")
print("\n")
self.__init()
self.__parse_config(param)

View File

@@ -5,7 +5,9 @@ import json
import os
import os.path
import platform
import random
import sys
import time
import uuid
from multiprocessing import Queue
from typing import Any, Dict, List, Text
@@ -18,6 +20,16 @@ from httprunner import __version__, exceptions
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():
if os.getenv("DISABLE_SENTRY") == "true":
return
@@ -30,8 +42,78 @@ def init_sentry_sdk():
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
report_url = "https://www.google-analytics.com/collect"
report_debug_url = (
@@ -219,16 +301,6 @@ def omit_long_data(body, omit_len=512):
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 get_index_from_list(lst: List, item: Any):
try:

View File

@@ -7,7 +7,7 @@ from pathlib import Path
import toml
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):
@@ -160,3 +160,12 @@ class TestUtils(unittest.TestCase):
pyproject = toml.loads(open(str(path)).read())
pyproject_version = pyproject["tool"]["poetry"]["version"]
self.assertEqual(pyproject_version, __version__)
def test_ga4_send_event(self):
ga4_client.send_event(
"httprunner_debug_event",
{
"a": 123,
"b": 456,
},
)