@teamscale/coverage-collector 0.0.1-beta.33 → 0.0.1-beta.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +1 -1
- package/dist/src/main.js +19 -15
- package/dist/src/receiver/CollectingServer.d.ts +1 -1
- package/dist/src/receiver/CollectingServer.js +8 -3
- package/dist/src/receiver/Session.d.ts +2 -2
- package/dist/src/receiver/Session.js +44 -7
- package/dist/src/storage/DataStorage.d.ts +1 -1
- package/dist/src/utils/PrettyFileLogger.d.ts +13 -0
- package/dist/src/utils/PrettyFileLogger.js +24 -0
- package/dist/src/utils/StdConsoleLogger.d.ts +5 -0
- package/dist/src/utils/StdConsoleLogger.js +15 -0
- package/package.json +1 -1
package/dist/package.json
CHANGED
package/dist/src/main.js
CHANGED
|
@@ -42,6 +42,8 @@ const util_1 = require("util");
|
|
|
42
42
|
const tmp_1 = __importDefault(require("tmp"));
|
|
43
43
|
const mkdirp_1 = __importDefault(require("mkdirp"));
|
|
44
44
|
const path_1 = __importDefault(require("path"));
|
|
45
|
+
const StdConsoleLogger_1 = require("./utils/StdConsoleLogger");
|
|
46
|
+
const PrettyFileLogger_1 = require("./utils/PrettyFileLogger");
|
|
45
47
|
/**
|
|
46
48
|
* The main class of the Teamscale JavaScript Collector.
|
|
47
49
|
* Used to start the collector for with a given configuration.
|
|
@@ -69,6 +71,10 @@ class Main {
|
|
|
69
71
|
help: 'Print received coverage information to the terminal?',
|
|
70
72
|
default: false
|
|
71
73
|
});
|
|
74
|
+
parser.add_argument('-j', '--json-log', {
|
|
75
|
+
help: 'Additional JSON-like log file format.',
|
|
76
|
+
action: 'store_true'
|
|
77
|
+
});
|
|
72
78
|
// Parameters for the upload to Teamscale
|
|
73
79
|
parser.add_argument('-u', '--teamscale-server-url', {
|
|
74
80
|
help: 'Upload the coverage to the given Teamscale server URL, for example, https://teamscale.dev.example.com:8080/production.',
|
|
@@ -122,22 +128,20 @@ class Main {
|
|
|
122
128
|
const logfilePath = config.log_to_file.trim();
|
|
123
129
|
mkdirp_1.default.sync(path_1.default.dirname(logfilePath));
|
|
124
130
|
const logLevel = config.log_level;
|
|
125
|
-
|
|
131
|
+
const logger = bunyan_1.default.createLogger({
|
|
132
|
+
name: 'Collector',
|
|
126
133
|
streams: [
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
path: logfilePath
|
|
139
|
-
}
|
|
140
|
-
] });
|
|
134
|
+
// console output
|
|
135
|
+
{ level: logLevel, stream: new StdConsoleLogger_1.StdConsoleLogger(), type: 'raw' },
|
|
136
|
+
// default log file
|
|
137
|
+
{ level: logLevel, stream: new PrettyFileLogger_1.PrettyFileLogger(fs.createWriteStream(logfilePath)), type: 'raw' }
|
|
138
|
+
]
|
|
139
|
+
});
|
|
140
|
+
// If the given flag is set, we also log with a JSON-like format
|
|
141
|
+
if (config.json_log) {
|
|
142
|
+
logger.addStream({ level: logLevel, path: `${logfilePath}.json` });
|
|
143
|
+
}
|
|
144
|
+
return logger;
|
|
141
145
|
}
|
|
142
146
|
/**
|
|
143
147
|
* Entry point of the Teamscale JavaScript Profiler.
|
|
@@ -133,14 +133,19 @@ class WebSocketCollectingServer {
|
|
|
133
133
|
*/
|
|
134
134
|
handleCoverageMessage(session, body) {
|
|
135
135
|
var _a;
|
|
136
|
-
const bodyPattern = /(?<fileId>\S+) (?<positions>((\d+:\d+)
|
|
136
|
+
const bodyPattern = /(?<fileId>\S+) (?<positions>((\d+:\d+(:\d+:\d+)?\s+)*(\d+:\d+(:\d+:\d+)?)))/;
|
|
137
137
|
const matches = bodyPattern.exec(body);
|
|
138
138
|
if (matches === null || matches === void 0 ? void 0 : matches.groups) {
|
|
139
139
|
const fileId = matches.groups.fileId;
|
|
140
140
|
const positions = ((_a = matches.groups.positions) !== null && _a !== void 0 ? _a : '').split(/\s+/);
|
|
141
141
|
for (const position of positions) {
|
|
142
|
-
const
|
|
143
|
-
|
|
142
|
+
const positionParts = position.split(':');
|
|
143
|
+
if (positionParts.length === 2) {
|
|
144
|
+
session.putCoverage(fileId, Number.parseInt(positionParts[0]), Number.parseInt(positionParts[1]), Number.parseInt(positionParts[1]), Number.parseInt(positionParts[2]));
|
|
145
|
+
}
|
|
146
|
+
else if (positionParts.length === 4) {
|
|
147
|
+
session.putCoverage(fileId, Number.parseInt(positionParts[0]), Number.parseInt(positionParts[1]), Number.parseInt(positionParts[2]), Number.parseInt(positionParts[3]));
|
|
148
|
+
}
|
|
144
149
|
}
|
|
145
150
|
}
|
|
146
151
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Socket } from 'net';
|
|
3
3
|
import { IDataStorage } from '../storage/DataStorage';
|
|
4
|
-
import Logger from
|
|
4
|
+
import Logger from 'bunyan';
|
|
5
5
|
/**
|
|
6
6
|
* The session maintains the relevant information for a client.
|
|
7
7
|
* One session is created for each client.
|
|
@@ -46,7 +46,7 @@ export declare class Session {
|
|
|
46
46
|
* @param line - The line number within the bundle.
|
|
47
47
|
* @param column - The column within the bundle.
|
|
48
48
|
*/
|
|
49
|
-
putCoverage(fileId: string,
|
|
49
|
+
putCoverage(fileId: string, startLine: number, startColumn: number, endLine: number, endColumn: number): void;
|
|
50
50
|
/**
|
|
51
51
|
* Map to the original file position.
|
|
52
52
|
*
|
|
@@ -54,13 +54,50 @@ class Session {
|
|
|
54
54
|
* @param line - The line number within the bundle.
|
|
55
55
|
* @param column - The column within the bundle.
|
|
56
56
|
*/
|
|
57
|
-
putCoverage(fileId,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
putCoverage(fileId, startLine, startColumn, endLine, endColumn) {
|
|
58
|
+
var _a, _b;
|
|
59
|
+
// Iterate over the lines to scan
|
|
60
|
+
let line = startLine;
|
|
61
|
+
while (line <= endLine) {
|
|
62
|
+
// Determine the column range to consider for this line
|
|
63
|
+
let scanFromColumn;
|
|
64
|
+
if (line === startLine) {
|
|
65
|
+
scanFromColumn = startColumn;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
scanFromColumn = 0;
|
|
69
|
+
}
|
|
70
|
+
let scanToColumn;
|
|
71
|
+
if (line === endLine) {
|
|
72
|
+
scanToColumn = endColumn;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Since we do not know the length of the different lines, we assume
|
|
76
|
+
// all to end in the lager of `endColumn` and `startColumn`.
|
|
77
|
+
// A better estimate (or the correct value) is supposed to be implemented
|
|
78
|
+
// in context of TS-30077.
|
|
79
|
+
scanToColumn = Math.max(endColumn, startColumn);
|
|
80
|
+
}
|
|
81
|
+
let column = scanFromColumn;
|
|
82
|
+
let lastCoveredLine = -1;
|
|
83
|
+
while (column <= scanToColumn) {
|
|
84
|
+
const originalPosition = this.mapToOriginal(fileId, line, column);
|
|
85
|
+
if (originalPosition.line && originalPosition.source) {
|
|
86
|
+
if (lastCoveredLine !== originalPosition.line) {
|
|
87
|
+
this.storage.putCoverage(this.projectId, originalPosition.source, [originalPosition.line]);
|
|
88
|
+
lastCoveredLine = originalPosition.line;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.storage.signalUnmappedCoverage(this.projectId);
|
|
93
|
+
}
|
|
94
|
+
// Step to the next column to map back to the original.
|
|
95
|
+
// `originalPosition.name` is the token on the position, that is, if it is present
|
|
96
|
+
// we increment the column by its length.
|
|
97
|
+
column = column + Math.max(1, (_b = (_a = originalPosition.name) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 1);
|
|
98
|
+
}
|
|
99
|
+
// And the next line
|
|
100
|
+
line++;
|
|
64
101
|
}
|
|
65
102
|
}
|
|
66
103
|
/**
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import 'dotenv/config';
|
|
3
|
+
import { WriteStream } from 'fs';
|
|
4
|
+
/**
|
|
5
|
+
* Class for log4j-like logger. Stream output shows less information than the
|
|
6
|
+
* standard JSON format of the bunyan logger and therefore has better readability.
|
|
7
|
+
*/
|
|
8
|
+
export declare class PrettyFileLogger {
|
|
9
|
+
outputStream: WriteStream;
|
|
10
|
+
constructor(outputStream: WriteStream);
|
|
11
|
+
write(rec: Record<any, any>): void;
|
|
12
|
+
end(): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PrettyFileLogger = void 0;
|
|
7
|
+
const bunyan_1 = __importDefault(require("bunyan"));
|
|
8
|
+
require("dotenv/config");
|
|
9
|
+
/**
|
|
10
|
+
* Class for log4j-like logger. Stream output shows less information than the
|
|
11
|
+
* standard JSON format of the bunyan logger and therefore has better readability.
|
|
12
|
+
*/
|
|
13
|
+
class PrettyFileLogger {
|
|
14
|
+
constructor(outputStream) {
|
|
15
|
+
this.outputStream = outputStream;
|
|
16
|
+
}
|
|
17
|
+
write(rec) {
|
|
18
|
+
this.outputStream.write(`[${rec.time.toISOString()}] ${bunyan_1.default.nameFromLevel[rec.level].toUpperCase()}: ${rec.msg}\n`);
|
|
19
|
+
}
|
|
20
|
+
end() {
|
|
21
|
+
this.outputStream.close();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.PrettyFileLogger = PrettyFileLogger;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.StdConsoleLogger = void 0;
|
|
7
|
+
const bunyan_1 = __importDefault(require("bunyan"));
|
|
8
|
+
require("dotenv/config");
|
|
9
|
+
/** Class for console logger. Doesn't print all information to ensure better readability. */
|
|
10
|
+
class StdConsoleLogger {
|
|
11
|
+
write(rec) {
|
|
12
|
+
console.log(`[${rec.time.toISOString()}] ${bunyan_1.default.nameFromLevel[rec.level].toUpperCase()}: ${rec.msg}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.StdConsoleLogger = StdConsoleLogger;
|