-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
966 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#!/usr/bin/env python | ||
# Copyright 2025 Canonical Ltd. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
"""FIXME dummy_load docstring.""" | ||
|
||
from __future__ import annotations | ||
|
||
import time | ||
|
||
import opentelemetry.trace | ||
|
||
import ops | ||
|
||
tracer = opentelemetry.trace.get_tracer(__name__) | ||
|
||
|
||
class FakeCharm(ops.CharmBase): | ||
"""Dummy docstring.""" | ||
|
||
def __init__(self, framework: ops.Framework): | ||
"""Dummy docstring.""" | ||
super().__init__(framework) | ||
self.framework.observe(self.on.start, self._on_start) | ||
self.framework.observe(self.on.collect_app_status, self._on_collect_app_status) | ||
self.framework.observe(self.on.collect_unit_status, self._on_collect_unit_status) | ||
|
||
def _on_start(self, event: ops.StartEvent) -> None: | ||
"""Dummy docstring.""" | ||
ops.configure_tracing_destination('http://localhost:4318/v1/traces') | ||
self.dummy_load(event, 0.0025) | ||
|
||
def _on_collect_app_status(self, event: ops.CollectStatusEvent) -> None: | ||
"""Dummy docstring.""" | ||
self.dummy_load(event) | ||
event.add_status(ops.ActiveStatus('app seems ready')) | ||
|
||
def _on_collect_unit_status(self, event: ops.CollectStatusEvent) -> None: | ||
"""Dummy docstring.""" | ||
self.dummy_load(event) | ||
event.add_status(ops.ActiveStatus('unit ready')) | ||
|
||
@tracer.start_as_current_span('FakeCharm.dummy_load') # type: ignore | ||
def dummy_load(self, event: ops.EventBase, duration: float = 0.001) -> None: | ||
"""Dummy docstring.""" | ||
print(event) | ||
time.sleep(duration) | ||
|
||
|
||
if __name__ == '__main__': | ||
ops.main(FakeCharm) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
name: testmetest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
receivers: | ||
otlp: | ||
protocols: | ||
grpc: | ||
endpoint: "[::]:4317" | ||
http: | ||
endpoint: "[::]:4318" | ||
|
||
processors: | ||
batch: | ||
|
||
exporters: | ||
debug: | ||
verbosity: detailed | ||
jaeger: | ||
endpoint: jaeger:14250 | ||
tls: | ||
insecure: true | ||
|
||
service: | ||
pipelines: | ||
traces: | ||
receivers: [otlp] | ||
processors: [batch] | ||
exporters: [debug] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
### Usage | ||
|
||
Recommended for traces of moderate and high complexity: | ||
|
||
```command | ||
dima@colima-ahh /c/operator (feat-otel)> docker run --rm --name jaeger \ | ||
-p 16686:16686 \ | ||
-p 4317:4317 \ | ||
-p 4318:4318 \ | ||
-p 5778:5778 \ | ||
-p 9411:9411 \ | ||
jaegertracing/jaeger:2.2.0 | ||
``` | ||
|
||
After which, you should be able to: | ||
- open http://192.168.107.4:16686/ in your browser | ||
- select the correct **Service** (`testapp-charm` at current branch state) | ||
- click Search at the bottom of the form | ||
|
||
Note: the `jaeger` container keeps traces in memory, and your Service can't be selected | ||
until it has sent some data to `jaeger`. | ||
|
||
Alternatively, text-based: | ||
|
||
```command | ||
dima@colima-ahh /c/operator (feat-otel)> docker run -it --rm \ | ||
-v (pwd)/dont-merge/otel-collector-config.yaml:/etc/otel-collector-config.yaml \ | ||
-p 4317:4317 \ | ||
-p 4318:4318 \ | ||
otel/opentelemetry-collector:latest \ | ||
--config=/etc/otel-collector-config.yaml | ||
``` | ||
|
||
and then | ||
|
||
```command | ||
dima@colima-ahh /c/operator (feat-otel)> uv venv --seed .ahh-venv | ||
Using CPython 3.13.0 | ||
Creating virtual environment with seed packages at: .ahh-venv | ||
|
||
dima@colima-ahh /c/operator (feat-otel)> . .ahh-venv/bin/activate.fish | ||
(.ahh-venv) dima@colima-ahh /c/operator (feat-otel)> | ||
|
||
(.ahh-venv) dima@colima-ahh /c/operator (feat-otel)> uv pip install -e .[tracing] -U | ||
Using Python 3.13.0 environment at .ahh-venv | ||
Resolved 21 packages in 907ms | ||
Prepared 18 packages in 72ms | ||
... | ||
|
||
(.ahh-venv) dima@colima-ahh /c/operator (feat-otel)> python dont-merge/send-traces.py | ||
Span created and exported to the collector! | ||
``` | ||
|
||
### Hacking | ||
|
||
Or, trying to run code outside of a charm. | ||
|
||
Somehow I'm not getting anything, because the `juju-log` hook tool is missing. | ||
|
||
Let's fix that. | ||
|
||
```command | ||
> ln -s (which echo) juju-log | ||
``` | ||
|
||
Generate some tracing data: | ||
|
||
```command | ||
(venv) > JUJU_UNIT_NAME=testapp/42 JUJU_CHARM_DIR=dont-merge/ PATH=$PATH:. JUJU_VERSION=3.5.4 ./dont-merge/start | ||
``` | ||
|
||
OTEL collector debug output would look like this: | ||
|
||
``` | ||
2025-01-15T08:46:23.229Z info Traces {"kind": "exporter", "data_type": "traces", "name": "debug", "resource spans": 1, "spans": 1} | ||
2025-01-15T08:46:23.229Z info ResourceSpans #0 | ||
Resource SchemaURL: | ||
Resource attributes: | ||
-> telemetry.sdk.language: Str(python) | ||
-> telemetry.sdk.name: Str(opentelemetry) | ||
-> telemetry.sdk.version: Str(1.29.0) | ||
-> service.name: Str(testapp-charm) | ||
-> compose_service: Str(testapp-charm) | ||
-> charm_type: Str(CharmBase) | ||
-> juju_unit: Str(testapp/42) | ||
-> juju_application: Str(testapp) | ||
-> juju_model: Str() | ||
-> juju_model_uuid: Str() | ||
ScopeSpans #0 | ||
ScopeSpans SchemaURL: | ||
InstrumentationScope ops | ||
Span #0 | ||
Trace ID : 8c3f292c89f29c59f1b37fe59ba0abbc | ||
Parent ID : | ||
ID : e0253a03ef694a4f | ||
Name : ops.main | ||
Kind : Internal | ||
Start time : 2025-01-15 08:46:23.175916835 +0000 UTC | ||
End time : 2025-01-15 08:46:23.182329655 +0000 UTC | ||
Status code : Error | ||
Status message : RuntimeError: command not found: is-leader | ||
Events: | ||
SpanEvent #0 | ||
-> Name: exception | ||
-> Timestamp: 2025-01-15 08:46:23.182316071 +0000 UTC | ||
-> DroppedAttributesCount: 0 | ||
-> Attributes:: | ||
-> exception.type: Str(RuntimeError) | ||
-> exception.message: Str(command not found: is-leader) | ||
-> exception.stacktrace: Str(Traceback (most recent call last): | ||
... | ||
-> exception.escaped: Str(False) | ||
{"kind": "exporter", "data_type": "traces", "name": "debug"} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Copyright 2025 Canonical Ltd. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
"""FIXME dummy docstring.""" | ||
|
||
from __future__ import annotations | ||
|
||
import logging | ||
|
||
import opentelemetry.trace | ||
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter | ||
from opentelemetry.sdk.resources import Resource | ||
from opentelemetry.sdk.trace import TracerProvider | ||
from opentelemetry.sdk.trace.export import BatchSpanProcessor | ||
|
||
# The default ProxyTracer allows tracers to be declared ahead of time like loggers | ||
logger = logging.getLogger(__name__) | ||
tracer = opentelemetry.trace.get_tracer(__name__) | ||
|
||
# 1. Create a tracer provider with a "service.name" resource attribute | ||
opentelemetry.trace.set_tracer_provider( | ||
TracerProvider(resource=Resource.create({'service.name': 'example-service'})) | ||
) | ||
|
||
# 2. Configure the OTLP HTTP exporter (defaults to protobuf format) | ||
otlp_exporter = OTLPSpanExporter( | ||
endpoint='http://localhost:4318/v1/traces' | ||
# If you needed headers or auth, you could add them like: | ||
# headers={"Authorization": "Bearer <TOKEN>"}, | ||
) | ||
|
||
# 3. Create a span processor (BatchSpanProcessor recommended for production) | ||
span_processor = BatchSpanProcessor(otlp_exporter) | ||
opentelemetry.trace.get_tracer_provider().add_span_processor(span_processor) # type: ignore | ||
|
||
|
||
@tracer.start_as_current_span('some label') # type: ignore | ||
def main(foo: int = 42): | ||
"""Do something.""" | ||
# can't add attributes to a decorator, if needed use the below instead | ||
# | ||
# with tracer.start_as_current_span("some label") as span: | ||
# span.set_attribute('foo', 'bar') | ||
# span.add_event('sample_event', {'event_attr': 123}) | ||
|
||
logger.info('Span created and will be exported to the collector soon!') | ||
|
||
|
||
if __name__ == '__main__': | ||
logging.basicConfig(level='INFO') | ||
main() | ||
# from typing_extensions import reveal_type | ||
# reveal_type(main) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.