diff --git a/duetector/analyzer/jaeger/__init__.py b/duetector/analyzer/jaeger/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/duetector/collectors/models.py b/duetector/collectors/models.py index 6ef1d51..865e0a5 100644 --- a/duetector/collectors/models.py +++ b/duetector/collectors/models.py @@ -81,13 +81,15 @@ def from_namedtuple(tracer, data: NamedTuple) -> Tracking: # type: ignore """ Create a Tracking instance from tracer's data """ - if isinstance(tracer, type): - tracer_name = getattr(tracer, "__name__") - elif isinstance(tracer, str): - tracer_name = tracer - else: - # Is instance of tracer - tracer_name = getattr(tracer, "name", tracer.__class__.__name__) + tracer_name = getattr(data, "tracer_name", None) + if not tracer_name: + if isinstance(tracer, type): + tracer_name = getattr(tracer, "__name__") + elif isinstance(tracer, str): + tracer_name = tracer + else: + # Is instance of tracer + tracer_name = getattr(tracer, "name", tracer.__class__.__name__) tracer_name = tracer_name.lower() args = { @@ -112,7 +114,7 @@ def from_namedtuple(tracer, data: NamedTuple) -> Tracking: # type: ignore return Tracking(**args) - def set_span(self, span): + def set_span(self, collector, span): for k in self.model_fields: if k in ("tracer", "extended"): continue @@ -122,10 +124,10 @@ def set_span(self, span): span.set_attribute(k, v) for k, v in self.extended.items(): span.set_attribute(k, v) + span.set_attribute("collector_id", collector.id) - @property - def span_name(self): - return self.tracer + def span_name(self, collector): + return f"{self.tracer}@{collector.id}" if __name__ == "__main__": diff --git a/duetector/collectors/otel.py b/duetector/collectors/otel.py index 84ff7a1..15e9b2e 100644 --- a/duetector/collectors/otel.py +++ b/duetector/collectors/otel.py @@ -155,8 +155,8 @@ def __init__(self, config: Optional[Dict[str, Any]] = None, *args, **kwargs): def _emit(self, t: Tracking): tracer = trace.get_tracer(self.id) - with tracer.start_as_current_span(t.span_name) as span: - t.set_span(span) + with tracer.start_as_current_span(t.span_name(self)) as span: + t.set_span(self, span) def summary(self) -> Dict: return {} diff --git a/duetector/monitors/subprocess_monitor.py b/duetector/monitors/subprocess_monitor.py index 1773006..caefdc4 100644 --- a/duetector/monitors/subprocess_monitor.py +++ b/duetector/monitors/subprocess_monitor.py @@ -130,6 +130,7 @@ def poll(self, tracer: SubprocessTracer): """ p = self.tracers[tracer] if not self.is_alive(tracer): + # Restart tracer if self.restart_times == 0: return if ( diff --git a/duetector/tracers/base.py b/duetector/tracers/base.py index b0bb1bb..fa38d13 100644 --- a/duetector/tracers/base.py +++ b/duetector/tracers/base.py @@ -19,6 +19,11 @@ class Tracer(Configuable): Default scope for config is ``Tracer.__class__.__name__``. """ + name: Optional[str] + """ + Name for this tracer. Will be used for collecting data. + """ + data_t: NamedTuple """ Data type for this tracer. @@ -239,11 +244,11 @@ class ShellTracer(Tracer): Cache means the same output will not be converted and emited again. """ - comm = List[str] + comm: List[str] """ shell command """ - data_t = namedtuple("ShellOutput", ["output", "dt"]) + data_t: namedtuple("ShellOutput", ["output", "dt"]) """ data type for this tracer """ diff --git a/duetector/tracers/bcc/clone.py b/duetector/tracers/bcc/clone.py index 2008eee..76aace5 100644 --- a/duetector/tracers/bcc/clone.py +++ b/duetector/tracers/bcc/clone.py @@ -10,6 +10,8 @@ class CloneTracer(BccTracer): A tracer for clone syscall. """ + name = "__x64_sys_clone" + default_config = { **BccTracer.default_config, "attach_event": "__x64_sys_clone", @@ -21,13 +23,13 @@ class CloneTracer(BccTracer): def attatch_args(self): return {"fn_name": "do_trace", "event": self.config.attach_event} - poll_fn = "perf_buffer_poll" + poll_fn = "ring_buffer_poll" @property def poll_args(self): return {"timeout": int(self.config.poll_timeout)} - data_t = namedtuple("CloneTracking", ["pid", "timestamp", "comm"]) + data_t = namedtuple("CloneTracking", ["pid", "uid", "gid", "timestamp", "comm"]) prog = """ #include @@ -39,7 +41,7 @@ def poll_args(self): u64 timestamp; char comm[TASK_COMM_LEN]; }; - BPF_PERF_OUTPUT(events); + BPF_RINGBUF_OUTPUT(buffer, 1 << 4); int do_trace(struct pt_regs *ctx) { struct data_t data = {}; @@ -50,7 +52,7 @@ def poll_args(self): data.timestamp = bpf_ktime_get_ns(); bpf_get_current_comm(&data.comm, sizeof(data.comm)); - events.perf_submit(ctx, &data, sizeof(data)); + buffer.ringbuf_output(&data, sizeof(data), 0); return 0; } @@ -58,10 +60,10 @@ def poll_args(self): def set_callback(self, host, callback: Callable[[NamedTuple], None]): def _(ctx, data, size): - event = host["events"].event(data) + event = host["buffer"].event(data) return callback(self._convert_data(event)) # type: ignore - host["events"].open_perf_buffer(_) + host["buffer"].open_ring_buffer(_) @hookimpl @@ -81,10 +83,11 @@ def init_tracer(config): def print_callback(data: NamedTuple): global start if start == 0: - print(f"[{data.comm} ({data.pid})] 0 ") + print(f"[{data.comm} ({data.pid}) {data.gid} {data.uid}] 0 ") + start = data.timestamp + else: print(f"[{data.comm} ({data.pid}) {data.gid} {data.uid}] {(data.timestamp-start)/1000000000}") # type: ignore - start = data.timestamp tracer.set_callback(b, print_callback) poller = tracer.get_poller(b) diff --git a/duetector/tracers/bcc/openat2.py b/duetector/tracers/bcc/openat2.py index 0701f8d..fbd0983 100644 --- a/duetector/tracers/bcc/openat2.py +++ b/duetector/tracers/bcc/openat2.py @@ -10,6 +10,8 @@ class OpenTracer(BccTracer): A tracer for openat2 syscall. """ + name = "do_sys_openat2" + default_config = { **BccTracer.default_config, "attach_event": "do_sys_openat2", diff --git a/duetector/tracers/bcc/tcpconnect.py b/duetector/tracers/bcc/tcpconnect.py index 69e9915..2bd72f0 100644 --- a/duetector/tracers/bcc/tcpconnect.py +++ b/duetector/tracers/bcc/tcpconnect.py @@ -11,6 +11,8 @@ class TcpconnectTracer(BccTracer): A tracer for tcpconnect syscall """ + name = "tcp_v4_connect" + default_config = { **BccTracer.default_config, "poll_timeout": 10, diff --git a/duetector/tracers/sh/uname.py b/duetector/tracers/sh/uname.py index facd717..d4911ce 100644 --- a/duetector/tracers/sh/uname.py +++ b/duetector/tracers/sh/uname.py @@ -7,6 +7,8 @@ class UnameTracer(ShellTracer): A tracer for uname command. """ + name = "uname" + comm = ["uname", "-a"] diff --git a/tests/bin/dummy_process.py b/tests/bin/dummy_process.py index 640d1f2..32ab7c4 100755 --- a/tests/bin/dummy_process.py +++ b/tests/bin/dummy_process.py @@ -34,8 +34,9 @@ def __init__(self, init_config) -> None: def _target(self): msg = EventMessage.from_subprocess( { + "tracer_name": self.name, "pid": os.getpid(), - "extra": "noting", + "extra": "nothing", } ) while not self.event.is_set():