Skip to content

Commit

Permalink
Suuport ShTracer template
Browse files Browse the repository at this point in the history
  • Loading branch information
Wh1isper committed Sep 22, 2023
1 parent 4436e9f commit 11b3df0
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 7 deletions.
1 change: 1 addition & 0 deletions duetector/collectors/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def from_namedtuple(tracer, data: NamedTuple) -> Tracking: # type: ignore
# Is instance of tracer
tracer_name = getattr(tracer, "name", tracer.__class__.__name__)

tracer_name = tracer_name.lower()
args = {
"tracer": tracer_name,
"extended": {},
Expand Down
64 changes: 61 additions & 3 deletions duetector/managers/tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pluggy

import duetector.tracers.register
from duetector.config import Configuable
from duetector.config import Config, Configuable
from duetector.extension.tracer import project_name
from duetector.log import logger
from duetector.managers.base import Manager
Expand All @@ -24,21 +24,79 @@ def init_tracer(config) -> Optional[Tracer]:


class TracerTemplate(Configuable):
"""
Using template to generate tracers.
Tracers are initialized from config, and can be ``disabled`` by config.
Tracer type is defined by ``_avaliable_tracer_type``.
Example:
.. code-block:: toml
[tracer.template.sh]
pstracer = { "comm" = ["ps", "-aux"], config = { "enable_cache" = false } }
"""

_avaliable_tracer_type = {
"sh": ShellTracer,
}
"""
Available tracer type.
"""

default_config = {
"disabled": False,
**{k: dict() for k in _avaliable_tracer_type.keys()},
}
"""
Default config for ``TracerTemplate``.
"""

@property
def disabled(self) -> bool:
"""
Whether the template is disabled.
"""
return self.config.disabled

def __init__(self, config: Optional[Dict[str, Any]] = None, *args, **kwargs):
super().__init__(config, *args, **kwargs)
self._avaliable_tracer: Dict[type, Dict[str, Any]] = {}

def _get_wrap_tracer(
self, tracer_type: Union[str, type], tracer_name: str, kwargs: Config
) -> Tracer:
"""
Get a wrapper class for tracer type.
"""
if isinstance(tracer_type, str):
tracer_type = self._avaliable_tracer_type[tracer_type]

class WrapTracer(tracer_type):
config_scope = None

tracer_config = kwargs.pop("config", {})
WrapTracer.__name__ = WrapTracer.name = tracer_name
for k, v in kwargs.items():
setattr(WrapTracer, k, v)

return WrapTracer(tracer_config)

def init(self) -> List[Tracer]:
return []
"""
Initialize all tracers from config.
"""
if self.disabled:
logger.info("TracerTemplate disabled.")
return []

objs = []
for k, tracer_type in self._avaliable_tracer_type.items():
for tracer_name, kwargs in self.config._config_dict[k].items():
objs.append(self._get_wrap_tracer(tracer_type, tracer_name, kwargs))

return objs


class TracerManager(Manager):
Expand Down
3 changes: 2 additions & 1 deletion duetector/monitors/sh_monitor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import subprocess
from datetime import datetime
from typing import Any, Callable, Dict, List, NamedTuple, Optional

from duetector.collectors.base import Collector
Expand Down Expand Up @@ -50,7 +51,7 @@ def _():
tracer.set_cache(output)

callback = self.callbacks[tracer]
callback(tracer.data_t(output=output))
callback(tracer.data_t(output=output, dt=datetime.now()))

return _

Expand Down
2 changes: 1 addition & 1 deletion duetector/tracers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class ShellTracer(Tracer):
"""
shell command
"""
data_t = namedtuple("ShellOutput", ["output"])
data_t = namedtuple("ShellOutput", ["output", "dt"])
"""
data type for this tracer
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/test_bcc_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ def test_bcc_monitor(bcc_monitor: MockMonitor):
bcc_monitor.poll_all()
bcc_monitor.shutdown()
assert bcc_monitor.summary()
bcc_monitor.summary()["MockMonitor"]["DBCollector"]["BccMockTracer"]["last"] == Tracking(
tracer="BccMockTracer",
bcc_monitor.summary()["MockMonitor"]["DBCollector"]["bccmocktracer"]["last"] == Tracking(
tracer="bccmocktracer",
pid=9999,
uid=9999,
gid=9999,
Expand Down
45 changes: 45 additions & 0 deletions tests/test_tracer_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import pytest

from duetector.managers.tracer import ShellTracer, TracerTemplate


def test_disabled_property():
tracer_template = TracerTemplate({"disabled": True})
assert tracer_template.disabled == True

tracer_template = TracerTemplate({"disabled": False})
assert tracer_template.disabled == False


def test_init():
tracer_template = TracerTemplate({"disabled": True})
assert tracer_template.init() == []

tracer_template = TracerTemplate(
{
"disabled": False,
"sh": {
"tracer_name": {
"comm": ["ps", "-aux"],
"config": {"enable_cache": False},
}
},
}
)
tracers = tracer_template.init()
assert len(tracers) == 1
assert isinstance(tracers[0], ShellTracer)


def test_get_wrap_tracer():
tracer_template = TracerTemplate()
tracer = tracer_template._get_wrap_tracer(
"sh", "tracer_name", {"comm": ["ps", "-aux"], "config": {"enable_cache": False}}
)
assert isinstance(tracer, ShellTracer)
assert tracer.config._config_dict == {"disabled": False, "enable_cache": False}
assert tracer.comm == ["ps", "-aux"]


if __name__ == "__main__":
pytest.main(["-s", "-vv", __file__])

0 comments on commit 11b3df0

Please sign in to comment.