blipit 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- blipit-0.1.0/.gitignore +12 -0
- blipit-0.1.0/PKG-INFO +55 -0
- blipit-0.1.0/README.md +36 -0
- blipit-0.1.0/blipit/__init__.py +75 -0
- blipit-0.1.0/pyproject.toml +29 -0
- blipit-0.1.0/tests/test_blipit.py +45 -0
blipit-0.1.0/.gitignore
ADDED
blipit-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: blipit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Blipit error monitoring for Python: Django, Flask, FastAPI, Celery and scripts. Know your app broke before your users tell you.
|
|
5
|
+
Project-URL: Homepage, https://blipit.io
|
|
6
|
+
Project-URL: Documentation, https://docs.blipit.io/python
|
|
7
|
+
Project-URL: Changelog, https://blipit.io/changelog
|
|
8
|
+
Author-email: Louward Labs <support@blipit.io>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: blipit,django,error-monitoring,errors,fastapi,flask,logging
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: System :: Monitoring
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
|
+
Requires-Dist: sentry-sdk>=2.0
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# blipit
|
|
21
|
+
|
|
22
|
+
Blipit error monitoring for Python. Know your app broke before your users tell you.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
pip install blipit
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
Call `init` once at startup, before the app is created. For Django, put it at the top of `settings.py`.
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import blipit
|
|
36
|
+
|
|
37
|
+
blipit.init(key="<public key>", project=<project id>, environment="production", release="myapp@1.4.2")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Both values are on the project's Keys page at app.blipit.io. Unhandled exceptions are reported on their own; Django, Flask, FastAPI, Celery, SQLAlchemy and other integrations are detected automatically.
|
|
41
|
+
|
|
42
|
+
## Manual capture
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
blipit.capture_exception(err)
|
|
46
|
+
blipit.capture_message("cache miss rate above 50%", level="warning")
|
|
47
|
+
blipit.set_user({"id": "42", "email": "ana@example.com"})
|
|
48
|
+
blipit.set_tag("region", "ap-southeast-1")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Performance
|
|
52
|
+
|
|
53
|
+
Pass `traces_sample_rate=0.2` to `init` and requests show up on the Performance page.
|
|
54
|
+
|
|
55
|
+
Docs: https://docs.blipit.io/python
|
blipit-0.1.0/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# blipit
|
|
2
|
+
|
|
3
|
+
Blipit error monitoring for Python. Know your app broke before your users tell you.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pip install blipit
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
Call `init` once at startup, before the app is created. For Django, put it at the top of `settings.py`.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import blipit
|
|
17
|
+
|
|
18
|
+
blipit.init(key="<public key>", project=<project id>, environment="production", release="myapp@1.4.2")
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Both values are on the project's Keys page at app.blipit.io. Unhandled exceptions are reported on their own; Django, Flask, FastAPI, Celery, SQLAlchemy and other integrations are detected automatically.
|
|
22
|
+
|
|
23
|
+
## Manual capture
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
blipit.capture_exception(err)
|
|
27
|
+
blipit.capture_message("cache miss rate above 50%", level="warning")
|
|
28
|
+
blipit.set_user({"id": "42", "email": "ana@example.com"})
|
|
29
|
+
blipit.set_tag("region", "ap-southeast-1")
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Performance
|
|
33
|
+
|
|
34
|
+
Pass `traces_sample_rate=0.2` to `init` and requests show up on the Performance page.
|
|
35
|
+
|
|
36
|
+
Docs: https://docs.blipit.io/python
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
import sentry_sdk
|
|
6
|
+
from sentry_sdk import add_breadcrumb, capture_exception, capture_message, set_tag, set_user
|
|
7
|
+
|
|
8
|
+
DEFAULT_ENDPOINT = "https://in.blipit.io"
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"init",
|
|
12
|
+
"capture_exception",
|
|
13
|
+
"capture_message",
|
|
14
|
+
"capture_security",
|
|
15
|
+
"set_user",
|
|
16
|
+
"set_tag",
|
|
17
|
+
"add_breadcrumb",
|
|
18
|
+
"flush",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def dsn(key: str, project: int | str, endpoint: str = DEFAULT_ENDPOINT) -> str:
|
|
23
|
+
host = endpoint.split("://", 1)[-1].rstrip("/")
|
|
24
|
+
scheme = "http" if endpoint.startswith("http://") else "https"
|
|
25
|
+
return f"{scheme}://{key}@{host}/{project}"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def init(
|
|
29
|
+
key: str,
|
|
30
|
+
project: int | str,
|
|
31
|
+
environment: Optional[str] = None,
|
|
32
|
+
release: Optional[str] = None,
|
|
33
|
+
traces_sample_rate: float = 0.0,
|
|
34
|
+
endpoint: str = DEFAULT_ENDPOINT,
|
|
35
|
+
**options: Any,
|
|
36
|
+
) -> None:
|
|
37
|
+
if not key:
|
|
38
|
+
raise ValueError("blipit.init needs the project's public key")
|
|
39
|
+
options.setdefault("send_default_pii", False)
|
|
40
|
+
sentry_sdk.init(
|
|
41
|
+
dsn=dsn(key, project, endpoint),
|
|
42
|
+
environment=environment,
|
|
43
|
+
release=release,
|
|
44
|
+
traces_sample_rate=traces_sample_rate,
|
|
45
|
+
**options,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def capture_security(
|
|
50
|
+
kind: str,
|
|
51
|
+
actor: str,
|
|
52
|
+
outcome: Optional[str] = None,
|
|
53
|
+
actor_id: Optional[str] = None,
|
|
54
|
+
ip: Optional[str] = None,
|
|
55
|
+
user_agent: Optional[str] = None,
|
|
56
|
+
target: Optional[str] = None,
|
|
57
|
+
) -> None:
|
|
58
|
+
payload = {
|
|
59
|
+
"kind": kind,
|
|
60
|
+
"actor": actor,
|
|
61
|
+
"outcome": outcome,
|
|
62
|
+
"actor_id": actor_id,
|
|
63
|
+
"ip": ip,
|
|
64
|
+
"user_agent": user_agent,
|
|
65
|
+
"target": target,
|
|
66
|
+
}
|
|
67
|
+
with sentry_sdk.new_scope() as scope:
|
|
68
|
+
scope.set_context("security", {k: v for k, v in payload.items() if v is not None})
|
|
69
|
+
scope.set_tag("security.kind", kind)
|
|
70
|
+
level = "warning" if kind in ("login_failed", "login_blocked") else "info"
|
|
71
|
+
capture_message(f"{kind} for {actor}", level=level)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def flush(timeout: float = 2.0) -> None:
|
|
75
|
+
sentry_sdk.flush(timeout)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "blipit"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Blipit error monitoring for Python: Django, Flask, FastAPI, Celery and scripts. Know your app broke before your users tell you."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [{ name = "Louward Labs", email = "support@blipit.io" }]
|
|
13
|
+
keywords = ["error-monitoring", "errors", "logging", "blipit", "django", "flask", "fastapi"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: System :: Monitoring",
|
|
20
|
+
]
|
|
21
|
+
dependencies = ["sentry-sdk>=2.0"]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://blipit.io"
|
|
25
|
+
Documentation = "https://docs.blipit.io/python"
|
|
26
|
+
Changelog = "https://blipit.io/changelog"
|
|
27
|
+
|
|
28
|
+
[tool.hatch.build.targets.wheel]
|
|
29
|
+
packages = ["blipit"]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import threading
|
|
3
|
+
import zlib
|
|
4
|
+
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
5
|
+
|
|
6
|
+
import blipit
|
|
7
|
+
|
|
8
|
+
received = []
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Handler(BaseHTTPRequestHandler):
|
|
12
|
+
def do_POST(self):
|
|
13
|
+
body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
|
|
14
|
+
if self.headers.get("Content-Encoding") == "gzip":
|
|
15
|
+
body = zlib.decompress(body, 16 + zlib.MAX_WBITS)
|
|
16
|
+
received.append((self.path, body))
|
|
17
|
+
self.send_response(200)
|
|
18
|
+
self.end_headers()
|
|
19
|
+
self.wfile.write(b"{}")
|
|
20
|
+
|
|
21
|
+
def log_message(self, *args):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_events_reach_blipit():
|
|
26
|
+
srv = HTTPServer(("127.0.0.1", 0), Handler)
|
|
27
|
+
threading.Thread(target=srv.serve_forever, daemon=True).start()
|
|
28
|
+
port = srv.server_address[1]
|
|
29
|
+
assert blipit.dsn("blipit_pk_abc", 7) == "https://blipit_pk_abc@in.blipit.io/7"
|
|
30
|
+
blipit.init(key="blipit_pk_abc", project=7, environment="test", endpoint=f"http://127.0.0.1:{port}")
|
|
31
|
+
blipit.capture_message("hello from python")
|
|
32
|
+
blipit.flush()
|
|
33
|
+
assert received, "nothing was sent"
|
|
34
|
+
path, body = received[0]
|
|
35
|
+
assert path == "/api/7/envelope/"
|
|
36
|
+
lines = body.decode().split("\n")
|
|
37
|
+
event = json.loads(lines[2])
|
|
38
|
+
assert event["message"] == "hello from python"
|
|
39
|
+
assert event["environment"] == "test"
|
|
40
|
+
srv.shutdown()
|
|
41
|
+
print("python sdk ok")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
if __name__ == "__main__":
|
|
45
|
+
test_events_reach_blipit()
|