Metadata-Version: 2.2
Name: gl-observability-binary
Version: 0.1.2
Summary: SDK for Observability tools
Author-email: HansSeanNathanael <hans.s.nathanael@gdplabs.id>
Requires-Python: <3.14,>=3.11
Description-Content-Type: text/markdown
Requires-Dist: fastapi<1.0.0,>=0.115.6
Requires-Dist: requests<3.0.0,>=2.31.0
Requires-Dist: httpx<1.0.0,>=0.27.0
Requires-Dist: langchain-core<1.0.0,>=0.3
Requires-Dist: sentry-sdk<3.0.0,>=2.20.0
Requires-Dist: opentelemetry-api
Requires-Dist: opentelemetry-sdk
Requires-Dist: opentelemetry-exporter-otlp-proto-http
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc
Requires-Dist: opentelemetry-instrumentation-fastapi
Requires-Dist: opentelemetry-instrumentation-langchain
Requires-Dist: opentelemetry-instrumentation-requests
Requires-Dist: opentelemetry-instrumentation-httpx
Requires-Dist: opentelemetry-instrumentation-logging
Provides-Extra: dev
Requires-Dist: pytest<9.0.0,>=8.3.4; extra == "dev"
Requires-Dist: pre-commit<4.0.0,>=3.7.0; extra == "dev"
Requires-Dist: pytest-cov<6.0.0,>=5.0.0; extra == "dev"
Requires-Dist: pytest-asyncio<1.0.0,>=0.25.3; extra == "dev"
Requires-Dist: pytest-mock<4.0.0,>=3.14.0; extra == "dev"
Requires-Dist: coverage<8.0.0,>=7.6.10; extra == "dev"
Requires-Dist: mypy<2.0.0,>=1.11.2; extra == "dev"
Requires-Dist: ruff<1.0.0,>=0.11.12; extra == "dev"

# GL Observability

`gl-observability` is a comprehensive SDK for implementing observability in Python applications. It provides easy-to-use wrappers for OpenTelemetry, Sentry, and custom logging handlers with PII redaction capabilities.

## Key Features

- 📊 **OpenTelemetry Integration**: simplified initialization for tracing.
- 🛡️ **Sentry Support**: easy setup for error tracking and performance monitoring.
- 🕵️ **PII Redaction**: custom logging handlers to redact PII using Regex or NER (Named Entity Recognition).
- 🔌 **Framework Support**: built-in support for FastAPI, Langchain, HTTPX, and Requests instrumentation.

## Installation

### Prerequisites

- Python 3.11-3.13 - [Install here](https://www.python.org/downloads/)
- Pip (if using pip) - [Install here](https://pip.pypa.io/en/stable/installation/)
- Poetry 2.1.3+ (if using Poetry) - [Install here](https://python-poetry.org/docs/#installation)
- uv (if using uv) - [Install here](https://docs.astral.sh/uv/guides/install-python/)
- Git (if using Git) - [Install here](https://git-scm.com/downloads)
- For git installation, access to the [GDP Labs SDK github repository](https://github.com/GDP-ADMIN/gl-sdk)

### 1. Installation from Pypi

Choose one of the following methods to install the package:

#### Using pip

```bash
pip install gl-observability-binary
```

#### Using Poetry

```bash
poetry add gl-observability-binary
```

#### Using uv

```bash
uv add gl-observability-binary
```

### 2. Development Installation (Git)

For development purposes, you can install directly from the Git repository:

```bash
poetry add "git+ssh://git@github.com/GDP-ADMIN/gl-sdk.git#subdirectory=libs/gl-observability"
```

## Usage

### 1. Telemetry Initialization

The library uses a unified `init_telemetry` function that takes a `TelemetryConfig` object. You can configure it to send traces to OpenTelemetry (OTLP) or Sentry backend. Multiple backend configuration is supported.

#### OpenTelemetry Configuration

This setup sends traces to an external OTLP collector (e.g., Jaeger, Tempo).

```python
from fastapi import FastAPI
from gl_observability import init_telemetry, TelemetryConfig, OpenTelemetryBackendConfig, FastAPIConfig

# 1. Setup FastAPI Config (optional, if using FastAPI)
app = FastAPI()
fastapi_config = FastAPIConfig(app=app)

# 2. Configure OpenTelemetryBackendConfig
otel_backend_config = OpenTelemetryBackendConfig(
    endpoint="localhost:4318",                  # OTLP endpoint
    use_grpc=False,                             # Use gRPC or HTTP
    headers={"Authorization": "Bearer ..."},    # Optional headers
)

# 3. Configure TelemetryConfig
otel_config = TelemetryConfig(
    attributes={"service.name": "..."},         # Resource attributes
    backend_config=otel_backend_config,         # Backend configuration
    fastapi_config=fastapi_config,              # FastAPI Instrumentation
    use_langchain=True,                         # Enable Langchain instrumentation
    use_httpx=True,                             # Enable HTTPX instrumentation
    use_requests=True,                          # Enable Requests instrumentation
)

# 4. Initialize Telemetry
init_telemetry(otel_config)
```

#### Sentry Configuration

This setup sends errors and traces to Sentry.

```python
from fastapi import FastAPI
from gl_observability import init_telemetry, TelemetryConfig, SentryBackendConfig, FastAPIConfig

# 1. Setup FastAPI Config (optional, if using FastAPI)
app = FastAPI()
fastapi_config = FastAPIConfig(app=app)

# 2. Configure SentryBackendConfig
sentry_backend_config = SentryBackendConfig(
    dsn="https://...",
    environment="...",
    release="...",
    send_default_pii=True,
    disable_sentry_distributed_tracing=False
)

# 3. Configure TelemetryConfig
otel_config = TelemetryConfig(
    attributes={"service.name": "..."},         # Resource attributes
    backend_config=sentry_backend_config,       # Backend configuration
    fastapi_config=fastapi_config,              # FastAPI Instrumentation
    use_langchain=True,                         # Enable Langchain instrumentation
    use_httpx=True,                             # Enable HTTPX instrumentation
    use_requests=True,                          # Enable Requests instrumentation
)

# 4. Initialize Telemetry
init_telemetry(otel_config)
```

#### Multiple Backend Configuration

This setup the OpenTelemetry SDK used for tracing.

```python
from fastapi import FastAPI
from gl_observability import init_telemetry, TelemetryConfig, OpenTelemetryBackendConfig, SentryBackendConfig

jaeger_backend = OpenTelemetryBackendConfig(endpoint="jager...", ...)
init_telemetry(
    TelemetryConfig(
        attributes={"service.name": "..."},
        backend_config=jaeger_backend,
        fastapi_config=fastapi_config,
        use_langchain=True,
        use_httpx=True,
        use_requests=True,
    )
)

langfuse_backend = OpenTelemetryBackendConfig(endpoint="langfuse...", ...)
init_telemetry(
    TelemetryConfig(
        backend_config=langfuse_backend
    )
)

sentry_backend = SentryBackendConfig(dsn="https://...", ...)
init_telemetry(
    TelemetryConfig(
        backend_config=sentry_backend
    )
)
```

### 2. Logging Handlers

The library provides logging handlers to automatically redact Personally Identifiable Information (PII) from logs.

#### Regex-based PII Redaction

Uses regular expressions to mask common PII patterns like KTP, NPWP, Phone Numbers, and Email.

```python
import logging
from gl_observability.logs.regex_pii_logger_handler import init_regex_pii_logging_handler

# Initialize the handler for a specific logger
init_regex_pii_logging_handler(
    logger_name="my_application_logger",
    pii_regex_process_enabled=True
)

logger = logging.getLogger("my_application_logger")
logger.info("User email is john.doe@example.com and phone is 08123456789")
# Output: User email is jo******om and phone is 0812******6789
```

#### NER-based PII Redaction (Named Entity Recognition)

Uses an external API to perform Named Entity Recognition for more advanced PII detection and redaction.

> [!WARNING]
> The NER logging handler makes synchronous API calls for each log record, which may impact performance.

```python
import logging
from gl_observability.logs.ner_pii_logger_handler import init_ner_pii_logging_handler

# Initialize the handler
init_ner_pii_logging_handler(
    logger_name="my_application_logger",
    api_url="https://your-ner-api.com/anonymize",
    api_field="text",  # The field name in API response containing the redacted text
    pii_ner_process_enabled=True
)

logger = logging.getLogger("my_application_logger")
logger.info("My KTP is 3525011212941001")
# Output will be redacted based on API response
```
