forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexception_handler.ts
More file actions
122 lines (102 loc) · 3.72 KB
/
exception_handler.ts
File metadata and controls
122 lines (102 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import {Injectable} from 'angular2/di';
import {isPresent, isBlank, print, BaseException} from 'angular2/src/facade/lang';
import {ListWrapper, isListLikeIterable} from 'angular2/src/facade/collection';
class _ArrayLogger {
res: any[] = [];
log(s: any): void { this.res.push(s); }
logGroup(s: any): void { this.res.push(s); }
logGroupEnd(){};
}
/**
* Provides a hook for centralized exception handling.
*
* The default implementation of `ExceptionHandler` prints error messages to the `Console`. To
* intercept error handling,
* write a custom exception handler that replaces this default as appropriate for your app.
*
* # Example
*
* ```javascript
*
* class MyExceptionHandler implements ExceptionHandler {
* call(error, stackTrace = null, reason = null) {
* // do something with the exception
* }
* }
*
* bootstrap(MyApp, [bind(ExceptionHandler).toClass(MyExceptionHandler)])
*
* ```
*/
@Injectable()
export class ExceptionHandler {
constructor(private logger: any, private rethrowException: boolean = true) {}
static exceptionToString(exception: any, stackTrace: any = null, reason: string = null): string {
var l = new _ArrayLogger();
var e = new ExceptionHandler(l, false);
e.call(exception, stackTrace, reason);
return l.res.join("\n");
}
call(exception: any, stackTrace: any = null, reason: string = null): void {
var originalException = this._findOriginalException(exception);
var originalStack = this._findOriginalStack(exception);
var context = this._findContext(exception);
this.logger.logGroup(`EXCEPTION: ${exception}`);
if (isPresent(stackTrace) && isBlank(originalStack)) {
this.logger.log("STACKTRACE:");
this.logger.log(this._longStackTrace(stackTrace));
}
if (isPresent(reason)) {
this.logger.log(`REASON: ${reason}`);
}
if (isPresent(originalException)) {
this.logger.log(`ORIGINAL EXCEPTION: ${originalException}`);
}
if (isPresent(originalStack)) {
this.logger.log("ORIGINAL STACKTRACE:");
this.logger.log(this._longStackTrace(originalStack));
}
if (isPresent(context)) {
this.logger.log("ERROR CONTEXT:");
this.logger.log(context);
}
this.logger.logGroupEnd();
// We rethrow exceptions, so operations like 'bootstrap' will result in an error
// when an exception happens. If we do not rethrow, bootstrap will always succeed.
if (this.rethrowException) throw exception;
}
_longStackTrace(stackTrace: any): any {
return isListLikeIterable(stackTrace) ? (<any>stackTrace).join("\n\n-----async gap-----\n") :
stackTrace.toString();
}
_findContext(exception: any): any {
try {
if (!(exception instanceof BaseException)) return null;
return isPresent(exception.context) ? exception.context :
this._findContext(exception.originalException);
} catch (e) {
// exception.context can throw an exception. if it happens, we ignore the context.
return null;
}
}
_findOriginalException(exception: any): any {
if (!(exception instanceof BaseException)) return null;
var e = exception.originalException;
while (e instanceof BaseException && isPresent(e.originalException)) {
e = e.originalException;
}
return e;
}
_findOriginalStack(exception: any): any {
if (!(exception instanceof BaseException)) return null;
var e = exception;
var stack = exception.originalStack;
while (e instanceof BaseException && isPresent(e.originalException)) {
e = e.originalException;
if (e instanceof BaseException && isPresent(e.originalException)) {
stack = e.originalStack;
}
}
return stack;
}
}