mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-03 06:49:38 +08:00
feat: send events to Google Analytics 4 in python version
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user