Skip to content

Commit f1a0783

Browse files
authored
Merge pull request #21 from backtrace-labs/release/0.4.0
Version 0.4.0
2 parents 48409f1 + 9a06638 commit f1a0783

File tree

7 files changed

+180
-37
lines changed

7 files changed

+180
-37
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Version 0.4.0
2+
3+
- Changed a submission flow - from spawning and sending data from a process to background thread(#19).
4+
- Added support for submit.backtrace.io(#14).
5+
- Added new default attributes:
6+
- backtrace.agent, backtrace.version (#13)
7+
- application.session (#13),
8+
- uname.sysname, uname.version, uname.release (#13),
9+
- error.type (#13),
10+
- linux process and system memory information (#15),
11+
- guid (#15),
12+
- cpu attributes (#15),
13+
- process.age (#15),
14+
- Added a support for attachments (#19),
15+
- Added a new client initialization attributes:
16+
- attributes - client specific attributes that will be included every time the report is being generated (#19),
17+
- attachments - list of attachments paths (#19),
18+
- collect_source_code - disable collecting source code information for each stack trace (#20),
19+
- ignore_ssl_certificate - if True, the option disables ssl validation (#19).

README.md

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,98 +16,118 @@ This module supports Python 2, Python 3, and PyPy.
1616
python -m pip install backtracepython
1717
```
1818

19-
2019
## Basic Usage
2120

22-
```import backtracepython as bt
21+
```python
22+
import backtracepython as bt
2323
bt.initialize(
24-
    endpoint="https://yourcompany.sp.backtrace.io:6098", token="51cc8e69c5b62fa8c72dc963e730f1e8eacbd243aeafc35d08d05ded9a024121"
24+
    endpoint="https://submit.backtrace.io/{universe}/{token}/json"
2525
)
2626
```
27+
2728
### Sending Reports from Unhandled Exceptions
2829

29-
By default, the backtracepython module will automatically capture unhandled exceptions and create and send error reports from them.  This behavior can be adjusted with the ```disable_global_handler``` option to ```bt.initialize``` (see below).
30+
By default, the `backtracepython` module automatically captures unhandled exceptions and creates and sends error reports from them. This behavior can be adjusted with the `disable_global_handler` option in `bt.initialize` (see below).
3031

3132
### Sending Reports Manually
3233

33-
You can also send error reports manually within code.  However, in order to get a correct callstack and source code context, you must send an error with a python exception context.  To do this, you can raise a python exception then immediately send a report via the ```send_last_exception call```.  A simple example:
34+
You can also send error reports manually in your code. However, to get a correct callstack and source code context, you must send an error with a Python exception context. To do this, you can raise a Python exception and then immediately send a report using the `send_last_exception` call. Here's an example:
3435

35-
```try:
36+
```python
37+
try:
3638
    raise Exception("This report was sent manually.")
3739
except:
3840
    bt.send_last_exception()
3941
```
4042

41-
## Reference
42-
### bt.initialize(**kwargs)
43+
## Documentation
44+
45+
### bt.initialize
46+
4347
#### Arguments
44-
* endpoint  - Required. Example: https://yourcompany.sp.backtrace.io:6098 .  Sets the HTTP/HTTPS endpoint that error reports will be sent to. 
45-
token  -  Required. Example: 51cc8e69c5b62fa8c72dc963e730f1e8eacbd243aeafc35d08d05ded9a024121  Sets the token that will be used for authentication when sending an error report. 
46-
* attributes  - Dictionary that contains additional attributes to be sent along with every error report. These can be overridden on an individual report with report.set_attribute  Example: { 'application': "ApplicationName", 'serverId': "foo" }  
47-
* timeout  - Defaults to 4. Maximum amount of seconds to wait for error report processing and sending before concluding it failed. 
48-
* debug_backtrace - Defaults to False . Set to True to have an error during collecting the report raise an exception, and to print some debugging information to stderr. 
49-
* disable_global_handler - Defaults to False. If this is False  this module will insert itself in the sys.excepthook chain and report those errors automatically before re-raising the exception. Set to True  to disable this. Note that in this case the only way error reports will be reported is if you manually create and send them. 
50-
* context_line_count  - Defaults to 200 . When an error is reported, this many lines above and below each stack function are included in the report. 
51-
* tab_width  - Defaults to 8.  If there are any hard tabs in the source code, it is unclear how many spaces they should be indented to correctly display the source code. Therefore the error report can override this number to specify how many spaces a hard tab should be represented by when viewing source code. 
48+
49+
- endpoint  - Required. Example: https://yourcompany.sp.backtrace.io:6098 or https://submit.backtrace.io/{universe}/{token}/json.  Sets the HTTP/HTTPS endpoint that error reports will be sent to. If submit.backtrace.io url is provided, the token argument is not required.
50+
token  -  Required only if endpoint is not set to submit.backtrace.io. Example: 51cc8e69c5b62fa8c72dc963e730f1e8eacbd243aeafc35d08d05ded9a024121  Sets the token that will be used for authentication when sending an error report.
51+
- attributes  - Dictionary that contains additional attributes to be sent along with every error report. These can be overridden on an individual report with report.set_attribute  Example: { 'application': "ApplicationName", 'serverId': "foo" }. Attributes values should be set to a primitive value such as boolean, integer or string.
52+
- attachments - A list of file paths that will be sent with each report.
53+
- ignore_ssl_certificate - Defaults to False. If True, ssl verification will be ignored during HTTP submission.
54+
- timeout  - Defaults to 4. Maximum amount of seconds to wait for error report processing and sending before concluding it failed.
55+
- debug_backtrace - Defaults to False . Set to True to have an error during collecting the report raise an exception, and to print some debugging information to stderr.
56+
- disable_global_handler - Defaults to False. If this is False  this module will insert itself in the sys.excepthook chain and report those errors automatically before re-raising the exception. Set to True  to disable this. Note that in this case the only way error reports will be reported is if you manually create and send them.
57+
- context_line_count  - Defaults to 200 . When an error is reported, this many lines above and below each stack function are included in the report.
58+
- tab_width  - Defaults to 8.  If there are any hard tabs in the source code, it is unclear how many spaces they should be indented to correctly display the source code. Therefore the error report can override this number to specify how many spaces a hard tab should be represented by when viewing source code.
59+
- collect_source_code - Default to True. By default Backtrace client collects corresponded source code and send it with the report. If set to False, the source code will not be collected.
5260

5361
### bt.BacktraceReport
5462

5563
Create a report object that you can later choose whether or not to send. This may be useful to track something like a request.
5664

57-
```report.set_attribute(key, value) ```
65+
`report.set_attribute(key, value) `
5866
Adds an attribute to a specific report. Valid types for value are str, float, int, and bool.
59-
Attributes are indexed and searchable. See also ```addAnnotation```
67+
Attributes are indexed and searchable. See also `addAnnotation`
6068

61-
```report.set_dict_attributes(dict)``` 
69+
`report.set_dict_attributes(dict)`
6270

6371
Adds all key-value pairs of dict into the report recursively.
6472

65-
```report.set_annotation(key, value) ```
73+
`report.get_attributes() `
74+
75+
Returns all report attributes.
76+
77+
`report.set_annotation(key, value) `
6678

6779
Adds an annotation to a specific report. Annotations, unlike attributes, are not indexed and searchable. However, they are available for inspection when you view a specific report.
6880

6981
key - String which is the name of the annotation.
7082
value - Any type which is JSON-serializable.
7183

72-
```report.set_dict_annotations(dict) ```
84+
`report.set_dict_annotations(dict) `
7385

7486
Adds all key-value pairs of dict into the report.
7587

76-
```report.set_exception(ExceptionType, exception, traceback)```
88+
`report.add_attachment(attachment_path) `
89+
90+
Adds an attachment to the report.
91+
92+
`report.get_attachments() `
93+
94+
Returns a list of attachment paths.
95+
96+
`report.set_exception(ExceptionType, exception, traceback)`
7797

7898
error  is an Error object. Backtrace will extract information from this object such as the error message and stack trace and send this information along with the report.
7999

80-
```report.capture_last_exception() ```
100+
`report.capture_last_exception() `
81101

82-
This is the same as report.set_exception(*sys.exc_info())
102+
This is the same as report.set_exception(\*sys.exc_info())
83103

84-
```report.log(line) ```
104+
`report.log(line)`
85105

86106
Adds a timestamped log message to the report. Log output is available when you view a report.
87107

88-
```report.send() ```
108+
`report.send()`
89109

90110
Sends the error report to the endpoint specified in initialize.
91111

92-
### bt.send_last_exception(**kwargs)
93-
* attributes  - dictionary of attributes to add to the report. See report.set_dict_attributes
94-
* annotations  - dictionary of annotations to add to the report. See report.set_dict_annotations
112+
### bt.send_last_exception(\*\*kwargs)
95113

114+
- attributes  - dictionary of attributes to add to the report. See report.set_dict_attributes
115+
- annotations  - dictionary of annotations to add to the report. See report.set_dict_annotations
96116

97117
## Contributing
98118

99119
To run the test suite:
100120

101121
```
102-
python setup.py test
122+
pytest
103123
```
104124

105125
Since all of these implementations of Python are supported, be sure to run the
106126
test suite with all of them:
107127

108-
* Python 2
109-
* Python 3
110-
* PyPy
128+
- Python 2
129+
- Python 3
130+
- PyPy
111131

112132
### Publishing to PyPI
113133

@@ -116,6 +136,6 @@ test suite with all of them:
116136
3. Tag the version in git.
117137

118138
```
119-
python2 setup.py bdist_wheel --universal
139+
python3 setup.py bdist_wheel --universal
120140
twine upload dist/*
121141
```

backtracepython/client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ def get_attributes():
2323
return attribute_manager.get()
2424

2525

26+
def set_attribute(key, value):
27+
attribute_manager.add({key: value})
28+
29+
30+
def set_attributes(attributes):
31+
attribute_manager.add(attributes)
32+
33+
2634
def send(report, attachments=[]):
2735
if globs.handler is None:
2836
return False

backtracepython/version.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
class version:
22
major = 0
3-
minor = 3
4-
patch = 3
3+
minor = 4
4+
patch = 0
55

66

77
version_string = "{}.{}.{}".format(version.major, version.minor, version.patch)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
setup(
66
name="backtracepython",
7-
version="0.3.3",
7+
version="0.4.0",
88
description="Backtrace.io error reporting tool for Python",
99
author="Backtrace.io",
1010
author_email="[email protected]",

tests/test_report_attributes.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from backtracepython.client import set_attribute
12
from backtracepython.report import BacktraceReport
23

34
report = BacktraceReport()
@@ -30,3 +31,33 @@ def test_report_attribute_override():
3031
override_report.set_attribute(override_attribute_name, expected_value)
3132

3233
assert override_report.get_attributes()[override_attribute_name] == expected_value
34+
35+
36+
def test_unique_user_id():
37+
attributes = report.get_attributes()
38+
assert attributes["guid"] is not None
39+
40+
41+
def test_unique_user_should_always_be_the_same():
42+
override_report = BacktraceReport()
43+
attributes = report.get_attributes()
44+
override_report_attributes = override_report.get_attributes()
45+
assert attributes["guid"] == override_report_attributes["guid"]
46+
47+
48+
def test_override_default_client_attribute():
49+
test_attribute = "guid"
50+
test_attribute_value = "foo"
51+
set_attribute(test_attribute, test_attribute_value)
52+
new_report = BacktraceReport()
53+
attributes = new_report.get_attributes()
54+
assert attributes["guid"] == test_attribute_value
55+
56+
57+
def test_override_default_client_attribute_by_report():
58+
test_attribute = "guid"
59+
test_attribute_value = "bar"
60+
new_report = BacktraceReport()
61+
new_report.set_attribute(test_attribute, test_attribute_value)
62+
attributes = new_report.get_attributes()
63+
assert attributes["guid"] == test_attribute_value

tests/test_stack_trace_parser.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import sys
2+
import threading
3+
import time
4+
5+
from backtracepython.report import BacktraceReport
6+
7+
8+
def open_file(name):
9+
open(name).read()
10+
11+
12+
def failing_function():
13+
open_file("test")
14+
15+
16+
def test_main_thread_generation_without_exception():
17+
report = BacktraceReport()
18+
data = report.get_data()
19+
stack_trace = data["threads"][data["mainThread"]]
20+
assert len(stack_trace["stack"]) != 0
21+
22+
23+
def test_skipping_backtrace_module_in_process_stack():
24+
test_name = sys._getframe().f_code.co_name
25+
26+
report = BacktraceReport()
27+
data = report.get_data()
28+
stack_trace = data["threads"][data["mainThread"]]
29+
30+
current_function_name = stack_trace["stack"][0]["funcName"]
31+
assert current_function_name == test_name
32+
33+
34+
def test_main_thread_generation_with_exception():
35+
# this funciton + 2 fauulting functions
36+
expected_number_of_frames = 3
37+
try:
38+
failing_function()
39+
except:
40+
report = BacktraceReport()
41+
report.capture_last_exception()
42+
data = report.get_data()
43+
stack_trace = data["threads"][data["mainThread"]]
44+
assert len(stack_trace["stack"]) == expected_number_of_frames
45+
46+
47+
def test_background_thread_stack_trace_generation():
48+
if_stop = False
49+
50+
def wait_in_thread():
51+
while not if_stop:
52+
time.sleep(0.1)
53+
54+
def runner():
55+
wait_in_thread()
56+
57+
thread = threading.Thread(target=runner, name="runner")
58+
thread.start()
59+
60+
report = BacktraceReport()
61+
data = report.get_data()
62+
if_stop = True
63+
thread.join()
64+
stack_trace = data["threads"][str(thread.ident)]
65+
assert len(stack_trace) != 0

0 commit comments

Comments
 (0)