Skip to content

Commit

Permalink
Add docs for oTel(jager backend) (#90)
Browse files Browse the repository at this point in the history
* Updating docs

* Fix some bugs on otel collector
  • Loading branch information
Wh1isper authored Oct 23, 2023
1 parent 1dce1f1 commit 60f2347
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 4 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<p align="center">
<a href="https://github.com/hitsz-ids/dataucon"><img alt="DataUCon" src="https://raw.githubusercontent.com/hitsz-ids/dataucon/main/img/white-icon-simple.png"></a>
</p>

<h2 align="center">duetector🔍: Data Usage Extensible detector(eBPF Support)</h2>
<p align="center">
<a href="https://github.com/hitsz-ids/duetector/actions"><img alt="Actions Status" src="https://github.com/hitsz-ids/duetector/actions/workflows/python-package.yml/badge.svg"></a>
Expand Down
4 changes: 4 additions & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<p align="center">
<a href="https://github.com/hitsz-ids/dataucon"><img alt="DataUCon" src="https://raw.githubusercontent.com/hitsz-ids/dataucon/main/img/white-icon-simple.png"></a>
</p>

<h2 align="center">duetector🔍: 支持eBPF的可扩展数据使用探测器</h2>
<p align="center">
<a href="https://github.com/hitsz-ids/duetector/actions"><img alt="Actions Status" src="https://github.com/hitsz-ids/duetector/actions/workflows/python-package.yml/badge.svg"></a>
Expand Down
Binary file added docs/how-to/images/jaeger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
115 changes: 115 additions & 0 deletions docs/how-to/intergration-with-otel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Integration with OpenTelemetry

[OpenTelemetry](https://opentelemetry.io/) is a collection of APIs, SDKs, and tools that allow development teams to generate, process, and transmit telemetry data in a unified single format.

`duetector` support integration with OpenTelemetry. Through [otel collector](../../duetector/collectors/otel.py), we can export traces to any backend supported by OpenTelemetry.

## Deploy a bancend

**If you already have a backend and familiar with OpenTelemetry, you can skip this section.**

Before we start, we need a backend to receive traces. Here we use [jaeger](https://www.jaegertracing.io/) as an example, which is a popular open source tracing backend and supports OpenTelemetry directly.

Deploy [jaeger all in one](https://www.jaegertracing.io/docs/1.50/getting-started/#all-in-one) with docker:

> [Latest jaeger all in one guide](https://www.jaegertracing.io/docs/latest/getting-started/#all-in-one)
```bash
docker run --rm --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
-p 14250:14250 \
-p 14268:14268 \
-p 14269:14269 \
-p 9411:9411 \
jaegertracing/all-in-one:1.50
```

Then you can then navigate to http://localhost:16686 to access the Jaeger UI. The port `4317` is for OTLP gRPC receiver, and `4318` is for OTLP http receiver.

### Use otel collector to export traces

If your backend is **NOT** supported by OpenTelemetry, you can deploy a collector to receive traces and export them to your backend.

A simple way is to deploy a collector in [Agent mode](https://opentelemetry.io/docs/collector/deployment/agent/):

Use docker-compose to deploy a collector:

```yaml
otel-collector:
image: otel/opentelemetry-collector-contrib
volumes:
- ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml
ports:
- 1888:1888 # pprof extension
- 8888:8888 # Prometheus metrics exposed by the collector
- 8889:8889 # Prometheus exporter metrics
- 13133:13133 # health_check extension
- 4317:4317 # OTLP gRPC receiver
- 4318:4318 # OTLP http receiver
- 55679:55679 # zpages extension
```
Here is an example config file:
```yaml
receivers:
otlp: # the OTLP receiver the app is sending traces to
protocols:
grpc:

processors:
batch:

exporters:
otlp/jaeger: # Jaeger supports OTLP directly
endpoint: https://jaeger.example.com:4317

service:
pipelines:
traces/dev:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger]
```
For more deployment options, such as load balance, please refer to [OpenTelemetry Collecotr Deployment](https://opentelemetry.io/docs/collector/deployment/).
## Enable Duetector's Otel Collector
To enable duetector's otel collector, we need to set `collector.otelcollector.disabled` to `false` in config file, and set `exporter` and its `exporter_kwargs` to specify the backend. Also, you can use environment variables to set the config.

Here is an example config file:

```toml
[collector.otelcollector]
disabled = false
statis_id = "demo-service"
exporter = "otlp-grpc"
[collector.otelcollector.backend_args]
max_workers = 10
[collector.otelcollector.exporter_kwargs]
endpoint = "localhost:4317"
insecure = true
# disable dbcollector as we don't rely on db to store traces
[collector.dbcollector]
disabled = true
```

Then start duetector with the config file:

```bash
duectl start --config config.toml
```

Access jaeger UI(localhost:16686), you should see traces like this:

![jaeger](./images/jaeger.png)
15 changes: 15 additions & 0 deletions duetector/collectors/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ def normalize_field(cls, field, data):
data = get_boot_time_duration_ns(data)
return field, data

@classmethod
def serialize_field(cls, field, data):
"""
Serialize filed to one of ['bool', 'str', 'bytes', 'int', 'float'] or a sequence of those types
"""
if field == "dt":
field = "timestamp"
data = datetime.timestamp(data)
return field, data

@staticmethod
def from_namedtuple(tracer, data: NamedTuple) -> Tracking: # type: ignore
"""
Expand Down Expand Up @@ -108,10 +118,15 @@ def set_span(self, span):
continue
v = getattr(self, k)
if v is not None:
k, v = self.serialize_field(k, v)
span.set_attribute(k, v)
for k, v in self.extended.items():
span.set_attribute(k, v)

@property
def span_name(self):
return self.tracer


if __name__ == "__main__":
Tracking(tracer="test", dt=datetime.now())
10 changes: 7 additions & 3 deletions duetector/collectors/otel.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,22 @@ def endpoint(self) -> Optional[str]:
def exporter_kwargs(self) -> Dict[str, Any]:
return self.config.exporter_kwargs

@property
def service_name(self) -> str:
return f"duetector-{self.id}"

def __init__(self, config: Optional[Dict[str, Any]] = None, *args, **kwargs):
super().__init__(config, *args, **kwargs)
self.otel = OTelInitiator()
self.otel.initialize(
service_name="duetector",
service_name=self.service_name,
exporter=self.exporter,
exporter_kwargs=self.exporter_kwargs,
exporter_kwargs=self.exporter_kwargs._config_dict,
)

def _emit(self, t: Tracking):
tracer = trace.get_tracer(self.id)
with tracer.start_as_current_span(t.tracer) as span:
with tracer.start_as_current_span(t.span_name) as span:
t.set_span(span)

def summary(self) -> Dict:
Expand Down
5 changes: 4 additions & 1 deletion duetector/tracers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ def _convert_data(self, data) -> NamedTuple:
for k in self.data_t._fields: # type: ignore
v = getattr(data, k)
if isinstance(v, bytes):
v = v.decode("utf-8")
try:
v = v.decode("utf-8")
except UnicodeDecodeError:
pass

args[k] = v

Expand Down

0 comments on commit 60f2347

Please sign in to comment.