Skip to content

Commit 7a6357b

Browse files
Merge pull request #316 from Microsoft/develop
Merge develop to master for 0.22 release
2 parents 4325e12 + dd34598 commit 7a6357b

File tree

74 files changed

+3158
-2066
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+3158
-2066
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ obj/
77

88
# Ignore Node files
99
node_modules/**
10+
Tests/SampleApp/node_modules/**
11+
Tests/SampleConsoleApp/node_modules/**
1012

1113
# Ignore Visual Studio files
1214
*.suo
1315
*.sln
1416
*.dat
1517
*.njsproj
18+
.vscode/
1619

1720
# Ignore webstorm files
1821
.idea

.vscode/tasks.json

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
{
2-
// See https://go.microsoft.com/fwlink/?LinkId=733558
3-
// for the documentation about the tasks.json format
42
"version": "0.1.0",
5-
"command": "tsc",
3+
"command": "npm",
64
"isShellCommand": true,
7-
"args": ["-w", "-p", "."],
85
"showOutput": "silent",
9-
"isWatching": true,
10-
"problemMatcher": "$tsc-watch"
6+
"suppressTaskName": true,
7+
"tasks": [
8+
{
9+
"taskName": "test",
10+
"args": ["run", "test"],
11+
"isTestCommand": true
12+
},
13+
{
14+
"taskName": "build",
15+
"args": ["run", "build"],
16+
"isTestCommand": false
17+
}
18+
]
1119
}

AutoCollection/Console.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Client = require("../Library/Client");
1+
import TelemetryClient = require("../Library/TelemetryClient");
22
import Logging = require("../Library/Logging");
33

44
import {enable as enableConsole} from "./diagnostic-channel/console.sub";
@@ -12,10 +12,10 @@ class AutoCollectConsole {
1212
public static INSTANCE: AutoCollectConsole;
1313
private static _methodNames = ["debug", "info", "log", "warn", "error"];
1414

15-
private _client: Client;
15+
private _client: TelemetryClient;
1616
private _isInitialized: boolean;
1717

18-
constructor(client: Client) {
18+
constructor(client: TelemetryClient) {
1919
if(!!AutoCollectConsole.INSTANCE) {
2020
throw new Error("Console logging adapter tracking should be configured from the applicationInsights object");
2121
}
@@ -35,6 +35,7 @@ class AutoCollectConsole {
3535

3636
public dispose() {
3737
AutoCollectConsole.INSTANCE = null;
38+
this.enable(false);
3839
}
3940
}
4041

AutoCollection/Exceptions.ts

Lines changed: 14 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import http = require("http");
22

33
import Contracts = require("../Declarations/Contracts");
4-
import Client = require("../Library/Client");
4+
import TelemetryClient = require("../Library/TelemetryClient");
55
import Sender = require("../Library/Sender");
66
import Queue = require("../Library/Channel");
77
import Util = require("../Library/Util");
88

99
class AutoCollectExceptions {
1010

1111
public static INSTANCE: AutoCollectExceptions = null;
12+
public static get UNCAUGHT_EXCEPTION_HANDLER_NAME(): string { return "uncaughtException"; }
13+
public static get UNHANDLED_REJECTION_HANDLER_NAME(): string { return "unhandledRejection"; }
1214

1315
private _exceptionListenerHandle: (reThrow: boolean, error: Error) => void;
1416
private _rejectionListenerHandle: (reThrow: boolean, error: Error) => void;
15-
private _client: Client;
17+
private _client: TelemetryClient;
1618
private _isInitialized: boolean;
1719

18-
constructor(client: Client) {
19-
if(!!AutoCollectExceptions.INSTANCE) {
20+
constructor(client: TelemetryClient) {
21+
if (!!AutoCollectExceptions.INSTANCE) {
2022
throw new Error("Exception tracking should be configured from the applicationInsights object");
2123
}
2224

@@ -29,29 +31,28 @@ class AutoCollectExceptions {
2931
}
3032

3133
public enable(isEnabled: boolean) {
32-
if(isEnabled) {
34+
if (isEnabled) {
3335
this._isInitialized = true;
3436
var self = this;
3537
if (!this._exceptionListenerHandle) {
3638
var handle = (reThrow: boolean, error: Error) => {
37-
var data = AutoCollectExceptions.getExceptionData(error, false);
38-
var envelope = this._client.getEnvelope(data);
39-
this._client.channel.handleCrash(envelope);
39+
this._client.trackException({ exception: error });
40+
this._client.flush({ isAppCrashing: true });
4041
if (reThrow) {
4142
throw error;
4243
}
4344
};
4445
this._exceptionListenerHandle = handle.bind(this, true);
4546
this._rejectionListenerHandle = handle.bind(this, false);
4647

47-
process.on("uncaughtException", this._exceptionListenerHandle);
48-
process.on("unhandledRejection", this._rejectionListenerHandle);
48+
process.on(AutoCollectExceptions.UNCAUGHT_EXCEPTION_HANDLER_NAME, this._exceptionListenerHandle);
49+
process.on(AutoCollectExceptions.UNHANDLED_REJECTION_HANDLER_NAME, this._rejectionListenerHandle);
4950
}
5051

5152
} else {
5253
if (this._exceptionListenerHandle) {
53-
process.removeListener("uncaughtException", this._exceptionListenerHandle);
54-
process.removeListener("unhandledRejection", this._rejectionListenerHandle);
54+
process.removeListener(AutoCollectExceptions.UNCAUGHT_EXCEPTION_HANDLER_NAME, this._exceptionListenerHandle);
55+
process.removeListener(AutoCollectExceptions.UNHANDLED_REJECTION_HANDLER_NAME, this._rejectionListenerHandle);
5556
this._exceptionListenerHandle = undefined;
5657
this._rejectionListenerHandle = undefined;
5758
delete this._exceptionListenerHandle;
@@ -60,127 +61,13 @@ class AutoCollectExceptions {
6061
}
6162
}
6263

63-
/**
64-
* Track an exception
65-
* @param error the exception to track
66-
* @param handledAt where this exception was handled (leave null for unhandled)
67-
* @param properties additional properties
68-
* @param measurements metrics associated with this event, displayed in Metrics Explorer on the portal. Defaults to empty.
69-
*/
70-
public static getExceptionData(error: Error, isHandled: boolean, properties?:{ [key: string]: string; }, measurements?:{ [key: string]: number; }): Contracts.Data<Contracts.ExceptionData> {
71-
var exception = new Contracts.ExceptionData();
72-
exception.properties = properties;
73-
exception.severityLevel = Contracts.SeverityLevel.Error;
74-
exception.measurements = measurements;
75-
exception.exceptions = [];
76-
77-
var stack = error["stack"];
78-
var exceptionDetails = new Contracts.ExceptionDetails();
79-
exceptionDetails.message = error.message;
80-
exceptionDetails.typeName = error.name;
81-
exceptionDetails.parsedStack = this.parseStack(stack);
82-
exceptionDetails.hasFullStack = Util.isArray(exceptionDetails.parsedStack) && exceptionDetails.parsedStack.length > 0;
83-
exception.exceptions.push(exceptionDetails);
84-
85-
var data = new Contracts.Data<Contracts.ExceptionData>();
86-
data.baseType = Contracts.DataTypes.EXCEPTION;
87-
data.baseData = exception;
88-
return data;
89-
}
90-
91-
private static parseStack(stack: any): _StackFrame[] {
92-
var parsedStack: _StackFrame[] = undefined;
93-
if (typeof stack === "string") {
94-
var frames = stack.split("\n");
95-
parsedStack = [];
96-
var level = 0;
97-
98-
var totalSizeInBytes = 0;
99-
for (var i = 0; i <= frames.length; i++) {
100-
var frame = frames[i];
101-
if (_StackFrame.regex.test(frame)) {
102-
var parsedFrame = new _StackFrame(frames[i], level++);
103-
totalSizeInBytes += parsedFrame.sizeInBytes;
104-
parsedStack.push(parsedFrame);
105-
}
106-
}
107-
108-
// DP Constraint - exception parsed stack must be < 32KB
109-
// remove frames from the middle to meet the threshold
110-
var exceptionParsedStackThreshold = 32 * 1024;
111-
if (totalSizeInBytes > exceptionParsedStackThreshold) {
112-
var left = 0;
113-
var right = parsedStack.length - 1;
114-
var size = 0;
115-
var acceptedLeft = left;
116-
var acceptedRight = right;
117-
118-
while (left < right) {
119-
// check size
120-
var lSize = parsedStack[left].sizeInBytes;
121-
var rSize = parsedStack[right].sizeInBytes;
122-
size += lSize + rSize;
123-
124-
if (size > exceptionParsedStackThreshold) {
125-
126-
// remove extra frames from the middle
127-
var howMany = acceptedRight - acceptedLeft + 1;
128-
parsedStack.splice(acceptedLeft, howMany);
129-
break;
130-
}
131-
132-
// update pointers
133-
acceptedLeft = left;
134-
acceptedRight = right;
135-
136-
left++;
137-
right--;
138-
}
139-
}
140-
}
141-
142-
return parsedStack;
143-
}
144-
14564
public dispose() {
14665
AutoCollectExceptions.INSTANCE = null;
66+
this.enable(false);
14767
this._isInitialized = false;
14868
}
14969
}
15070

151-
class _StackFrame {
15271

153-
// regex to match stack frames from ie/chrome/ff
154-
// methodName=$2, fileName=$4, lineNo=$5, column=$6
155-
public static regex = /^([\s]+at)?(.*?)(\@|\s\(|\s)([^\(\@\n]+):([0-9]+):([0-9]+)(\)?)$/;
156-
public static baseSize = 58; //'{"method":"","level":,"assembly":"","fileName":"","line":}'.length
157-
public sizeInBytes = 0;
158-
public level: number;
159-
public method: string;
160-
public assembly: string;
161-
public fileName: string;
162-
public line: number;
163-
164-
constructor(frame: string, level: number) {
165-
this.level = level;
166-
this.method = "<no_method>";
167-
this.assembly = Util.trim(frame);
168-
var matches = frame.match(_StackFrame.regex);
169-
if (matches && matches.length >= 5) {
170-
this.method = Util.trim(matches[2]) || this.method;
171-
this.fileName = Util.trim(matches[4]) || "<no_filename>";
172-
this.line = parseInt(matches[5]) || 0;
173-
}
174-
175-
this.sizeInBytes += this.method.length;
176-
this.sizeInBytes += this.fileName.length;
177-
this.sizeInBytes += this.assembly.length;
178-
179-
// todo: these might need to be removed depending on how the back-end settles on their size calculation
180-
this.sizeInBytes += _StackFrame.baseSize;
181-
this.sizeInBytes += this.level.toString().length;
182-
this.sizeInBytes += this.line.toString().length;
183-
}
184-
}
18572

18673
export = AutoCollectExceptions;

0 commit comments

Comments
 (0)