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

Add kart diagnostics #1013

Merged
merged 1 commit into from
Nov 8, 2024
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ _When adding new entries to the changelog, please include issue/PR numbers where

- Upgrade to PDAL 2.7 [#1005](https://github.com/koordinates/kart/pull/1005)
- Adds a `--drop-empty-geometry-features` option to `kart export`. [#1007](https://github.com/koordinates/kart/pull/1007)
- Adds diagnostic output to Kart when `KART_DIAGNOSTICS=1` environment variable is set. [#1013](https://github.com/koordinates/kart/pull/1013)

## 0.15.3

Expand Down
10 changes: 10 additions & 0 deletions kart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import platform
import sys


L = logging.getLogger("kart.__init__")

# These env vars are retained in the helper process, rather than being clobbered
Expand Down Expand Up @@ -166,6 +167,15 @@ def _env_path(path):
# Libgit2 options
import pygit2 # noqa

try:
if "KART_DIAGNOSTICS" in os.environ or pygit2.Config.get_global_config()["kart.diagnostics"]:
from kart.diagnostics import print_diagnostics

print_diagnostics()
except:
pass


pygit2.option(pygit2.GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 0)

# By default, libgit2 caches tree object reads (up to 4K trees).
Expand Down
2 changes: 1 addition & 1 deletion kart/base_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def ensure_only_supported_capabilities(self):
# the same as any other unsupported dataset.
capabilities = self.get_meta_item("capabilities.json", missing_ok=True)
if capabilities is not None:
from .cli import get_version
from .version import get_version
from .output_util import dump_json_output

click.echo(
Expand Down
77 changes: 2 additions & 75 deletions kart/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import pygit2

from . import core, is_darwin, is_linux, is_windows # noqa
from kart.version import get_version_info_text
from kart.cli_util import (
add_help_subcommand,
call_and_exit_flag,
Expand Down Expand Up @@ -78,82 +79,8 @@ def load_all_commands():
_load_commands_from_module(mod)


def get_version():
import kart

with open(Path(kart.package_data_path) / "VERSION") as version_file:
return version_file.read().strip()


def get_version_tuple():
return tuple(get_version().split("."))


def print_version(ctx):
import osgeo
import psycopg2
import pysqlite3

import sqlalchemy
from kart.sqlalchemy.gpkg import Db_GPKG

click.echo(f"Kart v{get_version()}, Copyright (c) Kart Contributors")

git_version = (
subprocess.check_output(["git", "--version"])
.decode("ascii")
.strip()
.split()[-1]
)

gitlfs_version = re.match(
r"git-lfs/([^ ]+) \(",
subprocess.check_output(["git-lfs", "version"], text=True),
).group(1)

pdal_version = (
subprocess.check_output(["pdal", "--version"])
.decode("ascii")
.strip()
.split()[2]
)

engine = Db_GPKG.create_engine(":memory:")
with engine.connect() as conn:
spatialite_version = conn.scalar("SELECT spatialite_version();")

pq_version = psycopg2.__libpq_version__
pq_version = "{}.{}.{}".format(
*[int(k) for k in re.findall(r"\d\d", str(psycopg2.__libpq_version__))]
)

proj_version = "{}.{}.{}".format(
osgeo.osr.GetPROJVersionMajor(),
osgeo.osr.GetPROJVersionMinor(),
osgeo.osr.GetPROJVersionMicro(),
)

click.echo(
(
f"» GDAL v{osgeo._gdal.__version__}; "
f"PROJ v{proj_version}; "
f"PDAL v{pdal_version}\n"
f"» PyGit2 v{pygit2.__version__}; "
f"Libgit2 v{pygit2.LIBGIT2_VERSION}; "
f"Git v{git_version}; "
f"Git LFS v{gitlfs_version}\n"
f"» SQLAlchemy v{sqlalchemy.__version__}; "
f"pysqlite3 v{pysqlite3.version}/v{pysqlite3.sqlite_version}; "
f"SpatiaLite v{spatialite_version}; "
f"Libpq v{pq_version}"
)
)

# report on whether this was run through helper mode
helper_pid = os.environ.get("KART_HELPER_PID")
if helper_pid:
click.echo(f"Executed via helper, SID={os.getsid(0)} PID={helper_pid}")

click.echo("\n".join(get_version_info_text()))
ctx.exit()


Expand Down
92 changes: 92 additions & 0 deletions kart/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from datetime import datetime
import os
from pathlib import Path
import platform
import re
import shlex
import sys

def win_quote(arg, force=False):
if force or re.search(r'["\s^&|<>]', arg):
arg = arg.replace('"', '""')
return f'"{arg}"'
return arg

def get_executable_path():
def good_executable_path(exe_path):
return ("kart" in os.path.basename(exe_path), os.path.isabs(exe_path))

return max(sys.executable, sys.argv[0], key=good_executable_path)

def print_diagnostics():
if platform.system() == "Windows":
quote = win_quote
else:
quote = shlex.quote

output = ["==== KART DIAGNOSTICS ===="]

try:
from kart.version import get_version_info_text

output += get_version_info_text()
except:
raise

cmd = [get_executable_path()] + sys.argv[1:]
cmd = " ".join(quote(c) for c in cmd)
output.append("\n==== COMMAND ====")
output.append(cmd)

output.append("\n==== PROCESS ====")
other_info = {
"now": str(datetime.now()),
"ppid": os.getppid(),
"sid": os.getsid(0),
"kart_helper_pid": os.environ.get("KART_HELPER_PID"),
"pid": os.getpid(),
}
output.append(repr(other_info))

environ = dict(sorted(os.environ.items()))
output.append("\n==== ENVIRONMENT ====")
output.append("(as python dict)")
output.append(repr(environ))

# Manually setting this variable crashes zsh for some reason, so, we won't put it in the standalone command
environ.pop("XPC_SERVICE_NAME", None)

if platform.system() == "Windows":
# Powershell syntax
ps_env_vars = "; ".join(
f"${{env:{key}}}={win_quote(value, force=True)}"
for key, value in environ.items()
)
output.append("\n==== STANDALONE POWERSHELL COMMAND ====")
output.append(f"{ps_env_vars}; & {cmd}")

# CMD syntax
cmd_env_vars = " && ".join(
"set " + win_quote(f"{key}={value}", force=True)
for key, value in environ.items()
)
output.append("\n==== STANDALONE CMD COMMAND ====")
output.append(f"{cmd_env_vars} && {cmd}")
else:
# Linux / macOS syntax
env_vars = " ".join(
f"{shlex.quote(key)}={quote(value)}"
for key, value in environ.items()
)
standalone_cmd = f"{env_vars} {cmd}"
output.append("\n==== STANDALONE COMMAND ====")
output.append(standalone_cmd)

output.append("\n==== END DIAGNOSTICS ====\n\n")

output = "\n".join(output)
print(output, file=sys.stderr)
try:
Path(os.path.expanduser("~"), "kart-diagnostics.txt").write_text(output)
except:
pass
2 changes: 1 addition & 1 deletion kart/tabular/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def dataset_class_for_version(version):


def ensure_supported_repo_wide_version(version):
from kart.cli import get_version
from kart.version import get_version

if not MIN_SUPPORTED_VERSION <= version <= MAX_SUPPORTED_VERSION:
message = (
Expand Down
82 changes: 82 additions & 0 deletions kart/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import click
import os
from pathlib import Path
import re
from kart import subprocess_util as subprocess


def get_version():
import kart

with open(Path(kart.package_data_path) / "VERSION") as version_file:
return version_file.read().strip()


def get_version_tuple():
return tuple(get_version().split("."))


def get_version_info_text():
import osgeo
import psycopg2
import pysqlite3
import pygit2
import sqlalchemy
from kart.sqlalchemy.gpkg import Db_GPKG

output = [f"Kart v{get_version()}, Copyright (c) Kart Contributors"]

git_version = (
subprocess.check_output(["git", "--version"])
.decode("ascii")
.strip()
.split()[-1]
)

gitlfs_version = re.match(
r"git-lfs/([^ ]+) \(",
subprocess.check_output(["git-lfs", "version"], text=True),
).group(1)

pdal_version = (
subprocess.check_output(["pdal", "--version"])
.decode("ascii")
.strip()
.split()[2]
)

engine = Db_GPKG.create_engine(":memory:")
with engine.connect() as conn:
spatialite_version = conn.scalar("SELECT spatialite_version();")

pq_version = psycopg2.__libpq_version__
pq_version = "{}.{}.{}".format(
*[int(k) for k in re.findall(r"\d\d", str(psycopg2.__libpq_version__))]
)

proj_version = "{}.{}.{}".format(
osgeo.osr.GetPROJVersionMajor(),
osgeo.osr.GetPROJVersionMinor(),
osgeo.osr.GetPROJVersionMicro(),
)

output += [
f"» GDAL v{osgeo._gdal.__version__}; "
f"PROJ v{proj_version}; "
f"PDAL v{pdal_version}",
f"» PyGit2 v{pygit2.__version__}; "
f"Libgit2 v{pygit2.LIBGIT2_VERSION}; "
f"Git v{git_version}; "
f"Git LFS v{gitlfs_version}",
f"» SQLAlchemy v{sqlalchemy.__version__}; "
f"pysqlite3 v{pysqlite3.version}/v{pysqlite3.sqlite_version}; "
f"SpatiaLite v{spatialite_version}; "
f"Libpq v{pq_version}"
]

# report on whether this was run through helper mode
helper_pid = os.environ.get("KART_HELPER_PID")
if helper_pid:
output.append(f"Executed via helper, SID={os.getsid(0)} PID={helper_pid}")

return output
2 changes: 1 addition & 1 deletion scripts/doc_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class Doc:
INDENT = ""

def __init__(self, ctx: click.Context, doc: t.Optional[str] = None) -> None:
from kart.cli import get_version
from kart.version import get_version

self.command = ctx.command_path
self.version = get_version()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import pytest

from kart.cli import get_version
from kart.version import get_version
from kart.exceptions import UNSUPPORTED_VERSION
from kart.repo import KartRepo

Expand Down
Loading