Skip to content

Commit cd2d8b7

Browse files
author
Alon Ben Tamar
authored
Revert "Feature/stacks container name (#35)" for now, will merge back when backend is ready for it (#64)
1 parent c82a56b commit cd2d8b7

16 files changed

+49
-214
lines changed

.flake8

-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@
22
max-line-length = 120
33
# options for compatibility with black - see https://black.readthedocs.io/en/stable/compatible_configs.html#flake8
44
extend-ignore = E203, W503
5-
exclude = .git,__pycache__,build,gprofiler.egg-info,venv

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ docker pull granulate/gprofiler:latest
6161
docker run --name gprofiler -d --restart=always \
6262
--network=host --pid=host --userns=host --privileged \
6363
-v /lib/modules:/lib/modules:ro -v /usr/src:/usr/src:ro \
64-
-v /var/run/docker.sock:/var/run/docker.sock \
65-
granulate/gprofiler:latest -cu --token <token> --service-name <service> [options]
64+
granulate/gprofiler:latest -cu --token <token> --service-name <service> [options]
6665
```
6766

6867
For profiling with eBPF, kernel headers must be accessible from within the container at

deploy/k8s/gprofiler.yaml

-5
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ spec:
2626
- name: usr-src
2727
hostPath:
2828
path: /usr/src
29-
- name: docker-sock # Allow containers to fetch the names
30-
hostPath:
31-
path: /var/run/docker.sock
3229
hostPID: true
3330
securityContext:
3431
runAsUser: 0
@@ -54,8 +51,6 @@ spec:
5451
- name: usr-src
5552
mountPath: /usr/src
5653
readOnly: true
57-
- name: docker-sock
58-
mountPath: /var/run/docker.sock
5954
args:
6055
- -cu
6156
- --token

dev-requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ flake8
33
black
44
mypy
55
isort
6+
docker
67
pyinstaller==4.0
78
staticx

gprofiler/__main__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Copyright (c) Granulate. All rights reserved.
33
# Licensed under the AGPL3 License. See LICENSE.md in the project root for license information.
44
#
5-
from gprofiler.main import main
5+
from .main import main
66

77
if __name__ == "__main__":
88
main()

gprofiler/client.py

+5-13
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import requests
1313
from requests import Session
1414

15-
from gprofiler.utils import get_iso8061_format_time
15+
from .utils import get_iso8061_format_time
1616

1717
logger = logging.getLogger(__name__)
1818

@@ -48,18 +48,11 @@ def _init_session(self, key: str, service: str):
4848
# Raises on failure
4949
self.get_health()
5050

51-
def get_base_url(self, api_version: str = None) -> str:
52-
version = api_version if api_version is not None else self._version
53-
return "{}/{}/{}".format(self._host.rstrip("/"), self.BASE_PATH, version)
51+
def get_base_url(self) -> str:
52+
return "{}/{}/{}".format(self._host.rstrip("/"), self.BASE_PATH, self._version)
5453

5554
def _send_request(
56-
self,
57-
method: str,
58-
path: str,
59-
data: Dict,
60-
files: Dict = None,
61-
timeout: float = DEFAULT_REQUEST_TIMEOUT,
62-
api_version: str = None,
55+
self, method: str, path: str, data: Dict, files: Dict = None, timeout: float = DEFAULT_REQUEST_TIMEOUT
6356
) -> Dict:
6457
opts: dict = {"headers": {}, "files": files, "timeout": timeout}
6558

@@ -73,7 +66,7 @@ def _send_request(
7366
json.dump(data, gzip_file, ensure_ascii=False) # type: ignore
7467
opts["data"] = buffer.getvalue()
7568

76-
resp = self._session.request(method, "{}/{}".format(self.get_base_url(api_version), path), **opts)
69+
resp = self._session.request(method, "{}/{}".format(self.get_base_url(), path), **opts)
7770
if 400 <= resp.status_code < 500:
7871
try:
7972
data = resp.json()
@@ -114,5 +107,4 @@ def submit_profile(
114107
"profile": profile,
115108
},
116109
timeout=self._upload_timeout,
117-
api_version="v2",
118110
)

gprofiler/docker_client.py

-106
This file was deleted.

gprofiler/java.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
import psutil
1515
from psutil import Process
1616

17-
from gprofiler.exceptions import StopEventSetException
18-
from gprofiler.merge import parse_one_collapsed
19-
from gprofiler.profiler_base import ProfilerBase
20-
from gprofiler.utils import (
17+
from .exceptions import StopEventSetException
18+
from .merge import parse_one_collapsed
19+
from .profiler_base import ProfilerBase
20+
from .utils import (
2121
TEMPORARY_STORAGE_PATH,
2222
is_same_ns,
2323
pgrep_exe,

gprofiler/main.py

+9-39
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,13 @@
2020
import configargparse
2121
from requests import RequestException, Timeout
2222

23-
from gprofiler import __version__, merge
24-
from gprofiler.client import DEFAULT_UPLOAD_TIMEOUT, GRANULATE_SERVER_HOST, APIClient, APIError
25-
from gprofiler.docker_client import DockerClient
26-
from gprofiler.java import JavaProfiler
27-
from gprofiler.perf import SystemProfiler
28-
from gprofiler.profiler_base import NoopProfiler
29-
from gprofiler.python import get_python_profiler
30-
from gprofiler.utils import (
23+
from . import __version__, merge
24+
from .client import DEFAULT_UPLOAD_TIMEOUT, GRANULATE_SERVER_HOST, APIClient, APIError
25+
from .java import JavaProfiler
26+
from .perf import SystemProfiler
27+
from .profiler_base import NoopProfiler
28+
from .python import get_python_profiler
29+
from .utils import (
3130
TEMPORARY_STORAGE_PATH,
3231
TemporaryDirectoryWithMode,
3332
atomically_symlink,
@@ -77,7 +76,6 @@ def __init__(
7776
rotating_output: bool,
7877
runtimes: Dict[str, bool],
7978
client: APIClient,
80-
include_container_names=True,
8179
):
8280
self._frequency = frequency
8381
self._duration = duration
@@ -103,8 +101,6 @@ def __init__(
103101
self._frequency, self._duration, self._stop_event, self._temp_storage_dir.name
104102
)
105103
self.initialize_python_profiler()
106-
self._docker_client = DockerClient()
107-
self._include_container_names = include_container_names
108104

109105
def __enter__(self):
110106
self.start()
@@ -149,7 +145,6 @@ def _generate_output_files(
149145
base_filename = os.path.join(self._output_dir, "profile_{}".format(end_ts))
150146

151147
collapsed_path = base_filename + ".col"
152-
collapsed_data = self._strip_container_data(collapsed_data)
153148
Path(collapsed_path).write_text(collapsed_data)
154149

155150
# point last_profile.col at the new file; and possibly, delete the previous one.
@@ -177,15 +172,6 @@ def _generate_output_files(
177172

178173
logger.info(f"Saved flamegraph to {flamegraph_path}")
179174

180-
@staticmethod
181-
def _strip_container_data(collapsed_data):
182-
lines = []
183-
for line in collapsed_data.splitlines():
184-
if line.startswith("#"):
185-
continue
186-
lines.append(line[line.find(';') + 1 :])
187-
return '\n'.join(lines)
188-
189175
def start(self):
190176
self._stop_event.clear()
191177

@@ -227,9 +213,7 @@ def _snapshot(self):
227213
logger.exception(f"{future.name} profiling failed")
228214

229215
local_end_time = local_start_time + datetime.timedelta(seconds=(time.monotonic() - monotonic_start_time))
230-
merged_result = merge.merge_perfs(
231-
system_future.result(), process_perfs, self._docker_client, self._include_container_names
232-
)
216+
merged_result = merge.merge_perfs(system_future.result(), process_perfs)
233217

234218
if self._output_dir:
235219
self._generate_output_files(merged_result, local_start_time, local_end_time)
@@ -373,13 +357,6 @@ def parse_cmd_args():
373357
dest="log_rotate_backup_count",
374358
default=DEFAULT_LOG_BACKUP_COUNT,
375359
)
376-
parser.add_argument(
377-
"--disable-container-names",
378-
action="store_true",
379-
dest="disable_container_names",
380-
default=False,
381-
help="gProfiler won't gather the container names of processes that run in containers",
382-
)
383360

384361
continuous_command_parser = parser.add_argument_group("continuous")
385362
continuous_command_parser.add_argument(
@@ -482,14 +459,7 @@ def main():
482459

483460
runtimes = {"java": args.java, "python": args.python}
484461
gprofiler = GProfiler(
485-
args.frequency,
486-
args.duration,
487-
args.output_dir,
488-
args.flamegraph,
489-
args.rotating_output,
490-
runtimes,
491-
client,
492-
not args.disable_container_names,
462+
args.frequency, args.duration, args.output_dir, args.flamegraph, args.rotating_output, runtimes, client
493463
)
494464
logger.info("gProfiler initialized and ready to start profiling")
495465

gprofiler/merge.py

+7-32
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22
# Copyright (c) Granulate. All rights reserved.
33
# Licensed under the AGPL3 License. See LICENSE.md in the project root for license information.
44
#
5-
import json
65
import logging
76
import re
8-
import socket
97
from collections import Counter, defaultdict
108
from typing import Iterable, Mapping, MutableMapping
119

12-
from gprofiler.docker_client import DockerClient
13-
1410
logger = logging.getLogger(__name__)
1511

1612
SAMPLE_REGEX = re.compile(
@@ -67,7 +63,7 @@ def parse_many_collapsed(text: str) -> Mapping[int, Mapping[str, int]]:
6763
return results
6864

6965

70-
def collapse_stack(comm: str, stack: str) -> str:
66+
def collapse_stack(stack: str, comm: str) -> str:
7167
"""
7268
Collapse a single stack from "perf".
7369
"""
@@ -101,12 +97,7 @@ def parse_perf_script(script: str):
10197
logger.exception(f"Error processing sample: {sample}")
10298

10399

104-
def merge_perfs(
105-
perf_all: Iterable[Mapping[str, str]],
106-
process_perfs: Mapping[int, Mapping[str, int]],
107-
docker_client: DockerClient,
108-
should_determine_container_names: bool,
109-
) -> str:
100+
def merge_perfs(perf_all: Iterable[Mapping[str, str]], process_perfs: Mapping[int, Mapping[str, int]]) -> str:
110101
per_process_samples: MutableMapping[int, int] = Counter()
111102
new_samples: MutableMapping[str, int] = Counter()
112103
process_names = {}
@@ -117,10 +108,7 @@ def merge_perfs(
117108
per_process_samples[pid] += 1
118109
process_names[pid] = parsed["comm"]
119110
elif parsed["stack"] is not None:
120-
container_name = _get_container_name(pid, docker_client, should_determine_container_names)
121-
collapsed_stack = collapse_stack(parsed["comm"], parsed["stack"])
122-
stack_line = f'{container_name};{collapsed_stack}'
123-
new_samples[stack_line] += 1
111+
new_samples[collapse_stack(parsed["stack"], parsed["comm"])] += 1
124112
except Exception:
125113
logger.exception(f"Error processing sample: {parsed}")
126114

@@ -130,20 +118,7 @@ def merge_perfs(
130118
if process_perf_count > 0:
131119
ratio = perf_all_count / process_perf_count
132120
for stack, count in process_stacks.items():
133-
container_name = _get_container_name(pid, docker_client, should_determine_container_names)
134-
stack_line = ";".join([container_name, process_names[pid], stack])
135-
new_samples[stack_line] += round(count * ratio)
136-
container_names = docker_client.container_names
137-
docker_client.reset_cache()
138-
profile_metadata = {
139-
'containers': container_names,
140-
'hostname': socket.gethostname(),
141-
'container_names_enabled': should_determine_container_names,
142-
}
143-
output = [f"#{json.dumps(profile_metadata)}"]
144-
output += [f"{stack} {count}" for stack, count in new_samples.items()]
145-
return "\n".join(output)
146-
147-
148-
def _get_container_name(pid: int, docker_client: DockerClient, should_determine_container_names: bool):
149-
return docker_client.get_container_name(pid) if should_determine_container_names else ""
121+
full_stack = ";".join([process_names[pid], stack])
122+
new_samples[full_stack] += round(count * ratio)
123+
124+
return "\n".join((f"{stack} {count}" for stack, count in new_samples.items()))

0 commit comments

Comments
 (0)