Name | tn-observer JSON |
Version |
0.5.6
JSON |
| download |
home_page | None |
Summary | library for data observerability in our company THiNKNET via opentelemetry |
upload_time | 2024-07-05 08:20:19 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.7 |
license | None |
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"
}