Skip to content

Use optional module "@microsoft/typescript-etw" for ETW logging #32612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@types/gulp-sourcemaps": "0.0.32",
"@types/jake": "latest",
"@types/merge2": "latest",
"@types/microsoft__typescript-etw": "latest",
"@types/minimatch": "latest",
"@types/minimist": "latest",
"@types/mkdirp": "latest",
Expand Down Expand Up @@ -109,7 +110,8 @@
"browser": {
"fs": false,
"os": false,
"path": false
"path": false,
"@microsoft/typescript-etw": false
},
"dependencies": {}
}
2 changes: 2 additions & 0 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ namespace ts {

export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
performance.mark("beforeBind");
perfLogger.logStartBindFile("" + file.fileName);
binder(file, options);
perfLogger.logStopBindFile();
performance.mark("afterBind");
performance.measure("Bind", "beforeBind", "afterBind");
}
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/moduleNameResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@ namespace ts {
}
}

perfLogger.logStartResolveModule(moduleName /* , containingFile, ModuleResolutionKind[moduleResolution]*/);
switch (moduleResolution) {
case ModuleResolutionKind.NodeJs:
result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference);
Expand All @@ -675,6 +676,8 @@ namespace ts {
default:
return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`);
}
if (result && result.resolvedModule) perfLogger.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`);
perfLogger.logStopResolveModule((result && result.resolvedModule) ? "" + result.resolvedModule.resolvedFileName : "null");

if (perFolderCache) {
perFolderCache.set(moduleName, result);
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,12 +512,16 @@ namespace ts {
export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
performance.mark("beforeParse");
let result: SourceFile;

perfLogger.logStartParseSourceFile(fileName);
if (languageVersion === ScriptTarget.JSON) {
result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, ScriptKind.JSON);
}
else {
result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
}
perfLogger.logStopParseSourceFile();

performance.mark("afterParse");
performance.measure("Parse", "beforeParse", "afterParse");
return result;
Expand Down
43 changes: 43 additions & 0 deletions src/compiler/perfLogger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* @internal */
namespace ts {
type PerfLogger = typeof import("@microsoft/typescript-etw"); // tslint:disable-line:no-implicit-dependencies
const nullLogger: PerfLogger = {
logEvent: noop,
logErrEvent: noop,
logPerfEvent: noop,
logInfoEvent: noop,
logStartCommand: noop,
logStopCommand: noop,
logStartUpdateProgram: noop,
logStopUpdateProgram: noop,
logStartUpdateGraph: noop,
logStopUpdateGraph: noop,
logStartResolveModule: noop,
logStopResolveModule: noop,
logStartParseSourceFile: noop,
logStopParseSourceFile: noop,
logStartReadFile: noop,
logStopReadFile: noop,
logStartBindFile: noop,
logStopBindFile: noop,
logStartScheduledOperation: noop,
logStopScheduledOperation: noop,
};

// Load optional module to enable Event Tracing for Windows
// See https://github.com/microsoft/typescript-etw for more information
let etwModule;
try {
// require() will throw an exception if the module is not installed
// It may also return undefined if not installed properly
etwModule = require("@microsoft/typescript-etw"); // tslint:disable-line:no-implicit-dependencies
}
catch (e) {
etwModule = undefined;
}

/** Performance logger that will generate ETW events if possible */
export const perfLogger: PerfLogger = etwModule ? etwModule : nullLogger;

perfLogger.logInfoEvent(`Starting TypeScript v${versionMajorMinor} with command line: ${JSON.stringify(process.argv)}`);
}
12 changes: 11 additions & 1 deletion src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ namespace ts {
return (directoryName, callback) => fsWatchFile(directoryName, () => callback(directoryName), PollingInterval.Medium);
}

function readFile(fileName: string, _encoding?: string): string | undefined {
function readFileWorker(fileName: string, _encoding?: string): string | undefined {
if (!fileExists(fileName)) {
return undefined;
}
Expand Down Expand Up @@ -1115,7 +1115,15 @@ namespace ts {
return buffer.toString("utf8");
}

function readFile(fileName: string, _encoding?: string): string | undefined {
perfLogger.logStartReadFile(fileName);
const file = readFileWorker(fileName, _encoding);
perfLogger.logStopReadFile();
return file;
}

function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
perfLogger.logEvent("WriteFile: " + fileName);
// If a BOM is required, emit one
if (writeByteOrderMark) {
data = byteOrderMarkIndicator + data;
Expand All @@ -1135,6 +1143,7 @@ namespace ts {
}

function getAccessibleFileSystemEntries(path: string): FileSystemEntries {
perfLogger.logEvent("ReadDir: " + (path || "."));
try {
const entries = _fs.readdirSync(path || ".").sort();
const files: string[] = [];
Expand Down Expand Up @@ -1196,6 +1205,7 @@ namespace ts {
}

function getDirectories(path: string): string[] {
perfLogger.logEvent("ReadDir: " + path);
return filter<string>(_fs.readdirSync(path), dir => fileSystemEntryExists(combinePaths(path, dir), FileSystemEntryKind.Directory));
}

Expand Down
1 change: 1 addition & 0 deletions src/compiler/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"core.ts",
"debug.ts",
"performance.ts",
"perfLogger.ts",
"semver.ts",

"types.ts",
Expand Down
12 changes: 9 additions & 3 deletions src/compiler/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1005,13 +1005,19 @@ namespace ts {

switch (reloadLevel) {
case ConfigFileProgramReloadLevel.Partial:
return reloadFileNamesFromConfigFile();
perfLogger.logStartUpdateProgram("PartialConfigReload");
reloadFileNamesFromConfigFile();
break;
case ConfigFileProgramReloadLevel.Full:
return reloadConfigFile();
perfLogger.logStartUpdateProgram("FullConfigReload");
reloadConfigFile();
break;
default:
perfLogger.logStartUpdateProgram("SynchronizeProgram");
synchronizeProgram();
return;
break;
}
perfLogger.logStopUpdateProgram("Done");
}

function reloadFileNamesFromConfigFile() {
Expand Down
2 changes: 2 additions & 0 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,7 @@ namespace ts.server {
* @returns: true if set of files in the project stays the same and false - otherwise.
*/
updateGraph(): boolean {
perfLogger.logStartUpdateGraph();
this.resolutionCache.startRecordingFilesWithChangedResolutions();

const hasNewProgram = this.updateGraphWorker();
Expand Down Expand Up @@ -886,6 +887,7 @@ namespace ts.server {
if (hasNewProgram) {
this.projectProgramVersion++;
}
perfLogger.logStopUpdateGraph();
return !hasNewProgram;
}

Expand Down
12 changes: 11 additions & 1 deletion src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,9 @@ namespace ts.server {
}
return;
}
this.host.write(formatMessage(msg, this.logger, this.byteLength, this.host.newLine));
const msgText = formatMessage(msg, this.logger, this.byteLength, this.host.newLine);
perfLogger.logEvent(`Response message size: ${msgText.length}`);
this.host.write(msgText);
}

public event<T extends object>(body: T, eventName: string): void {
Expand Down Expand Up @@ -2509,6 +2511,8 @@ namespace ts.server {
try {
request = <protocol.Request>JSON.parse(message);
relevantFile = request.arguments && (request as protocol.FileRequest).arguments.file ? (request as protocol.FileRequest).arguments : undefined;

perfLogger.logStartCommand("" + request.command, message.substring(0, 100));
const { response, responseRequired } = this.executeCommand(request);

if (this.logger.hasLevel(LogLevel.requestTime)) {
Expand All @@ -2521,6 +2525,8 @@ namespace ts.server {
}
}

// Note: Log before writing the response, else the editor can complete its activity before the server does
perfLogger.logStopCommand("" + request.command, "Success");
if (response) {
this.doOutput(response, request.command, request.seq, /*success*/ true);
}
Expand All @@ -2531,10 +2537,14 @@ namespace ts.server {
catch (err) {
if (err instanceof OperationCanceledException) {
// Handle cancellation exceptions
perfLogger.logStopCommand("" + (request && request.command), "Canceled: " + err);
this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true);
return;
}

this.logErrorWorker(err, message, relevantFile);
perfLogger.logStopCommand("" + (request && request.command), "Error: " + err);

this.doOutput(
/*info*/ undefined,
request ? request.command : CommandNames.Unknown,
Expand Down
4 changes: 4 additions & 0 deletions src/server/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,13 @@ namespace ts.server {
}

private static run(self: ThrottledOperations, operationId: string, cb: () => void) {
perfLogger.logStartScheduledOperation(operationId);
self.pendingTimeouts.delete(operationId);
if (self.logger) {
self.logger.info(`Running: ${operationId}`);
}
cb();
perfLogger.logStopScheduledOperation();
}
}

Expand All @@ -174,6 +176,7 @@ namespace ts.server {
private static run(self: GcTimer) {
self.timerId = undefined;

perfLogger.logStartScheduledOperation("GC collect");
const log = self.logger.hasLevel(LogLevel.requestTime);
const before = log && self.host.getMemoryUsage!(); // TODO: GH#18217

Expand All @@ -182,6 +185,7 @@ namespace ts.server {
const after = self.host.getMemoryUsage!(); // TODO: GH#18217
self.logger.perftrc(`GC::before ${before}, after ${after}`);
}
perfLogger.logStopScheduledOperation();
}
}

Expand Down
12 changes: 12 additions & 0 deletions src/tsserver/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,18 @@ namespace ts.server {
}

msg(s: string, type: Msg = Msg.Err) {
switch (type) {
case Msg.Info:
perfLogger.logInfoEvent(s);
break;
case Msg.Perf:
perfLogger.logPerfEvent(s);
break;
default: // Msg.Err
perfLogger.logErrEvent(s);
break;
}

if (!this.canWrite) return;

s = `[${nowString()}] ${s}\n`;
Expand Down