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, Requests, OpenAI, Anthropic, Bedrock, and Google Generative AI instrumentation.
Installation
Prerequisites
- Python 3.11-3.13 - Install here
- Pip (if using pip) - Install here
- Poetry 2.1.3+ (if using Poetry) - Install here
- uv (if using uv) - Install here
- Git (if using Git) - Install here
- For git installation, access to the GDP Labs SDK github repository
1. Installation from Pypi
Choose one of the following methods to install the package:
Using pip
pip install gl-observability-binary[all]
Using Poetry
poetry add gl-observability-binary[all]
Using uv
uv add gl-observability-binary[all]
2. Development Installation (Git)
For development purposes, you can install directly from the Git repository:
poetry add "git+ssh://git@github.com/GDP-ADMIN/gl-sdk.git#subdirectory=libs/gl-observability" --extras all
Optional Dependencies
The OTel instrumentor packages for FastAPI, Langchain, HTTPX, Requests, OpenAI, Anthropic, Bedrock, and Google Generative AI are bundled in core. HTTPX, Requests, and all LLM providers (OpenAI, Anthropic, Bedrock, Google Generative AI) are enabled by default — use_httpx and use_requests default to True, and use_llm (which covers all four LLM providers together) defaults to True. Set any flag to False to disable that integration. Langchain and FastAPI follow the same use_* pattern (use_langchain defaults to False; FastAPI runs when fastapi_config is set).
Each instrumentor must run against a compatible version of the library it traces. If you hit a DependencyConflictError at startup, it means your installed library version falls outside the range the bundled instrumentor supports.
The optional extras solve this by pulling in the instrumented library at a version that is known to be compatible with the bundled instrumentor. Use them as a version resolver, not as a feature flag.
| Extra | Installs |
|---|---|
fastapi |
fastapi at a compatible version |
langchain |
langchain at a compatible version |
httpx |
httpx at a compatible version |
requests |
requests at a compatible version |
llm |
openai, anthropic, boto3, google-generativeai at compatible versions |
all |
All libraries above |
Install a specific extra via gl-observability-binary:
# pip
pip install "gl-observability-binary[langchain]"
# Poetry
poetry add "gl-observability-binary[langchain]"
# uv
uv add "gl-observability-binary[langchain]"
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).
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 (default: False)
# use_httpx, use_requests, and use_llm default to True; set to False to disable.
)
# 4. Initialize Telemetry
init_telemetry(otel_config)
Sentry Configuration
This setup sends errors and traces to Sentry.
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 (default: False)
# use_httpx, use_requests, and use_llm default to True; set to False to disable.
)
# 4. Initialize Telemetry
init_telemetry(otel_config)
Multiple Backend Configuration
This setup the OpenTelemetry SDK used for tracing.
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,
use_llm=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
)
)
Masking policy and failure reporting
Import the public masking API from gl_observability:
| Purpose | Public names |
|---|---|
| Configure scrubbing | MaskingConfig, MaskingRule, BuiltInMaskingRule, DenyFields, MaskingMode |
| Consume failure reports | MaskingReport, MaskingFailureGroup, MaskingPatternSource, OnReportHook |
| Reuse default reporting | masking_config_default_on_report |
| Reuse policy defaults | DEFAULT_RULES, DEFAULT_MASKING_CONFIG, EMPTY_DENY_FIELDS |
from gl_observability import (
DEFAULT_RULES,
EMPTY_DENY_FIELDS,
BuiltInMaskingRule,
MaskingConfig,
MaskingMode,
MaskingRule,
)
masking_config = MaskingConfig(
rules=DEFAULT_RULES + (MaskingRule(name="CUSTOM_ID", pattern=r"customer-\d+"),),
deny_fields=EMPTY_DENY_FIELDS,
mode=MaskingMode.FAIL_CLOSED,
)
# Select individual built-ins directly; an explicit tuple replaces the defaults.
email_only = MaskingConfig(rules=(BuiltInMaskingRule.EMAIL,))
# Pass masking_config to TelemetryConfig(masking_config=masking_config, ...).
BuiltInMaskingRule.PRIVATE_KEY_BLOCK masks from a recognized BEGIN … PRIVATE KEY
header through the first END … PRIVATE KEY delimiter, regardless of label. If no
closing delimiter exists, it masks the rest of that string, including any trailing
text or serialized JSON punctuation. Text after a complete block is preserved.
Masking is enabled by default. TelemetryConfig(masking_config=None) disables it.
A policy with both rules=() and deny_fields.fields=() also skips compilation and
installs no masking wrapper or stage: no masking traversal, reports, or FAIL_OPEN
warning occurs. Rule-only and deny-only policies remain active, including a deny
pattern of "", which matches every attribute key.
OTLP masks span names and span attributes, including string sequences. Sentry masks
child-span data, op, and description; root contexts.trace.data, op, and
description; root contexts.otel.attributes; the transaction name and its
contexts.trace.dynamic_sampling_context.transaction copy; and
recursive string leaves in transaction request and user regions. Names,
operations, and descriptions use the configured value rules only, without
attribute-key denial. SQL and URL text copied into descriptions is masked too.
The sampling transaction name is scrubbed before Sentry moves it into the envelope
header; other sampling metadata remains unchanged.
Both backends preserve resources. OTLP events, links, status and instrumentation metadata, and Sentry other contexts, tags, extra, breadcrumbs and error events are outside this masking stage. Independent SDK scrubbing and consumer hooks may still change those fields.
Behavior change: Matching text in OTel span names and Sentry operations and
transaction names is now redacted; Sentry description masking is retained.
For example, both data["db.statement"] and its copied description become
SELECT * FROM users WHERE email = '[EMAIL]'. An HTTP description becomes
GET api.internal /reset?[GENERIC_CREDENTIAL_KV] when its target contains
token=abc123456789. Ordinary operation labels remain unchanged, but matching
names/operations may change dashboard grouping. These fields use the same
FAIL_CLOSED / FAIL_OPEN behavior as other covered values.
Sentry resources previously masked by this component now pass through unchanged.
Applications relying on resource masking can sanitize contexts.otel.resource
in a consumer before_send_transaction hook supplied through SentryBackendConfig.
The hook runs after this component's masking stage. Regex rules still have false
positives and false negatives; this coverage does not guarantee removal of every
sensitive value.
Deny fields apply only to attribute keys, before value rules, using Python
re.match prefix semantics. Matching is case-sensitive unless flags are supplied:
email does not deny user.email, while user\.email$ does. Denied values keep the
configured deny mask without value scanning. Request/user keys are never deny-checked.
FAIL_CLOSED replaces a value whose scrubbing raises with [Dropped]. FAIL_OPEN
returns that value unmasked and is intended for non-production debugging. Both modes
continue scrubbing the other values normally. EMPTY_DENY_FIELDS disables key-based
denial; value rules still apply.
on_report receives one MaskingReport per item with masking failures. It defaults to
masking_config_default_on_report; a custom hook replaces it, and None disables reporting.
Hooks must return promptly. A hook exception is caught and diagnostic logging is attempted;
if diagnostic logging raises, that exception may propagate. During context-manager exit,
it may replace a traversal exception, which remains in the exception context chain.
Nested report delivery on the same thread is skipped while a hook runs; masking still applies
and later independent reports can be delivered.
Compiled policies, MaskingSession, MaskingPatternError, DROPPED_VALUE, exporters,
and chain/traversal helpers are internal implementation details. The supported masking API consists of the package-root
imports listed above; deep imports of implementation details have no compatibility guarantee.
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.
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.
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
Metadata
Release files for gl-observability-binary 0.2.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
Total release size: 4.7 MB
Release files / gl_observability_binary-0.2.8-cp313-cp313-win_amd64.whl
| Download URL | gl_observability_binary-0.2.8-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 418.1 kB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
9f1cbacad8b1a5bed4274cc7e6ebe0b6e91b82c6bc636391150a28aa8a803fe8
|
|
BLAKE2b-256 checksum How to use checksums |
d7d45729e74e2fb6f5094ae0c1a390abfe1f96040f6d05db28e6cb4f1c7e3929
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logRelease files / gl_observability_binary-0.2.8-cp313-cp313-manylinux_2_31_x86_64.whl
| Download URL | gl_observability_binary-0.2.8-cp313-cp313-manylinux_2_31_x86_64.whl |
|---|---|
| Size | 712.9 kB |
| Tags | CPython 3.13 Linux glibc 2.31+ x86-64 |
|
SHA-256 checksum How to use checksums |
b54480850695f13cc89532640d4971ccd65a86e8762aca7c6a451cc0d9ce0750
|
|
BLAKE2b-256 checksum How to use checksums |
8dd9ef60eb4b17e7f9d93c7b7bbea726ef5c1d37b9e9f2726ec801af300a3e9e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.8.24
|
Release files / gl_observability_binary-0.2.8-cp313-cp313-macosx_13_0_arm64.whl
| Download URL | gl_observability_binary-0.2.8-cp313-cp313-macosx_13_0_arm64.whl |
|---|---|
| Size | 475.7 kB |
| Tags | CPython 3.13 macOS 13.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
4c850932a389ab5bc656ab535a23acb3cde97db9d625c27d03109673c6805241
|
|
BLAKE2b-256 checksum How to use checksums |
f7c4da3de635b431f5e73950babb907f89c7c1da5fc94f0fb710d452295b8418
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logRelease files / gl_observability_binary-0.2.8-cp312-cp312-win_amd64.whl
| Download URL | gl_observability_binary-0.2.8-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 418.6 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
4d13cab496e590c9d789b34bf23fd21a1b3a62d6e0938e11a0d5bc522a713925
|
|
BLAKE2b-256 checksum How to use checksums |
49511eed7d72d09e084ccc19f134b757093c7016e296ec4ee15afa561ba3862f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logRelease files / gl_observability_binary-0.2.8-cp312-cp312-manylinux_2_31_x86_64.whl
| Download URL | gl_observability_binary-0.2.8-cp312-cp312-manylinux_2_31_x86_64.whl |
|---|---|
| Size | 708.7 kB |
| Tags | CPython 3.12 Linux glibc 2.31+ x86-64 |
|
SHA-256 checksum How to use checksums |
2a744b290af6152b7fe307ccd896afe29861310bdc35b9e99bd24730448f872f
|
|
BLAKE2b-256 checksum How to use checksums |
0db7c84e6b816f5d8783c8faca64e3e1957a844ca0fbe2f996ff32d42daf8a1b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.8.24
|
Release files / gl_observability_binary-0.2.8-cp312-cp312-macosx_13_0_arm64.whl
| Download URL | gl_observability_binary-0.2.8-cp312-cp312-macosx_13_0_arm64.whl |
|---|---|
| Size | 462.8 kB |
| Tags | CPython 3.12 macOS 13.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
7153474fa6da37f1e903c7c147cefd29cf22c07bd1919f9b47ee09f76cfc3258
|
|
BLAKE2b-256 checksum How to use checksums |
372479d00f731f5c69f4694607de13405786daef24d60fe79a903d2b82bafbfb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logRelease files / gl_observability_binary-0.2.8-cp311-cp311-win_amd64.whl
| Download URL | gl_observability_binary-0.2.8-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 435.8 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
e856cdce7dffa5d4a434c9955afc3a1e8d2a611f2338b57012a4571b0b5b37d3
|
|
BLAKE2b-256 checksum How to use checksums |
985acc35ac19255393116a1b535869722ec7dbbb28a0689c5c69c738e2cbc1a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency logRelease files / gl_observability_binary-0.2.8-cp311-cp311-manylinux_2_31_x86_64.whl
| Download URL | gl_observability_binary-0.2.8-cp311-cp311-manylinux_2_31_x86_64.whl |
|---|---|
| Size | 646.5 kB |
| Tags | CPython 3.11 Linux glibc 2.31+ x86-64 |
|
SHA-256 checksum How to use checksums |
ff66a9ecd3170d9b6bec8e083f62361915dd3762d5922d367c6560b232ff9ef7
|
|
BLAKE2b-256 checksum How to use checksums |
a70d3716442970c1fc870ca8ef22c2ea21623125cae286ec8c6a7f0321cb8946
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.8.24
|
Release files / gl_observability_binary-0.2.8-cp311-cp311-macosx_13_0_arm64.whl
| Download URL | gl_observability_binary-0.2.8-cp311-cp311-macosx_13_0_arm64.whl |
|---|---|
| Size | 461.1 kB |
| Tags | CPython 3.11 macOS 13.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
6f44c042c8d2f8907b54fd52771309011aee058e92d7a69d72a9031dd881a159
|
|
BLAKE2b-256 checksum How to use checksums |
9a3702445d247c2ec3c7d3a8cb840aee5744772c3bf6dc93f35860abdea550ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.
Transparency log