tn-observer


Nametn-observer JSON
Version 0.5.6 PyPI version JSON
download
home_pageNone
Summarylibrary for data observerability in our company THiNKNET via opentelemetry
upload_time2024-07-05 08:20:19
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseNone
keywords thinknet observerability
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # thinknet-observer-python

A library use for collect metrics, log and tracing via opentelemetry.



## Installation
```
pip install tn-observer
```


## Prerequisites
you should these enviroment in your `.env` file, 

```env
OTEL_EXPORTER_OTLP_ENDPOINT="[OTEL_ENDPOINT]"
APP_VERSION="[APP_VERSION]"
SERVICE_NAME_PREFIX="[SERVICE_NAME_PREFIX]"
SERVICE_NAME="[SERVICE_NAME]"
LOG_LEVEL="info"
OTEL_DISABLE_TRACE="False" or "True"
OTEL_PYTHON_EXCLUDED_URLS="hello,testy"

```


## Get started
1. in `main.py` or `server.py` import thinknet observer library
```python
from thinknet_observer import TNObserver
``` 

2. call setup otel 
```python
tn_observer = TNObserver.with_default_service_info()

tracer = TNObserver.setup_trace(__name__, tn_observer.resources)
meter = TNObserver.setup_metrics(__name__, tn_observer.resources)

```



### Flask Instrumentation

```python
# import library
from flask import Flask, request

from thinknet_observer import TNObserver
from thinknet_observer import FlaskLoggerMiddleware

tn_observer = TNObserver.with_default_service_info()

# create web server
app = Flask(__name__)

# trace setup
tracer = TNObserver.setup_trace(__name__, tn_observer.resources)
# instrument flask
TNObserver.flask_instrumentation(app)
# logging and metric setup
FlaskObserverMiddleware(app, tn_observer.resources)
```

### FastAPI Instrumentation

```python
# import libraries
from fastapi import FastAPI, APIRouter

from thinknet_observer import TNObserver
from thinknet_observer import FastAPILogger

tn_observer = TNObserver.with_default_service_info()

app = FastAPI()
# for access log #
app.add_middleware(FastObserverMiddleware,  resource=tn_observer.resources)
# handle error #
router = APIRouter(route_class=FastAPILogger)

TNObserver.register_metrics(app, tn_observer.resources)
# instrument fastaPI
TNObserver.fast_instrumentation(app)
...

```


### pymongo instrumentation
insert the commands to `mongo.py` or file with use pymongo 
ex.

```python
from thinknet_observer import TNObserver

TNObserver.pymongo_instrumentation()
client = pymongo.MongoClient(MONGO_URI)

```

### requests instrumentation
when use lib requests to connect other services or graphQL
example

```python
import requests
from thinknet_observer import TNObserver

TNObserver.requests_instrumentation()
res = request.get(url)

```

### kafka instrumentation

```python
from thinknet_observer import TNObserver
from kafka import KafkaProducer, KafkaConsumer

TNObserver.kafka_instrumentation()

producer = KafkaProducer(bootstrap_servers=["KAFKA_HOST"])
...
```

### rabbitmq instrumentation
```python
import pika
from thinknet_observer import TNObserver

TNObserver.pika_instrumentation()

connection = pika.BlockingConnection(pika.URLParameters("mq_host"))
channel = connection.channel()

```

or instrumentation single channel
```python 
import pika
from thinknet_observer import TNObserver

connection = pika.BlockingConnection(pika.URLParameters("mq_host"))
channel = connection.channel()
channel.queue_declare(queue='mq_channel')

mq_instrumentor = TNObserver.pika_instrumentor()
mq_instrumentor.instrument_channel(channel=channel)
...

mq_instrumentor.uninstrument_channel(channel=channel)

```



### LOGGING

```python
from thinknet_observer import TNLogger, TNObserver

# use if service name and service version in env #
tn_observer = TNObserver.with_default_service_info()

# use if not service name and service version in env #
tn_observer = TNObserver(service_name, service_version)

logger = TNLogger("NAME", resource=tn_observer.resources)
logger.info("start consumer")

logger.info("extra attribute", extra={'a':1})

```

#### error logging

1. in file such as `error.py`

```
from thinknet_observer import TNAPIError

class DatabaseError(TNAPIError):
    http_status = 404
    message = "service can't connect database."

```
2. in controller

```
try:
    .....
except Exception as exc:
    raise DatabaseError(service_code="service can't connect database.")
```


### custom tracing

```python
from thinknet_observer import TNObserver

tracer = TNObserver.setup_trace(__name__, tn_observer.resources)

#sample function
def do_roll():
    with tracer.start_as_current_span("do_roll") as rollspan:
        res =  randint(1, 6)
        rollspan.set_attribute("roll.value", res)

```

### custom metrics

#### counter
```python
from  thinknet_observer  import  MetricCollector


CUSTOM_COUNTER = MetricCollector.counter(
    "CUSTOM_COUNTER", "desc of CUSTOM_COUNTER", ["something"]
)
CUSTOM_COUNTER_NOLABEL = MetricCollector.counter(
    "CUSTOM_COUNTER_NOLABEL", "desc of CUSTOM_COUNTER_NOLABEL"
)

# example to use count
@app.route("/count/<number>", methods=["POST"])
def count_metric(number):
    CUSTOM_COUNTER.labels("something's value").inc(float(number))
    CUSTOM_COUNTER_NOLABEL.inc(float(number))
    return {"msg": f"count {number}"}

```


#### gauge

```python
from thinknet_observer  import  MetricCollector

# NOTE: metrics name(1st param) must be unique for each metrics

# Custom gauge 
# (for gauge metrics if using multiprocess add param 'multiprocess_mode="livesum"')
CUSTOM_GAUGE = MetricCollector.gauge(
    "CUSTOM_GAUGE", "desc of CUSTOM_GAUGE", ["something"]
)
CUSTOM_GAUGE_NOLABEL = MetricCollector.gauge(
    "CUSTOM_GAUGE_NOLABEL", "desc of CUSTOM_GAUGE_NOLABEL"
)

# example to use gauge in function
@app.route("/inc_gauge/<number>", methods=["POST"])
def inc_gauge(number):
    CUSTOM_GAUGE.labels("something's value").inc(float(number))
    CUSTOM_GAUGE_NOLABEL.inc(float(number))
    return {"msg": f"inc {number}"}

@app_flask.route("/dec_gauge/<number>", methods=["POST"])
def dec_gauge(number):
    CUSTOM_GAUGE.labels("something's value").dec(float(number))
    CUSTOM_GAUGE_NOLABEL.dec(float(number))
    return {"msg": f"dec {number}"}

```

#### histogram

```python
from thinknet_observer import MetricCollector

# Custom histogram
CUSTOM_HISTOGRAM = MetricCollector.histogram(
    "CUSTOM_HISTOGRAM", "desc of CUSTOM_HISTOGRAM", ["something"]
)
CUSTOM_HISTOGRAM_NOLABEL = MetricCollector.histogram(
    "CUSTOM_HISTOGRAM_NOLABEL", "desc of CUSTOM_HISTOGRAM_NOLABEL"
)
CUSTOM_HISTOGRAM_NOLABEL_CUSTOMBUCKET = MetricCollector.histogram(
    "CUSTOM_HISTOGRAM_NOLABEL_CUSTOMBUCKET",
    "desc of CUSTOM_HISTOGRAM_NOLABEL_CUSTOMBUCKET",
    buckets=[0.5, 0.75, 1],
)

# example to use histogram
@app_flask.route("/histogram_observe/<number>", methods=["POST"])
def histogram_observe(number):
    CUSTOM_HISTOGRAM.labels("something's value").observe(float(number))
    CUSTOM_HISTOGRAM_NOLABEL.observe(float(number))
    return {"msg": f"histogram_observe {number}"}

@app_flask.route("/histogram_observe2/<number>", methods=["POST"])
def histogram_observe2(number):
    CUSTOM_HISTOGRAM_NOLABEL_CUSTOMBUCKET.observe(float(number))
    return {"msg": f"histogram_observe {number}"}

```

#### summary

```python
from thinknet_observer import  MetricCollector


# Custom summary
CUSTOM_SUMMARY = MetricCollector.summary(
    "CUSTOM_SUMMARY", "desc of CUSTOM_SUMMARY", ["something"]
)
CUSTOM_SUMMARY_NOLABEL = MetricCollector.summary(
    "CUSTOM_SUMMARY_NOLABEL",
    "desc of CUSTOM_SUMMARY_NOLABEL",
)

@app_flask.route("/summary_observe/<number>", methods=["POST"])
def summary_observe(number):
    CUSTOM_SUMMARY.labels("something's value").observe(float(number))
    CUSTOM_SUMMARY_NOLABEL.observe(float(number))
    return {"msg": f"summary_observe {number}"}


```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "tn-observer",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "thinknet, observerability",
    "author": null,
    "author_email": "capukampan <capukampan22@gmail.com>, THiNKNET <sorapol@thinknet.co.th>",
    "download_url": "https://files.pythonhosted.org/packages/81/5e/20bea0af1e20aff5f3eaf861ef4d788640e824c554023631f0e3326a5def/tn_observer-0.5.6.tar.gz",
    "platform": null,
    "description": "# thinknet-observer-python\n\nA library use for collect metrics, log and tracing via opentelemetry.\n\n\n\n## Installation\n```\npip install tn-observer\n```\n\n\n## Prerequisites\nyou should these enviroment in your `.env` file, \n\n```env\nOTEL_EXPORTER_OTLP_ENDPOINT=\"[OTEL_ENDPOINT]\"\nAPP_VERSION=\"[APP_VERSION]\"\nSERVICE_NAME_PREFIX=\"[SERVICE_NAME_PREFIX]\"\nSERVICE_NAME=\"[SERVICE_NAME]\"\nLOG_LEVEL=\"info\"\nOTEL_DISABLE_TRACE=\"False\" or \"True\"\nOTEL_PYTHON_EXCLUDED_URLS=\"hello,testy\"\n\n```\n\n\n## Get started\n1. in `main.py` or `server.py` import thinknet observer library\n```python\nfrom thinknet_observer import TNObserver\n``` \n\n2. call setup otel \n```python\ntn_observer = TNObserver.with_default_service_info()\n\ntracer = TNObserver.setup_trace(__name__, tn_observer.resources)\nmeter = TNObserver.setup_metrics(__name__, tn_observer.resources)\n\n```\n\n\n\n### Flask Instrumentation\n\n```python\n# import library\nfrom flask import Flask, request\n\nfrom thinknet_observer import TNObserver\nfrom thinknet_observer import FlaskLoggerMiddleware\n\ntn_observer = TNObserver.with_default_service_info()\n\n# create web server\napp = Flask(__name__)\n\n# trace setup\ntracer = TNObserver.setup_trace(__name__, tn_observer.resources)\n# instrument flask\nTNObserver.flask_instrumentation(app)\n# logging and metric setup\nFlaskObserverMiddleware(app, tn_observer.resources)\n```\n\n### FastAPI Instrumentation\n\n```python\n# import libraries\nfrom fastapi import FastAPI, APIRouter\n\nfrom thinknet_observer import TNObserver\nfrom thinknet_observer import FastAPILogger\n\ntn_observer = TNObserver.with_default_service_info()\n\napp = FastAPI()\n# for access log #\napp.add_middleware(FastObserverMiddleware,  resource=tn_observer.resources)\n# handle error #\nrouter = APIRouter(route_class=FastAPILogger)\n\nTNObserver.register_metrics(app, tn_observer.resources)\n# instrument fastaPI\nTNObserver.fast_instrumentation(app)\n...\n\n```\n\n\n### pymongo instrumentation\ninsert the commands to `mongo.py` or file with use pymongo \nex.\n\n```python\nfrom thinknet_observer import TNObserver\n\nTNObserver.pymongo_instrumentation()\nclient = pymongo.MongoClient(MONGO_URI)\n\n```\n\n### requests instrumentation\nwhen use lib requests to connect other services or graphQL\nexample\n\n```python\nimport requests\nfrom thinknet_observer import TNObserver\n\nTNObserver.requests_instrumentation()\nres = request.get(url)\n\n```\n\n### kafka instrumentation\n\n```python\nfrom thinknet_observer import TNObserver\nfrom kafka import KafkaProducer, KafkaConsumer\n\nTNObserver.kafka_instrumentation()\n\nproducer = KafkaProducer(bootstrap_servers=[\"KAFKA_HOST\"])\n...\n```\n\n### rabbitmq instrumentation\n```python\nimport pika\nfrom thinknet_observer import TNObserver\n\nTNObserver.pika_instrumentation()\n\nconnection = pika.BlockingConnection(pika.URLParameters(\"mq_host\"))\nchannel = connection.channel()\n\n```\n\nor instrumentation single channel\n```python \nimport pika\nfrom thinknet_observer import TNObserver\n\nconnection = pika.BlockingConnection(pika.URLParameters(\"mq_host\"))\nchannel = connection.channel()\nchannel.queue_declare(queue='mq_channel')\n\nmq_instrumentor = TNObserver.pika_instrumentor()\nmq_instrumentor.instrument_channel(channel=channel)\n...\n\nmq_instrumentor.uninstrument_channel(channel=channel)\n\n```\n\n\n\n### LOGGING\n\n```python\nfrom thinknet_observer import TNLogger, TNObserver\n\n# use if service name and service version in env #\ntn_observer = TNObserver.with_default_service_info()\n\n# use if not service name and service version in env #\ntn_observer = TNObserver(service_name, service_version)\n\nlogger = TNLogger(\"NAME\", resource=tn_observer.resources)\nlogger.info(\"start consumer\")\n\nlogger.info(\"extra attribute\", extra={'a':1})\n\n```\n\n#### error logging\n\n1. in file such as `error.py`\n\n```\nfrom thinknet_observer import TNAPIError\n\nclass DatabaseError(TNAPIError):\n    http_status = 404\n    message = \"service can't connect database.\"\n\n```\n2. in controller\n\n```\ntry:\n    .....\nexcept Exception as exc:\n    raise DatabaseError(service_code=\"service can't connect database.\")\n```\n\n\n### custom tracing\n\n```python\nfrom thinknet_observer import TNObserver\n\ntracer = TNObserver.setup_trace(__name__, tn_observer.resources)\n\n#sample function\ndef do_roll():\n    with tracer.start_as_current_span(\"do_roll\") as rollspan:\n        res =  randint(1, 6)\n        rollspan.set_attribute(\"roll.value\", res)\n\n```\n\n### custom metrics\n\n#### counter\n```python\nfrom  thinknet_observer  import  MetricCollector\n\n\nCUSTOM_COUNTER = MetricCollector.counter(\n    \"CUSTOM_COUNTER\", \"desc of CUSTOM_COUNTER\", [\"something\"]\n)\nCUSTOM_COUNTER_NOLABEL = MetricCollector.counter(\n    \"CUSTOM_COUNTER_NOLABEL\", \"desc of CUSTOM_COUNTER_NOLABEL\"\n)\n\n# example to use count\n@app.route(\"/count/<number>\", methods=[\"POST\"])\ndef count_metric(number):\n    CUSTOM_COUNTER.labels(\"something's value\").inc(float(number))\n    CUSTOM_COUNTER_NOLABEL.inc(float(number))\n    return {\"msg\": f\"count {number}\"}\n\n```\n\n\n#### gauge\n\n```python\nfrom thinknet_observer  import  MetricCollector\n\n# NOTE: metrics name(1st param) must be unique for each metrics\n\n# Custom gauge \n# (for gauge metrics if using multiprocess add param 'multiprocess_mode=\"livesum\"')\nCUSTOM_GAUGE = MetricCollector.gauge(\n    \"CUSTOM_GAUGE\", \"desc of CUSTOM_GAUGE\", [\"something\"]\n)\nCUSTOM_GAUGE_NOLABEL = MetricCollector.gauge(\n    \"CUSTOM_GAUGE_NOLABEL\", \"desc of CUSTOM_GAUGE_NOLABEL\"\n)\n\n# example to use gauge in function\n@app.route(\"/inc_gauge/<number>\", methods=[\"POST\"])\ndef inc_gauge(number):\n    CUSTOM_GAUGE.labels(\"something's value\").inc(float(number))\n    CUSTOM_GAUGE_NOLABEL.inc(float(number))\n    return {\"msg\": f\"inc {number}\"}\n\n@app_flask.route(\"/dec_gauge/<number>\", methods=[\"POST\"])\ndef dec_gauge(number):\n    CUSTOM_GAUGE.labels(\"something's value\").dec(float(number))\n    CUSTOM_GAUGE_NOLABEL.dec(float(number))\n    return {\"msg\": f\"dec {number}\"}\n\n```\n\n#### histogram\n\n```python\nfrom thinknet_observer import MetricCollector\n\n# Custom histogram\nCUSTOM_HISTOGRAM = MetricCollector.histogram(\n    \"CUSTOM_HISTOGRAM\", \"desc of CUSTOM_HISTOGRAM\", [\"something\"]\n)\nCUSTOM_HISTOGRAM_NOLABEL = MetricCollector.histogram(\n    \"CUSTOM_HISTOGRAM_NOLABEL\", \"desc of CUSTOM_HISTOGRAM_NOLABEL\"\n)\nCUSTOM_HISTOGRAM_NOLABEL_CUSTOMBUCKET = MetricCollector.histogram(\n    \"CUSTOM_HISTOGRAM_NOLABEL_CUSTOMBUCKET\",\n    \"desc of CUSTOM_HISTOGRAM_NOLABEL_CUSTOMBUCKET\",\n    buckets=[0.5, 0.75, 1],\n)\n\n# example to use histogram\n@app_flask.route(\"/histogram_observe/<number>\", methods=[\"POST\"])\ndef histogram_observe(number):\n    CUSTOM_HISTOGRAM.labels(\"something's value\").observe(float(number))\n    CUSTOM_HISTOGRAM_NOLABEL.observe(float(number))\n    return {\"msg\": f\"histogram_observe {number}\"}\n\n@app_flask.route(\"/histogram_observe2/<number>\", methods=[\"POST\"])\ndef histogram_observe2(number):\n    CUSTOM_HISTOGRAM_NOLABEL_CUSTOMBUCKET.observe(float(number))\n    return {\"msg\": f\"histogram_observe {number}\"}\n\n```\n\n#### summary\n\n```python\nfrom thinknet_observer import  MetricCollector\n\n\n# Custom summary\nCUSTOM_SUMMARY = MetricCollector.summary(\n    \"CUSTOM_SUMMARY\", \"desc of CUSTOM_SUMMARY\", [\"something\"]\n)\nCUSTOM_SUMMARY_NOLABEL = MetricCollector.summary(\n    \"CUSTOM_SUMMARY_NOLABEL\",\n    \"desc of CUSTOM_SUMMARY_NOLABEL\",\n)\n\n@app_flask.route(\"/summary_observe/<number>\", methods=[\"POST\"])\ndef summary_observe(number):\n    CUSTOM_SUMMARY.labels(\"something's value\").observe(float(number))\n    CUSTOM_SUMMARY_NOLABEL.observe(float(number))\n    return {\"msg\": f\"summary_observe {number}\"}\n\n\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "library for data observerability in our company THiNKNET via opentelemetry",
    "version": "0.5.6",
    "project_urls": null,
    "split_keywords": [
        "thinknet",
        " observerability"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "647daf9807d0029c81ce7d29f324dbeef850f3e374340b7690a602e9323f4de3",
                "md5": "114874d8edd0e2327623a5e4af47202d",
                "sha256": "1377ad89f2bebcdc65cad9699b5b2c5aa92b77d522543a22b5f10b49407f9284"
            },
            "downloads": -1,
            "filename": "tn_observer-0.5.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "114874d8edd0e2327623a5e4af47202d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 23754,
            "upload_time": "2024-07-05T08:20:16",
            "upload_time_iso_8601": "2024-07-05T08:20:16.285614Z",
            "url": "https://files.pythonhosted.org/packages/64/7d/af9807d0029c81ce7d29f324dbeef850f3e374340b7690a602e9323f4de3/tn_observer-0.5.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "815e20bea0af1e20aff5f3eaf861ef4d788640e824c554023631f0e3326a5def",
                "md5": "b1a9a71e6b7d6a5f63163a60202a0b3a",
                "sha256": "27e2176445e9b0a0598064a4921fded0fa8ce70faadc1706c3b40d609dec18c9"
            },
            "downloads": -1,
            "filename": "tn_observer-0.5.6.tar.gz",
            "has_sig": false,
            "md5_digest": "b1a9a71e6b7d6a5f63163a60202a0b3a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 25187,
            "upload_time": "2024-07-05T08:20:19",
            "upload_time_iso_8601": "2024-07-05T08:20:19.030825Z",
            "url": "https://files.pythonhosted.org/packages/81/5e/20bea0af1e20aff5f3eaf861ef4d788640e824c554023631f0e3326a5def/tn_observer-0.5.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-07-05 08:20:19",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "tn-observer"
}
        
Elapsed time: 0.31144s