Skip to content

Commit f22927a

Browse files
1.4.0 changes (#43)
* Improving parsing of Stack Traces, in particular when the first line (error message) itself contain the word <at> * Adding support for Java stack traces seen in ColdBox async error handling
1 parent d1feefb commit f22927a

File tree

9 files changed

+110
-74
lines changed

9 files changed

+110
-74
lines changed

README.md

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,104 @@
11
raygun4cfml
22
===========
33

4-
Raygun.io API client for CFML.
4+
Raygun Crash Reporting client for CFML.
55

6-
Current Version: 1.3.1 (July 26 2021)
6+
Current Version: 1.4.0 (May 24 2022)
77

88
Dependencies:
99

1010
- Testbox (for running unit and BDD tests only)
1111

1212
## Library organisation
1313

14-
/src contains the source code. The package structure is nz.co.ventego-creative.co.nz.raygun4cfml but the library's components themselves are independent of the package path. Therefore you can use the library in multiple ways:
14+
`/src` contains the source code. The package structure is `nz.co.ventego-creative.co.nz.raygun4cfml` but the library's components themselves are independent of the package path. Therefore you can use the library in multiple ways:
1515

16-
- Put the content of /src into your webroot and instantiate RaygunClient through something like the following:
16+
- Put the content of `/src` into your webroot and instantiate `RaygunClient` through something like the following:
1717

18+
```
1819
raygun = createObject("component","nz.co.ventego-creative.raygun4cfml.RaygunClient").init(
1920
apiKey = "YOURAPIKEYHERE"
2021
);
22+
```
23+
- Put the contents of `/src` into any other place of your choice and create a mapping to `/nz` in your server administrator or through code and then use the instantiation code as above.
2124
22-
- Put the contents of /src into any other place of your choice and create a mapping to /nz in your server administrator or through code and then use the instantiation code as above.
23-
24-
- Put the contents of the raygun4cfml into a place of your choice where your CFML has some sort of a mapping pointing towards and and just instantiate RaygunClient like this:
25-
25+
- Put the contents of the `raygun4cfml` directory into a place of your choice where your CFML has some sort of a mapping pointing towards and and just instantiate `RaygunClient` like this:
26+
27+
```
2628
raygun = createObject("component","RaygunClient").init(
2729
apiKey = "YOURAPIKEYHERE"
2830
);
31+
```
2932
30-
/samples contains a set of files that show how the library can be used in your code through a global error handler as well as a contributed example for ColdBox 3.6
33+
`/samples` contains a set of files that show how the library can be used in your code through a global error handler as well as a contributed example for ColdBox 3.6
3134
32-
/tests contains manual tests and more samples as well as a structure (but no tests at this stage) for Testbox unit and BDD tests.
35+
`/tests` contains manual tests and more samples as well as a structure (but no tests at this stage) for Testbox unit and BDD tests.
3336
3437
## Getting and Using raygun4cfml
3538
36-
Option 1 (preferred):
39+
### Option 1 (preferred):
3740
3841
Use Commandbox and Forgebox to get the library and then follow the ideas outlined in 'Library organisation' for further setup.
3942
4043
To get the latest from the master repository
4144
42-
box install raygun4cfml
45+
```
46+
box install raygun4cfml
47+
```
4348
44-
To install a specific release or tag:
45-
46-
box install git://github.com/MindscapeHQ/raygun4cfml.git#{tagname}
47-
48-
Example tag names are 1.1.0, 1.0.2.0, 1.0.1.0 etc. Please check the list of tags on Github. Be aware that if you install any tag from before I introduced support for Commandbox and Forgebox there won't be a box.json file and therefore Commandbox will give you a warning as well as there won't be any dependency management for such an installation of the library.
49+
To install a specific release or tag:
50+
51+
```
52+
box install git://github.com/MindscapeHQ/raygun4cfml.git#{tagname}
53+
```
54+
55+
Example tag names are `1.1.0`, `1.0.2.0`, `1.0.1.0` etc. Please check the list of tags on Github. Be aware that if you install any tag from before I introduced support for Commandbox and Forgebox there won't be a `box.json` file and therefore Commandbox will give you a warning as well as there won't be any dependency management for such an installation of the library.
4956
5057
Shortcut for the above:
5158
52-
box install MindscapeHQ/raygun4cfml#{tagname}
53-
59+
```
60+
box install MindscapeHQ/raygun4cfml#{tagname}
61+
```
62+
5463
To get the latest from my development repository (be warned, this might contain all sorts of untested code):
5564
56-
box install TheRealAgentK/raygun4cfml
65+
```
66+
box install TheRealAgentK/raygun4cfml
67+
```
5768
58-
Option 2:
69+
### Option 2:
5970
6071
Fork and clone the repo to your local system. Move the src/test directories into places of your choice and suitable for your system and follow the ideas outlined in 'Library organisation'.
6172
62-
Option 3:
73+
### Option 3:
6374
6475
Download a zip file containing the current content of the repo or a release/tag of your choice. Unzip the resulting file. Move the src/test directories into places of your choice and suitable for your system and follow the ideas outlined in 'Library organisation'.
6576
66-
####Notes:
77+
#### Notes:
6778
6879
(1) Options 2 and 3 will not fulfill any necessary dependencies, you're on your own.
6980
7081
## Versions
7182
7283
See changelog.md for further information.
7384
74-
####Notes:
85+
## General Notes
7586
76-
(1) All releases onwards from 0.5.0.0 will break your code if you've used 0.4 and older before and have used customRequestData. Please continue reading.
87+
(1) All releases onwards from 0.5.0.0 will break your code if you've used 0.4 and older before and have used `customRequestData`.
7788
78-
(2) If you are using the ACF Administrator setting: "Prefix serialized JSON with..." with anything else but the default prefix of "//", the library will not work.
89+
(2) If you are using the ACF Administrator setting: "Prefix serialized JSON with..." with anything else but the default prefix of `//`, the library will not work.
7990
8091
(3) Version 1.1.0 and newer will not work on Adobe ColdFusion 8 and most likely not on Railo 3 (the latter not tested).
8192
82-
8393
## How to contribute
8494
85-
The main repository of this project is https://github.com/MindscapeHQ/raygun4cfml. Please fork from there, create a local develop branch and merge changes back to your local master branch to submit a pull request. Even better, get in touch with me on Twitter (@AgentK) or here on Github before you undertake any work so that it can be coordinated with what I'm doing.
95+
The main repository of this project is https://github.com/MindscapeHQ/raygun4cfml. Please fork from there, create a local develop or feature branch and merge changes back to your local master branch to submit a pull request. Even better, get in touch with me on Twitter (@AgentK) or here on Github before you undertake any work so that it can be coordinated with what I'm doing.
8696
8797
Most of the active development happens in my own fork: https://github.com/TheRealAgentK/raygun4cfml - feel free to peek around in there.
8898
8999
## License
90100
91-
Copyright 2013-2021 Kai Koenig, Ventego Creative Ltd
101+
Copyright 2013-2022 Kai Koenig, Ventego Creative Ltd
92102
93103
Licensed under the Apache License, Version 2.0 (the "License");
94104
you may not use this file except in compliance with the License.

box.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name":"raygun4cfml",
3-
"version":"1.3.1",
4-
"location":"MindscapeHQ/raygun4cfml#1.3.0",
3+
"version":"1.4.0",
4+
"location":"MindscapeHQ/raygun4cfml#1.4.0",
55
"author":"Kai Koenig <kai@ventego-creative.co.nz>",
66
"homepage":"https://github.com/MindscapeHQ/raygun4cfml/",
77
"documentation":"https://github.com/MindscapeHQ/raygun4cfml/blob/master/README.md",

changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
History
22
=======
33

4+
1.4.0 (May 24 2022)
5+
6+
- Supporting stack traces where certain elements (like TagContext) don't exist
7+
- Support for specifc Java strack traces stemming from asynchronous handling
8+
49
1.3.1 (Jul 26 2021)
510

611
- Physical memory tracking again under certain conditions, provided the underlying Java code is available on the JVM (modules opened up).

src/nz/co/ventego-creative/raygun4cfml/RaygunClient.cfc

100755100644
File mode changed.

src/nz/co/ventego-creative/raygun4cfml/RaygunClientMessage.cfc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ limitations under the License.
3030
var returnContent = {};
3131

3232
returnContent["name"] = "raygun4cfml";
33-
returnContent["version"] = "1.2.0";
33+
returnContent["version"] = "1.4.0";
3434
returnContent["clientUrl"] = "https://github.com/MindscapeHQ/raygun4cfml";
3535

3636
return returnContent;

src/nz/co/ventego-creative/raygun4cfml/RaygunExceptionMessage.cfc

100644100755
Lines changed: 63 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,75 +30,96 @@ limitations under the License.
3030

3131
<cfscript>
3232
var returnContent = {};
33+
3334
var stackTraceData = [];
3435
var stackTraceLines = [];
3536
var tagContextData = [];
37+
var stackTraceLineElements = [];
38+
var stackTraceLineElement = {};
3639
var lenStackTraceLines = 0;
3740
var lenTagContext = 0;
38-
var stackTraceLineElements = [];
3941
var j = 0;
42+
4043
var isLucee = new RaygunInternalTools().isLucee();
4144
var isACF2021 = new RaygunInternalTools().isACF2021();
45+
46+
var entryPoint = arguments.issueDataStruct;
4247

43-
stackTraceLines = arguments.issueDataStruct.stacktrace.split("\sat");
44-
lenStackTraceLines = ArrayLen(stackTraceLines);
45-
46-
for (j=2;j<=lenStackTraceLines;j++)
47-
{
48-
stackTraceLineElements = stackTraceLines[j].split("\(");
49-
stackTraceData[j-1] = {};
50-
stackTraceData[j-1]["methodName"] = Trim(ListLast(stackTraceLineElements[1],"."));
51-
stackTraceData[j-1]["className"] = Trim(ListDeleteAt(stackTraceLineElements[1],ListLen(stackTraceLineElements[1],"."),"."));
52-
// PR 26 - It seems there are Java Strack Traces without line numbers
53-
// Check if a line number is present in the Java Stack Trace
54-
// We look for a colon followed by number(s)
55-
// If no line number, return 0 so it's apparent none was given.
56-
if (ReFind("\:(?!\D+)",stackTraceLineElements[2])){
57-
stackTraceData[j-1]["fileName"] = Trim(ReReplace(stackTraceLineElements[2].split("\:(?!\D+)")[1],"[\)\n\r]",""));
58-
stackTraceData[j-1]["lineNumber"] = Trim(ReReplace(stackTraceLineElements[2].split("\:(?!\D+)")[2],"[\)\n\r]",""));
59-
}
60-
else
48+
if (StructKeyExists(arguments.issueDataStruct,"Cause") && StructKeyExists(arguments.issueDataStruct.cause,"CatchBlock")) {
49+
entryPoint = arguments.issueDataStruct.cause.CatchBlock;
50+
}
51+
52+
if (isArray(entryPoint.stacktrace)) {
53+
stackTraceData = entryPoint.stacktrace;
54+
} elseif (isSimpleValue(entryPoint.stacktrace)) {
55+
stackTraceLines = entryPoint.stacktrace.split("\sat");
56+
lenStackTraceLines = ArrayLen(stackTraceLines);
57+
58+
for (j=2;j<=lenStackTraceLines;j++)
6159
{
62-
stackTraceData[j-1]["fileName"] = Trim(ReReplace(stackTraceLineElements[2],"[\)\n\r]",""));
63-
stackTraceData[j-1]["lineNumber"] = 0;
60+
stackTraceLineElements = stackTraceLines[j].split("\(");
61+
62+
if (ArrayLen(stackTraceLineElements) == 2) {
63+
64+
stackTraceLineElement = {};
65+
stackTraceLineElement["methodName"] = Trim(ListLast(stackTraceLineElements[1],"."));
66+
stackTraceLineElement["className"] = Trim(ListDeleteAt(stackTraceLineElements[1],ListLen(stackTraceLineElements[1],"."),"."));
67+
// PR 26 - It seems there are Java Strack Traces without line numbers
68+
// Check if a line number is present in the Java Stack Trace
69+
// We look for a colon followed by number(s)
70+
// If no line number, return 0 so it's apparent none was given.
71+
if (ReFind("\:(?!\D+)",stackTraceLineElements[2])){
72+
stackTraceLineElement["fileName"] = Trim(ReReplace(stackTraceLineElements[2].split("\:(?!\D+)")[1],"[\)\n\r]",""));
73+
stackTraceLineElement["lineNumber"] = Trim(ReReplace(stackTraceLineElements[2].split("\:(?!\D+)")[2],"[\)\n\r]",""));
74+
}
75+
else
76+
{
77+
stackTraceLineElement["fileName"] = Trim(ReReplace(stackTraceLineElements[2],"[\)\n\r]",""));
78+
stackTraceLineElement["lineNumber"] = 0;
79+
}
80+
81+
ArrayAppend(stackTraceData, stackTraceLineElement);
82+
}
6483
}
65-
}
66-
67-
lenTagContext = arraylen(arguments.issueDataStruct.tagcontext);
84+
}
6885

69-
for (j=1;j<=lenTagContext;j++)
70-
{
71-
tagContextData[j] = {};
72-
tagContextData[j]["methodName"] = "";
73-
tagContextData[j]["className"] = trim( arguments.issueDataStruct.tagcontext[j]["id"] );
74-
tagContextData[j]["fileName"] = trim( arguments.issueDataStruct.tagcontext[j]["template"] );
75-
tagContextData[j]["lineNumber"] = trim( arguments.issueDataStruct.tagcontext[j]["line"] );
76-
}
86+
if (structKeyExists(entryPoint,"tagcontext")) {
87+
lenTagContext = arraylen(entryPoint.tagcontext);
7788

89+
for (j=1;j<=lenTagContext;j++)
90+
{
91+
tagContextData[j] = {};
92+
tagContextData[j]["methodName"] = "";
93+
tagContextData[j]["className"] = trim( entryPoint.tagcontext[j]["id"] );
94+
tagContextData[j]["fileName"] = trim( entryPoint.tagcontext[j]["template"] );
95+
tagContextData[j]["lineNumber"] = trim( entryPoint.tagcontext[j]["line"] );
96+
}
97+
}
98+
7899
returnContent["data"] = {"JavaStrackTrace" = stackTraceData};
79100
returnContent["stackTrace"] = tagContextData;
80101

81102
// if we deal with an error struct, there'll be a root cause
82-
if (StructKeyExists(arguments.issueDataStruct,"RootCause")) {
83-
if (StructKeyExists(arguments.issueDataStruct["RootCause"],"Type") and arguments.issueDataStruct["RootCause"]["Type"] eq "expression")
103+
if (StructKeyExists(entryPoint,"RootCause")) {
104+
if (StructKeyExists(entryPoint["RootCause"],"Type") and entryPoint["RootCause"]["Type"] eq "expression")
84105
{
85-
returnContent["data"]["type"] = arguments.issueDataStruct["RootCause"]["Type"];
106+
returnContent["data"]["type"] = entryPoint["RootCause"]["Type"];
86107
}
87-
if (StructKeyExists(arguments.issueDataStruct["RootCause"],"Message"))
108+
if (StructKeyExists(entryPoint["RootCause"],"Message"))
88109
{
89-
returnContent["message"] = arguments.issueDataStruct["RootCause"]["Message"];
110+
returnContent["message"] = entryPoint["RootCause"]["Message"];
90111
}
91112
returnContent["catchingMethod"] = "Error struct";
92113
} else {
93-
// otherwise there's no root cause and the specific data has to be grabbed from somewhere else
94-
if (!isLucee || isACF2021) {
95-
returnContent["data"]["type"] = arguments.issueDataStruct.type;
114+
// otherwise there's no root cause and the specific data has to be grabbed from somewhere else
115+
if (!isLucee || isACF2021) {
116+
returnContent["data"]["type"] = entryPoint.type;
96117
}
97-
returnContent["message"] = arguments.issueDataStruct.message;
118+
returnContent["message"] = entryPoint.message;
98119
returnContent["catchingMethod"] = "CFCatch struct";
99120
}
100121

101-
returnContent["className"] = trim( arguments.issueDataStruct.type );
122+
returnContent["className"] = trim( entryPoint.type );
102123

103124
return returnContent;
104125
</cfscript>

src/nz/co/ventego-creative/raygun4cfml/RaygunMessageDetails.cfc

100755100644
File mode changed.

src/nz/co/ventego-creative/raygun4cfml/RaygunRequestMessage.cfc

100755100644
File mode changed.

src/nz/co/ventego-creative/raygun4cfml/RaygunUserCustomData.cfc

100755100644
File mode changed.

0 commit comments

Comments
 (0)