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