Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ migrations/
db.sqlite3
.vscode
.DS_Store
.venv/
.python-version
64 changes: 26 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,37 @@
- [Running The Demo](#running-the-demo)
- [Cleaning Up](#cleaning-up)


## Installing Dependencies
This project uses Django 2.2 that requires Python 3

1. Install Python 3:
```
brew install python3
1. Install Python:
```bash
brew install python
```

2. Install `virtualenv` and `virtualenvwrapper`
2. Create virtual environment
```bash
python -m venv .venv
```
pip3 install virtualenv virtualenvwrapper
echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrc
exec bash

3. Activate virtual environment
```bash
source .venv/bin/activate
```

3. Install Sentry's command line tool to use release tracking and Github integration for commit data:
```
npm install -g @sentry/cli
```bash
python -m pip install "sentry-cli"
```

This demo uses npm, pip, and virtualenv.

## Configuring Sentry

The Sentry client library requires a [DSN generated from Sentry](https://docs.sentry.io/quickstart/#configure-the-dsn) which specifies the project events will be sent to. Add the import and configuration code to `settings.py`:
The Sentry client library requires a [DSN generated from Sentry](https://docs.sentry.io/quickstart/#configure-the-dsn) which specifies the project events will be sent to. Add the import and configuration code to `settings.py`:

```
```python
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration

sentry_sdk.init(
dsn="https://yourdsn@sentry.io/1234567"
Expand All @@ -41,41 +43,26 @@ sentry_sdk.init(

Further details on configuring Sentry [here](https://docs.sentry.io/platforms/python/django/).

## Running The Demo

Create a python-3 virtualenv (see below) and run `deploy` target in `Makefile`.

### Virtualenv setup

Setup and activate a Python 3 virtual environment in the project root:
```
mkvirtualenv --python=python3 sentry-demo-django
```

To use virtualenv:
```
workon sentry-demo-django
```

## Running The Demo

### Runing Django
Run `deploy` target in `Makefile`. This will install relevant python libraries and run Django server.

Running the following command will install relevant python libraries and run django server
```
```bash
make deploy
```


### Demo Specs

This demo uses Django's rest-framework package and offers 3 API endpoints:
1. http://localhost:8000/handled - generates a runtime error excplicitly reported to Sentry though the SDk's captureException
1. http://localhost:8000/handled - generates a runtime error explicitly reported to Sentry though the SDK's `captureException`
2. http://localhost:8000/unhandled - generates an unhandled runtime error reported
3. http://localhost:8000/checkout - can be used with the [Sentry REACT demo store front demo](https://github.com/sentry-demos/react)
This endpoint can also be used with directly through the Django REST Framework web UI. To generate an error paste the following JSON payload in the POST payload text area:


```
```json
{
"cart": [
{"id": "wrench", "name": "Wrench", "price": 500},
Expand All @@ -87,16 +74,17 @@ This demo uses Django's rest-framework package and offers 3 API endpoints:

![Alt Text](django_demo_setup.gif)


## Cleaning Up

Pressing Ctrl-C once in each terminal window should stop Django's development server.

To deactivate the virtualenv sentry-demo-django:
```
To deactivate the virtual environment:
```bash
deactivate
```

To remove the virtualenv:
```
rmvirtualenv sentry-demo-django
To remove the virtual environment:
```bash
rm -rf .venv/
```
4 changes: 2 additions & 2 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
Expand All @@ -17,5 +17,5 @@ def main():
execute_from_command_line(sys.argv)


if __name__ == '__main__':
if __name__ == "__main__":
main()
File renamed without changes.
2 changes: 1 addition & 1 deletion myapp/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@


class MyappConfig(AppConfig):
name = 'myapp'
name = "myapp"
3 changes: 2 additions & 1 deletion myapp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

# Create your models here.


class Inventory(models.Model):
name = models.TextField(),
name = models.TextField()
count = models.IntegerField()

def __str__(self):
Expand Down
15 changes: 10 additions & 5 deletions myapp/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from django.urls import path, include
from rest_framework import routers, serializers, viewsets

from .views import InventoreyView, HandledErrorView, UnHandledErrorView, CaptureMessageView
from .views import (
InventoreyView,
HandledErrorView,
UnHandledErrorView,
CaptureMessageView,
)


urlpatterns = [
path('checkout', InventoreyView.as_view()),
path('handled', HandledErrorView.as_view()),
path('unhandled', UnHandledErrorView.as_view()),
path('message', CaptureMessageView.as_view()),
path("checkout", InventoreyView.as_view()),
path("handled", HandledErrorView.as_view()),
path("unhandled", UnHandledErrorView.as_view()),
path("message", CaptureMessageView.as_view()),
]
114 changes: 60 additions & 54 deletions myapp/views.py
Original file line number Diff line number Diff line change
@@ -1,117 +1,123 @@
from __future__ import unicode_literals

import sentry_sdk
import json

from rest_framework.response import Response
from rest_framework.views import APIView

from .serializers import InventorySerializer
from .models import Inventory
from sentry_sdk import add_breadcrumb

InventoryData = [{"name": "wrench", "count": 1},
{"name": "nails", "count": 1},
{"name": "hammer", "count": 1}]
import sentry_sdk


InventoryData = [
{"name": "wrench", "count": 1},
{"name": "nails", "count": 1},
{"name": "hammer", "count": 1},
]


def find_in_inventory(itemId):
for item in InventoryData:
if item['name'] == itemId:
if item["name"] == itemId:
return item
raise Exception("Item : " + itemId + " not in inventory ")


def process_order(cart):
add_breadcrumb(
category='Process Order',
message='Step taken to process an order',
level='info',
sentry_sdk.add_breadcrumb(
category="Process Order",
message="Step taken to process an order",
level="info",
)
global InventoryData
tempInventory = InventoryData
for item in cart:
itemID = item['id']
itemID = item["id"]
inventoryItem = find_in_inventory(itemID)
if inventoryItem['count'] <= 0:
raise Exception("Not enough inventory for " + itemID)
if inventoryItem["count"] <= 0:
raise Exception("Not enough inventory for " + itemID)
else:
inventoryItem['count'] -= 1
print( 'Success: ' + itemID + ' was purchased, remaining stock is ' + str(inventoryItem['count']) )
inventoryItem["count"] -= 1
print(
"Success: "
+ itemID
+ " was purchased, remaining stock is "
+ str(inventoryItem["count"])
)
InventoryData = tempInventory


class SentryContextMixin(object):

def dispatch(self, request, *args, **kwargs):
if (request.body):
body_unicode = request.body.decode('utf-8')
if request.body:
body_unicode = request.body.decode("utf-8")
order = json.loads(body_unicode)

with sentry_sdk.configure_scope() as scope:
scope.user = { "email" : order["email"] }
transactionId = request.headers.get('X-Transaction-ID')
scope.user = {"email": order["email"]}

transactionId = request.headers.get("X-Transaction-ID")

global InventoryData

with sentry_sdk.configure_scope() as scope:
if(transactionId):
if transactionId:
scope.set_tag("transaction_id", transactionId)

if(Inventory):
if Inventory:
scope.set_extra("inventory", InventoryData)

return super(SentryContextMixin, self).dispatch(request, *args, **kwargs)

# Create your views here.

class InventoreyView(SentryContextMixin, APIView):

def get(self, request):
results = InventorySerializer(InventoryData, many=True).data
return Response(results)


def post(self, request, format=None):
body_unicode = request.body.decode('utf-8')
body_unicode = request.body.decode("utf-8")
order = json.loads(body_unicode)
cart = order['cart']
cart = order["cart"]
process_order(cart)
return Response(InventoryData)
return Response(InventoryData)


class HandledErrorView(APIView):
def get(self, request):
add_breadcrumb(
category='URL Endpoints',
message='In the handled function',
level='info',
)
sentry_sdk.add_breadcrumb(
category="URL Endpoints",
message="In the handled function",
level="info",
)
try:
'2' + 2
"2" + 2
except Exception as err:
sentry_sdk.capture_exception(err)
return Response()


class UnHandledErrorView(APIView):
def get(self, request):
add_breadcrumb(
category='URL Endpoints',
message='In the unhandled function',
level='info',
)
def get(self, request):
sentry_sdk.add_breadcrumb(
category="URL Endpoints",
message="In the unhandled function",
level="info",
)
obj = {}
obj['keyDoesntExist']
obj["keyDoesntExist"]
return Response()


class CaptureMessageView(APIView):
def get(self, request):
add_breadcrumb(
category='URL Endpoints',
message='In the Capture Message function',
level='info',
)
sentry_sdk.capture_message("You caught me!")
sentry_sdk.add_breadcrumb(
category="URL Endpoints",
message="In the Capture Message function",
level="info",
)
sentry_sdk.capture_message("You caught me!", "fatal")

return Response()





File renamed without changes.
Loading