Skip to content

Commit

Permalink
Intro AnalyzerManager (#63)
Browse files Browse the repository at this point in the history
* Intro AnalyzerManager

* Solve dependence
  • Loading branch information
Wh1isper authored Sep 16, 2023
1 parent cc5afb2 commit 8c966dc
Show file tree
Hide file tree
Showing 31 changed files with 465 additions and 61 deletions.
13 changes: 13 additions & 0 deletions docs/source/managers/analyzer.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
AnalyzerManager
===========================================


.. autodata:: duetector.managers.analyzer.PROJECT_NAME
.. autofunction:: duetector.managers.analyzer.init_analyzer


.. autoclass:: duetector.managers.analyzer.AnalyzerManager
:members:
:undoc-members:
:inherited-members:
:show-inheritance:
2 changes: 1 addition & 1 deletion docs/source/managers/collector.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CollectorManager
.. autofunction:: duetector.managers.collector.init_collector


.. autoclass:: duetector.managers.CollectorManager
.. autoclass:: duetector.managers.collector.CollectorManager
:members:
:undoc-members:
:inherited-members:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/managers/filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FilterManager
.. autofunction:: duetector.managers.filter.init_filter


.. autoclass:: duetector.managers.FilterManager
.. autoclass:: duetector.managers.filter.FilterManager
:members:
:undoc-members:
:inherited-members:
Expand Down
3 changes: 2 additions & 1 deletion docs/source/managers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Managers
Managers provides a way to get instances of both built-in implementations and extensions.


.. autoclass:: duetector.managers.Manager
.. autoclass:: duetector.managers.base.Manager
:members:
:undoc-members:
:inherited-members:
Expand All @@ -20,3 +20,4 @@ Avaliable Manager
Collector Manager <collector>
Filter Manager <filter>
Tracer Manager <tracer>
Analyzer Manager <analyzer>
2 changes: 1 addition & 1 deletion docs/source/managers/tracer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ TracerManager
.. autofunction:: duetector.managers.tracer.init_tracer


.. autoclass:: duetector.managers.TracerManager
.. autoclass:: duetector.managers.tracer.TracerManager
:members:
:undoc-members:
:inherited-members:
Expand Down
23 changes: 17 additions & 6 deletions duetector/analyzer/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,28 @@ class Analyzer(Configuable):
A base class for all analyzers.
"""

default_config = {}
default_config = {
"disabled": False,
}
"""
Default config for ``Analyzer``.
"""

config_scope = "analyzer"
"""
Config scope for this analyzer.
@property
def disabled(self) -> bool:
"""
Weather this analyzer is disabled.
"""
return self.config.disabled

Subclasses cloud override this.
"""
@property
def config_scope(self):
"""
Config scope for this analyzer.
Subclasses cloud override this.
"""
return self.__class__.__name__.lower()

def get_all_tracers(self) -> List[str]:
"""
Expand Down
11 changes: 6 additions & 5 deletions duetector/analyzer/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from duetector.analyzer.base import Analyzer
from duetector.analyzer.models import AnalyzerBrief, Brief, Tracking
from duetector.db import SessionManager
from duetector.extension.analyzer import hookimpl
from duetector.log import logger


Expand Down Expand Up @@ -68,11 +69,6 @@ class DBAnalyzer(Analyzer):
Default config for ``DBAnalyzer``.
"""

config_scope = "db_analyzer"
"""
Config scope for this analyzer.
"""

def __init__(self, config: Optional[Dict[str, Any]] = None, *args, **kwargs):
super().__init__(config, *args, **kwargs)
# Init as a submodel
Expand Down Expand Up @@ -299,3 +295,8 @@ def brief(
collector_ids=set([brief.collector_id for brief in briefs]),
briefs={f"{brief.tracer}@{brief.collector_id}": brief for brief in briefs},
)


@hookimpl
def init_analyzer(config):
return DBAnalyzer(config)
4 changes: 4 additions & 0 deletions duetector/analyzer/register.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Expose for plugin system
from . import db

registers = [db]
5 changes: 4 additions & 1 deletion duetector/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from duetector.analyzer.db import DBAnalyzer
from duetector.config import CONFIG_PATH, ConfigLoader
from duetector.log import logger
from duetector.managers.analyzer import AnalyzerManager
from duetector.monitors import BccMonitor, ShMonitor
from duetector.monitors.base import Monitor
from duetector.tools.config_generator import ConfigGenerator
Expand Down Expand Up @@ -170,7 +171,9 @@ def _shutdown(sig=None, frame=None):
if brief:
try:
logger.info("Generating brief...")
logger.info(str(DBAnalyzer(c).brief(inspect_type=False)))
analyzers = AnalyzerManager(c).init()
for a in analyzers:
logger.info(str(a.brief(inspect_type=False)))
except Exception as e:
logger.error("Exception when generating brief")
logger.exception(e)
Expand Down
4 changes: 4 additions & 0 deletions duetector/extension/analyzer/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import pluggy

project_name = "duetector.analyzer"
hookimpl = pluggy.HookimplMarker(project_name)
6 changes: 0 additions & 6 deletions duetector/managers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +0,0 @@
from .base import Manager
from .collector import CollectorManager
from .filter import FilterManager
from .tracer import TracerManager

__all__ = ["Manager", "CollectorManager", "FilterManager", "TracerManager"]
70 changes: 70 additions & 0 deletions duetector/managers/analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import sys
from typing import Any, Dict, List, Optional

import pluggy

import duetector.analyzer.register
from duetector.analyzer.base import Analyzer
from duetector.extension.analyzer import project_name
from duetector.log import logger
from duetector.managers.base import Manager

PROJECT_NAME = project_name #: Default project name for pluggy
hookspec = pluggy.HookspecMarker(PROJECT_NAME)


@hookspec
def init_analyzer(config) -> Optional[Analyzer]:
"""
Initialize analyzer from config
None means the analyzer is not available
Also the analyzer can be disabled by config, Manager will discard disabled analyzer
"""


class AnalyzerManager(Manager):
"""
Manager for all analyzers.
Analyzers are initialized from config, and can be ``disabled`` by config.
"""

config_scope = "analyzer"
"""
Config scope for ``AnalyzerManager``.
"""

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

self.pm = pluggy.PluginManager(PROJECT_NAME)
self.pm.add_hookspecs(sys.modules[__name__])
self.pm.load_setuptools_entrypoints(PROJECT_NAME)
self.register(duetector.analyzer.register)

def init(self, analyzer_type=Analyzer, ignore_disabled=True) -> List[Analyzer]:
"""
Initialize all analyzers from config.
Args:
analyzer_type: Only return analyzers of this type
ignore_disabled: Ignore disabled analyzers
"""
if self.disabled:
logger.info("AnalyzerManager disabled.")
return []

objs = []
for f in self.pm.hook.init_analyzer(config=self.config._config_dict):
if not f or (f.disabled and ignore_disabled):
logger.debug(f"Analyzer {f.__class__.__name__} is not available (None or Disabled)")
continue
if not isinstance(f, analyzer_type):
logger.debug(
f"Skip Analyzer {f.__class__.__name__} (Not a instance of {analyzer_type})"
)
continue

objs.append(f)

return objs
2 changes: 1 addition & 1 deletion duetector/managers/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from duetector.collectors.base import Collector
from duetector.extension.collector import project_name
from duetector.log import logger
from duetector.managers import Manager
from duetector.managers.base import Manager

PROJECT_NAME = project_name #: Default project name for pluggy
hookspec = pluggy.HookspecMarker(PROJECT_NAME)
Expand Down
2 changes: 1 addition & 1 deletion duetector/managers/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from duetector.extension.filter import project_name
from duetector.filters.base import Filter
from duetector.log import logger
from duetector.managers import Manager
from duetector.managers.base import Manager

PROJECT_NAME = project_name #: Default project name for pluggy
hookspec = pluggy.HookspecMarker(PROJECT_NAME)
Expand Down
2 changes: 1 addition & 1 deletion duetector/managers/tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import duetector.tracers.register
from duetector.extension.tracer import project_name
from duetector.log import logger
from duetector.managers import Manager
from duetector.managers.base import Manager
from duetector.tracers.base import Tracer

PROJECT_NAME = project_name #: Default project name for pluggy
Expand Down
4 changes: 3 additions & 1 deletion duetector/monitors/bcc_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

from duetector.collectors.base import Collector
from duetector.log import logger
from duetector.managers import CollectorManager, FilterManager, TracerManager
from duetector.managers.collector import CollectorManager
from duetector.managers.filter import FilterManager
from duetector.managers.tracer import TracerManager
from duetector.monitors.base import Monitor
from duetector.tracers import BccTracer

Expand Down
4 changes: 3 additions & 1 deletion duetector/monitors/sh_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

from duetector.collectors.base import Collector
from duetector.log import logger
from duetector.managers import CollectorManager, FilterManager, TracerManager
from duetector.managers.collector import CollectorManager
from duetector.managers.filter import FilterManager
from duetector.managers.tracer import TracerManager
from duetector.monitors.base import Monitor
from duetector.tracers.base import ShellTracer

Expand Down
7 changes: 3 additions & 4 deletions duetector/service/query/controller.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Any, Dict, List, Optional

from duetector.analyzer.base import Analyzer
from duetector.analyzer.db import DBAnalyzer
from duetector.managers.analyzer import AnalyzerManager
from duetector.service.base import Controller
from duetector.service.exceptions import NotFoundError

Expand All @@ -11,11 +11,10 @@ def __init__(self, config: Optional[Dict[str, Any]] = None, *args, **kwargs):
super().__init__(config, *args, **kwargs)

# TODO: Make this configurable, may intro a manager for analyzer
self._avaliable_analyzers = [DBAnalyzer]
self._avaliable_analyzers = AnalyzerManager(config).init()

self._analyzers: Dict[str, Analyzer] = {
analyzer.config_scope: self._init_analyzer(analyzer)
for analyzer in self._avaliable_analyzers
analyzer.config_scope: analyzer for analyzer in self._avaliable_analyzers
}

def _init_analyzer(self, analyzer: type):
Expand Down
19 changes: 13 additions & 6 deletions duetector/static/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ maxlen = 1024
[collector.dequecollector.backend_args]
max_workers = 10

[analyzer]
disabled = false
include_extension = true

[analyzer.dbanalyzer]
disabled = false

[analyzer.dbanalyzer.db]
table_prefix = "duetector_tracking"

[analyzer.dbanalyzer.db.engine]
url = "sqlite:///duetector-dbcollector.sqlite3"

[monitor.bcc]
disabled = false
auto_init = true
Expand All @@ -99,11 +112,5 @@ max_workers = 10
[monitor.sh.poller]
interval_ms = 500

[db_analyzer.db]
table_prefix = "duetector_tracking"

[db_analyzer.db.engine]
url = "sqlite:///duetector-dbcollector.sqlite3"

[server]
token = ""
15 changes: 5 additions & 10 deletions duetector/tools/config_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
from duetector.analyzer.db import DBAnalyzer
from duetector.config import ConfigLoader
from duetector.log import logger
from duetector.managers import CollectorManager, FilterManager, TracerManager
from duetector.managers.analyzer import AnalyzerManager
from duetector.managers.collector import CollectorManager
from duetector.managers.filter import FilterManager
from duetector.managers.tracer import TracerManager
from duetector.monitors import BccMonitor, ShMonitor
from duetector.service.config import ServerConfig

Expand Down Expand Up @@ -48,7 +51,7 @@ class ConfigGenerator:
"""

managers = [FilterManager, TracerManager, CollectorManager]
managers = [FilterManager, TracerManager, CollectorManager, AnalyzerManager]
"""
All managers to inspect.
"""
Expand All @@ -58,11 +61,6 @@ class ConfigGenerator:
All monitors to inspect.
"""

analyzer = [DBAnalyzer]
"""
All analyzers to inspect.
"""

others = [ServerConfig]

def __init__(
Expand All @@ -88,9 +86,6 @@ def __init__(
for m in self.monitors:
_recursive_load(m.config_scope, self.dynamic_config, m.default_config)

for a in self.analyzer:
_recursive_load(a.config_scope, self.dynamic_config, a.default_config)

for o in self.others:
_recursive_load(o.config_scope, self.dynamic_config, o.default_config)
# This will generate default config file if not exists
Expand Down
Loading

0 comments on commit 8c966dc

Please sign in to comment.