Metadata-Version: 2.1
Name: nucliadb_telemetry
Version: 5.1.1.post1318
Summary: NucliaDB Telemetry Library Python process
Home-page: https://github.com/nuclia/nucliadb
Author: nucliadb Authors
Author-email: nucliadb@nuclia.com
License: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Classifier: Framework :: AsyncIO
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: pydantic>=2.6
Requires-Dist: pydantic-settings>=2.2
Requires-Dist: prometheus-client>=0.12.0
Requires-Dist: orjson>=3.6.7
Requires-Dist: wrapt>=1.14.1
Provides-Extra: all
Requires-Dist: nats-py[nkeys]>=2.5.0; extra == "all"
Requires-Dist: grpcio-testing<1.63.0,>=1.44.0; extra == "all"
Requires-Dist: PyNaCl; extra == "all"
Requires-Dist: grpcio-status<1.63.0,>=1.44.0; extra == "all"
Requires-Dist: opentelemetry-semantic-conventions>=0.42b0; extra == "all"
Requires-Dist: opentelemetry-proto==1.21.0; extra == "all"
Requires-Dist: grpcio-health-checking<1.63.0,>=1.44.0; extra == "all"
Requires-Dist: opentelemetry-instrumentation-aiohttp-client>=0.42b0; extra == "all"
Requires-Dist: fastapi; extra == "all"
Requires-Dist: opentelemetry-propagator-b3==1.21.0; extra == "all"
Requires-Dist: grpcio<1.63.0,>=1.44.0; extra == "all"
Requires-Dist: grpcio-tools<1.63.0,>=1.44.0; extra == "all"
Requires-Dist: opentelemetry-api==1.21.0; extra == "all"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.42b0; extra == "all"
Requires-Dist: opentelemetry-exporter-jaeger==1.21.0; extra == "all"
Requires-Dist: opentelemetry-sdk==1.21.0; extra == "all"
Requires-Dist: grpcio-reflection<1.63.0,>=1.44.0; extra == "all"
Requires-Dist: grpcio-channelz<1.63.0,>=1.44.0; extra == "all"
Provides-Extra: fastapi
Requires-Dist: fastapi; extra == "fastapi"
Requires-Dist: opentelemetry-sdk==1.21.0; extra == "fastapi"
Requires-Dist: opentelemetry-api==1.21.0; extra == "fastapi"
Requires-Dist: opentelemetry-proto==1.21.0; extra == "fastapi"
Requires-Dist: opentelemetry-exporter-jaeger==1.21.0; extra == "fastapi"
Requires-Dist: opentelemetry-propagator-b3==1.21.0; extra == "fastapi"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.42b0; extra == "fastapi"
Requires-Dist: opentelemetry-instrumentation-aiohttp-client>=0.42b0; extra == "fastapi"
Requires-Dist: opentelemetry-semantic-conventions>=0.42b0; extra == "fastapi"
Provides-Extra: grpc
Requires-Dist: grpcio<1.63.0,>=1.44.0; extra == "grpc"
Requires-Dist: grpcio-health-checking<1.63.0,>=1.44.0; extra == "grpc"
Requires-Dist: grpcio-channelz<1.63.0,>=1.44.0; extra == "grpc"
Requires-Dist: grpcio-status<1.63.0,>=1.44.0; extra == "grpc"
Requires-Dist: grpcio-tools<1.63.0,>=1.44.0; extra == "grpc"
Requires-Dist: grpcio-testing<1.63.0,>=1.44.0; extra == "grpc"
Requires-Dist: grpcio-reflection<1.63.0,>=1.44.0; extra == "grpc"
Requires-Dist: opentelemetry-sdk==1.21.0; extra == "grpc"
Requires-Dist: opentelemetry-api==1.21.0; extra == "grpc"
Requires-Dist: opentelemetry-proto==1.21.0; extra == "grpc"
Requires-Dist: opentelemetry-exporter-jaeger==1.21.0; extra == "grpc"
Requires-Dist: opentelemetry-propagator-b3==1.21.0; extra == "grpc"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.42b0; extra == "grpc"
Requires-Dist: opentelemetry-instrumentation-aiohttp-client>=0.42b0; extra == "grpc"
Requires-Dist: opentelemetry-semantic-conventions>=0.42b0; extra == "grpc"
Provides-Extra: nats
Requires-Dist: nats-py[nkeys]>=2.5.0; extra == "nats"
Requires-Dist: PyNaCl; extra == "nats"
Requires-Dist: opentelemetry-sdk==1.21.0; extra == "nats"
Requires-Dist: opentelemetry-api==1.21.0; extra == "nats"
Requires-Dist: opentelemetry-proto==1.21.0; extra == "nats"
Requires-Dist: opentelemetry-exporter-jaeger==1.21.0; extra == "nats"
Requires-Dist: opentelemetry-propagator-b3==1.21.0; extra == "nats"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.42b0; extra == "nats"
Requires-Dist: opentelemetry-instrumentation-aiohttp-client>=0.42b0; extra == "nats"
Requires-Dist: opentelemetry-semantic-conventions>=0.42b0; extra == "nats"
Provides-Extra: otel
Requires-Dist: opentelemetry-sdk==1.21.0; extra == "otel"
Requires-Dist: opentelemetry-api==1.21.0; extra == "otel"
Requires-Dist: opentelemetry-proto==1.21.0; extra == "otel"
Requires-Dist: opentelemetry-exporter-jaeger==1.21.0; extra == "otel"
Requires-Dist: opentelemetry-propagator-b3==1.21.0; extra == "otel"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.42b0; extra == "otel"
Requires-Dist: opentelemetry-instrumentation-aiohttp-client>=0.42b0; extra == "otel"
Requires-Dist: opentelemetry-semantic-conventions>=0.42b0; extra == "otel"

# NucliaDB Telemetry

Open telemetry compatible plugin to propagate traceid on FastAPI, Nats and GRPC with Asyncio.

ENV vars:

```
    JAEGER_ENABLED = True
    JAEGER_HOST = "127.0.0.1"
    JAEGER_PORT = server.port
```

On FastAPI you should add:

```python
    tracer_provider = get_telemetry("HTTP_SERVICE")
    app = FastAPI(title="Test API")  # type: ignore
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)

    set_global_textmap(B3MultiFormat())
    FastAPIInstrumentor.instrument_app(app, tracer_provider=tracer_provider)

    ..
    await init_telemetry(tracer_provider)  # To start asyncio task
    ..

```

On GRPC Server you should add:

```python
    tracer_provider = get_telemetry("GRPC_SERVER_SERVICE")
    telemetry_grpc = GRPCTelemetry("GRPC_CLIENT_SERVICE", tracer_provider)
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)

    set_global_textmap(B3MultiFormat())
    server = telemetry_grpc.init_server()
    helloworld_pb2_grpc.add_GreeterServicer_to_server(SERVICER, server)

    ..
    await init_telemetry(tracer_provider)  # To start asyncio task
    ..
```

On GRPC Client you should add:

```python
    tracer_provider = get_telemetry("GRPC_CLIENT_SERVICE")
    telemetry_grpc = GRPCTelemetry("GRPC_CLIENT_SERVICE", tracer_provider)
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)

    set_global_textmap(B3MultiFormat())
    channel = telemetry_grpc.init_client(f"localhost:{grpc_service}")
    stub = helloworld_pb2_grpc.GreeterStub(channel)

    ..
    await init_telemetry(tracer_provider)  # To start asyncio task
    ..

```

On Nats jetstream push subscriber you should add:

```python
    nc = await nats.connect(servers=[self.natsd])
    js = self.nc.jetstream()
    tracer_provider = get_telemetry("NATS_SERVICE")
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)
    set_global_textmap(B3MultiFormat())
    jsotel = JetStreamContextTelemetry(
        js, "NATS_SERVICE", tracer_provider
    )

    subscription = await jsotel.subscribe(
        subject="testing.telemetry",
        stream="testing",
        cb=handler,
    )

```

On Nats publisher you should add:

```python
    nc = await nats.connect(servers=[self.natsd])
    js = self.nc.jetstream()
    tracer_provider = get_telemetry("NATS_SERVICE")
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)

    set_global_textmap(B3MultiFormat())
    jsotel = JetStreamContextTelemetry(
        js, "NATS_SERVICE", tracer_provider
    )

     await jsotel.publish("testing.telemetry", request.name.encode())

```


On Nats jetstream pull subscription you can use different patterns if you want to
just get one message and exit or pull several ones. For just one message

```python
    nc = await nats.connect(servers=[self.natsd])
    js = self.nc.jetstream()
    tracer_provider = get_telemetry("NATS_SERVICE")
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)
    set_global_textmap(B3MultiFormat())
    jsotel = JetStreamContextTelemetry(
        js, "NATS_SERVICE", tracer_provider
    )

    # You can use either pull_subscribe or pull_subscribe_bind
    subscription = await jsotel.pull_subscribe(
        subject="testing.telemetry",
        durable="consumer_name"
        stream="testing",
    )

    async def callback(message):
        # Do something with your message
        # and optionally return something
        return True

    try:
        result = await jsotel.pull_one(subscription, callback)
    except errors.TimeoutError
        pass

```
For multiple messages just wrap it in a loop:

```python
    while True:
        try:
            result = await jsotel.pull_one(subscription, callback)
        except errors.TimeoutError
            pass

```


On Nats client (NO Jestream! ) publisher you should add:

```python
    nc = await nats.connect(servers=[self.natsd])
    js = self.nc.jetstream()
    tracer_provider = get_telemetry("NATS_SERVICE")
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)

    set_global_textmap(B3MultiFormat())
    ncotel = NatsClientTelemetry(
        nc, "NATS_SERVICE", tracer_provider
    )

     await ncotel.publish("testing.telemetry", request.name.encode())

```

On Nats client (NO Jestream! ) subscriber you should add:

```python
    nc = await nats.connect(servers=[self.natsd])
    js = self.nc.jetstream()
    tracer_provider = get_telemetry("NATS_SERVICE")
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)
    set_global_textmap(B3MultiFormat())
    ncotel = NatsClientContextTelemetry(
        js, "NATS_SERVICE", tracer_provider
    )

    subscription = await ncotel.subscribe(
        subject="testing.telemetry",
        queue="queue_nname",
        cb=handler,
    )

```


On Nats client (NO Jestream! ) request you should add:

```python
    nc = await nats.connect(servers=[self.natsd])
    js = self.nc.jetstream()
    tracer_provider = get_telemetry("NATS_SERVICE")
    if not tracer_provider.initialized:
        await init_telemetry(tracer_provider)

    set_global_textmap(B3MultiFormat())
    ncotel = NatsClientTelemetry(
        nc, "NATS_SERVICE", tracer_provider
    )

    response = await ncotel.request("testing.telemetry", request.name.encode())

```

And to handle responses on the other side, you can use the same pattern as in plain Nats client
subscriber, just adding the `msg.respond()` on the handler when done
