Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add telemetry #584

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .github/workflows/build_assets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
- distro: "python:3.11-bullseye"
arch: arm64
distro_name: linux

steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -127,6 +127,3 @@ jobs:
asset_name: codecovcli_${{ matrix.distro_name }}_${{ matrix.arch }}
tag: ${{ github.ref }}
overwrite: true



2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ jobs:
fail-fast: false
matrix:
include:
- python-version: "3.13"
- python-version: "3.12"
- python-version: "3.11"
- python-version: "3.10"
- python-version: "3.9"
- python-version: "3.8"
steps:
- uses: actions/checkout@v4
with:
Expand Down
215 changes: 110 additions & 105 deletions codecov_cli/commands/upload_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@
import typing

import click
from opentelemetry import trace

from codecov_cli.commands.commit import create_commit
from codecov_cli.commands.report import create_report
from codecov_cli.commands.upload import do_upload, global_upload_options
from codecov_cli.helpers.args import get_cli_args
from codecov_cli.helpers.options import global_options
from codecov_cli.opentelemetry import close_telem
from codecov_cli.services.upload_coverage import upload_coverage_logic
from codecov_cli.types import CommandContext

logger = logging.getLogger("codecovcli")
tracer = trace.get_tracer(__name__)


# These options are the combined options of commit, report and upload commands
Expand Down Expand Up @@ -60,116 +63,118 @@ def upload_coverage(
token: typing.Optional[str],
use_legacy_uploader: bool,
):
args = get_cli_args(ctx)
logger.debug(
"Starting upload coverage",
extra=dict(
extra_log_attributes=args,
),
)

if not use_legacy_uploader and report_type == "coverage":
versioning_system = ctx.obj["versioning_system"]
codecov_yaml = ctx.obj["codecov_yaml"] or {}
cli_config = codecov_yaml.get("cli", {})
ci_adapter = ctx.obj.get("ci_adapter")
enterprise_url = ctx.obj.get("enterprise_url")
with tracer.start_as_current_span("upload_coverage"):
args = get_cli_args(ctx)
ctx.invoke(
upload_coverage_logic,
cli_config,
versioning_system,
ci_adapter,
branch=branch,
build_code=build_code,
build_url=build_url,
commit_sha=commit_sha,
disable_file_fixes=disable_file_fixes,
disable_search=disable_search,
dry_run=dry_run,
enterprise_url=enterprise_url,
env_vars=env_vars,
fail_on_error=fail_on_error,
files_search_exclude_folders=files_search_exclude_folders,
files_search_explicitly_listed_files=files_search_explicitly_listed_files,
files_search_root_folder=files_search_root_folder,
flags=flags,
gcov_args=gcov_args,
gcov_executable=gcov_executable,
gcov_ignore=gcov_ignore,
gcov_include=gcov_include,
git_service=git_service,
handle_no_reports_found=handle_no_reports_found,
job_code=job_code,
name=name,
network_filter=network_filter,
network_prefix=network_prefix,
network_root_folder=network_root_folder,
parent_sha=parent_sha,
plugin_names=plugin_names,
pull_request_number=pull_request_number,
report_code=report_code,
slug=slug,
swift_project=swift_project,
token=token,
upload_file_type=report_type,
use_legacy_uploader=use_legacy_uploader,
args=args,
)
else:
ctx.invoke(
create_commit,
commit_sha=commit_sha,
parent_sha=parent_sha,
pull_request_number=pull_request_number,
branch=branch,
slug=slug,
token=token,
git_service=git_service,
fail_on_error=True,
logger.debug(
"Starting upload coverage",
extra=dict(
extra_log_attributes=args,
),
)
if report_type == "coverage":

if not use_legacy_uploader and report_type == "coverage":
versioning_system = ctx.obj["versioning_system"]
codecov_yaml = ctx.obj["codecov_yaml"] or {}
cli_config = codecov_yaml.get("cli", {})
ci_adapter = ctx.obj.get("ci_adapter")
enterprise_url = ctx.obj.get("enterprise_url")
args = get_cli_args(ctx)
ctx.invoke(
create_report,
upload_coverage_logic,
cli_config,
versioning_system,
ci_adapter,
branch=branch,
build_code=build_code,
build_url=build_url,
commit_sha=commit_sha,
disable_file_fixes=disable_file_fixes,
disable_search=disable_search,
dry_run=dry_run,
enterprise_url=enterprise_url,
env_vars=env_vars,
fail_on_error=fail_on_error,
files_search_exclude_folders=files_search_exclude_folders,
files_search_explicitly_listed_files=files_search_explicitly_listed_files,
files_search_root_folder=files_search_root_folder,
flags=flags,
gcov_args=gcov_args,
gcov_executable=gcov_executable,
gcov_ignore=gcov_ignore,
gcov_include=gcov_include,
git_service=git_service,
handle_no_reports_found=handle_no_reports_found,
job_code=job_code,
name=name,
network_filter=network_filter,
network_prefix=network_prefix,
network_root_folder=network_root_folder,
parent_sha=parent_sha,
plugin_names=plugin_names,
pull_request_number=pull_request_number,
report_code=report_code,
slug=slug,
swift_project=swift_project,
token=token,
code=report_code,
fail_on_error=True,
upload_file_type=report_type,
use_legacy_uploader=use_legacy_uploader,
args=args,
)
else:
ctx.invoke(
create_commit,
commit_sha=commit_sha,
parent_sha=parent_sha,
pull_request_number=pull_request_number,
branch=branch,
slug=slug,
token=token,
git_service=git_service,
fail_on_error=True,
)
ctx.invoke(
do_upload,
branch=branch,
build_code=build_code,
build_url=build_url,
commit_sha=commit_sha,
disable_file_fixes=disable_file_fixes,
disable_search=disable_search,
dry_run=dry_run,
env_vars=env_vars,
fail_on_error=fail_on_error,
files_search_exclude_folders=files_search_exclude_folders,
files_search_explicitly_listed_files=files_search_explicitly_listed_files,
files_search_root_folder=files_search_root_folder,
flags=flags,
gcov_args=gcov_args,
gcov_executable=gcov_executable,
gcov_ignore=gcov_ignore,
gcov_include=gcov_include,
git_service=git_service,
handle_no_reports_found=handle_no_reports_found,
job_code=job_code,
name=name,
network_filter=network_filter,
network_prefix=network_prefix,
network_root_folder=network_root_folder,
plugin_names=plugin_names,
pull_request_number=pull_request_number,
report_code=report_code,
report_type=report_type,
slug=slug,
swift_project=swift_project,
token=token,
use_legacy_uploader=use_legacy_uploader,
)
if report_type == "coverage":
ctx.invoke(
create_report,
token=token,
code=report_code,
fail_on_error=True,
commit_sha=commit_sha,
slug=slug,
git_service=git_service,
)
ctx.invoke(
do_upload,
branch=branch,
build_code=build_code,
build_url=build_url,
commit_sha=commit_sha,
disable_file_fixes=disable_file_fixes,
disable_search=disable_search,
dry_run=dry_run,
env_vars=env_vars,
fail_on_error=fail_on_error,
files_search_exclude_folders=files_search_exclude_folders,
files_search_explicitly_listed_files=files_search_explicitly_listed_files,
files_search_root_folder=files_search_root_folder,
flags=flags,
gcov_args=gcov_args,
gcov_executable=gcov_executable,
gcov_ignore=gcov_ignore,
gcov_include=gcov_include,
git_service=git_service,
handle_no_reports_found=handle_no_reports_found,
job_code=job_code,
name=name,
network_filter=network_filter,
network_prefix=network_prefix,
network_root_folder=network_root_folder,
plugin_names=plugin_names,
pull_request_number=pull_request_number,
report_code=report_code,
report_type=report_type,
slug=slug,
swift_project=swift_project,
token=token,
use_legacy_uploader=use_legacy_uploader,
)
close_telem()
2 changes: 1 addition & 1 deletion codecov_cli/helpers/ci_adapters/azure_pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def _get_commit_sha(self):

def _get_build_url(self):
if os.getenv("SYSTEM_TEAMPROJECT") and os.getenv("BUILD_BUILDID"):
return f'{os.getenv("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI")}{os.getenv("SYSTEM_TEAMPROJECT")}/_build/results?buildId={os.getenv("BUILD_BUILDID")}'
return f"{os.getenv('SYSTEM_TEAMFOUNDATIONCOLLECTIONURI')}{os.getenv('SYSTEM_TEAMPROJECT')}/_build/results?buildId={os.getenv('BUILD_BUILDID')}"

def _get_build_code(self):
return os.getenv("BUILD_BUILDNUMBER")
Expand Down
8 changes: 8 additions & 0 deletions codecov_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import click

from codecov_cli import __version__
from codecov_cli.opentelemetry import init_telem
from codecov_cli.commands.base_picking import pr_base_picking
from codecov_cli.commands.commit import create_commit
from codecov_cli.commands.create_report_result import create_report_results
Expand Down Expand Up @@ -43,6 +44,9 @@
"--enterprise-url", "--url", "-u", help="Change the upload host (Enterprise use)"
)
@click.option("-v", "--verbose", "verbose", help="Use verbose logging", is_flag=True)
@click.option(
"--disable-telem", help="Disable sending telemetry data to Codecov", is_flag=True
)
@click.pass_context
@click.version_option(__version__, prog_name="codecovcli")
def cli(
Expand All @@ -51,6 +55,7 @@ def cli(
codecov_yml_path: pathlib.Path,
enterprise_url: str,
verbose: bool = False,
disable_telem: bool = False,
):
ctx.obj["cli_args"] = ctx.params
ctx.obj["cli_args"]["version"] = f"cli-{__version__}"
Expand All @@ -65,6 +70,9 @@ def cli(
ctx.default_map = {ctx.invoked_subcommand: {"token": token}}
ctx.obj["enterprise_url"] = enterprise_url

if not disable_telem:
init_telem(__version__, enterprise_url)


cli.add_command(do_upload)
cli.add_command(create_commit)
Expand Down
32 changes: 32 additions & 0 deletions codecov_cli/opentelemetry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import os
import time

from opentelemetry import trace
from opentelemetry.propagate import set_global_textmap
from opentelemetry.sdk.trace import TracerProvider
import sentry_sdk
from sentry_sdk.integrations.opentelemetry import SentrySpanProcessor, SentryPropagator


def init_telem(version, url):
if url: # dont run on dedicated cloud
return

if os.getenv("IS_CI", False):
return

sentry_sdk.init(
dsn="https://[email protected]/4508615876083713",
enable_tracing=True,
release=f"cli@{version}",
instrumenter="otel",
)

provider = TracerProvider()
provider.add_span_processor(SentrySpanProcessor())
trace.set_tracer_provider(provider)
set_global_textmap(SentryPropagator())


def close_telem():
sentry_sdk.flush()
2 changes: 1 addition & 1 deletion codecov_cli/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _load_plugin_from_yaml(plugin_dict: typing.Dict):

except TypeError:
click.secho(
f"Unable to instantiate {class_obj} with provided parameters { plugin_dict.get('params', '') }",
f"Unable to instantiate {class_obj} with provided parameters {plugin_dict.get('params', '')}",
err=True,
)
return NoopPlugin()
Expand Down
5 changes: 4 additions & 1 deletion codecov_cli/plugins/compress_pycoverage_contexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
from typing import Any, List

import ijson
from opentelemetry import trace

from codecov_cli.plugins.types import PreparationPluginReturn

logger = logging.getLogger("codecovcli")
tracer = trace.get_tracer(__name__)


class Encoder(json.JSONEncoder):
Expand Down Expand Up @@ -47,6 +49,7 @@ def __init__(self, config: dict = None) -> None:
str(self.file_to_compress).replace(".json", "") + ".codecov.json"
)

@tracer.start_as_current_span("compress_pycoverage")
def run_preparation(self, collector) -> PreparationPluginReturn:
if not self.file_to_compress.exists():
logger.warning(
Expand Down Expand Up @@ -120,7 +123,7 @@ def _compress_files(self, files_in_report, fd_out) -> None:
# Save the inverted index of labels table in the report
# So when we are processing the result we have int -> label
fd_out.write(
f'"labels_table": {json.dumps({ value: key for key, value in labels_table.items() })}'
f'"labels_table": {json.dumps({value: key for key, value in labels_table.items()})}'
)

def _copy_file_details(self, file_name, file_details, fd_out) -> None:
Expand Down
Loading
Loading