Skip to content
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

WIP: Tracing #4

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c5b4d99
mapped spawn()
kawing-ho Jan 9, 2019
8f07533
mapped execCommand()
kawing-ho Jan 9, 2019
f78ee09
mapped index.js => main()
kawing-ho Jan 9, 2019
1128169
mapped header()/footer()
kawing-ho Jan 9, 2019
cba4da9
added new logging file and imported in relevant files
kawing-ho Jan 9, 2019
49b0867
missing t
kawing-ho Jan 9, 2019
1d514a1
intermeddiate push
kawing-ho Jan 10, 2019
1498475
Merge branch 'kawing-yarn' of github.com:stemn/yarn into kawing-yarn
kawing-ho Jan 10, 2019
8f7d024
indentation issue
kawing-ho Jan 10, 2019
ac9de0f
debugging -> debug
kawing-ho Jan 10, 2019
48edb39
added header/footer
kawing-ho Jan 10, 2019
037076b
moved first_timestamp up
kawing-ho Jan 10, 2019
dc04138
transitioned to environment variables
kawing-ho Jan 11, 2019
0936eb7
quotes
kawing-ho Jan 11, 2019
cc9ce10
tab
kawing-ho Jan 11, 2019
9e0343f
made some changes, indentation on the way
kawing-ho Jan 14, 2019
ee45409
commit before sleep
kawing-ho Jan 14, 2019
c596262
commit before the server crashes again lol
kawing-ho Jan 15, 2019
6ed59d1
fixed
kawing-ho Jan 15, 2019
2aa69b3
indenting
kawing-ho Jan 15, 2019
eb0a0f9
cleaner output so not logging timestamp
kawing-ho Jan 15, 2019
d2a9c5d
added braces
kawing-ho Jan 15, 2019
e20804b
pretty print pretty much done
kawing-ho Jan 15, 2019
b9ebf41
touch-ups
kawing-ho Jan 15, 2019
241359b
added jaeger-client to package.json
kawing-ho Jan 15, 2019
13c9a1f
Revert "touch-ups"
kawing-ho Jan 15, 2019
9d15063
Revert "Revert "touch-ups""
kawing-ho Jan 16, 2019
43703dd
Revert "added jaeger-client to package.json"
kawing-ho Jan 16, 2019
76c13cb
edited a word
kawing-ho Jan 16, 2019
b791b3e
Merge branch 'master' of github.com:yarnpkg/yarn into kawing-yarn-mer…
sabrehagen Jan 18, 2019
0cc6962
name
sabrehagen Mar 11, 2019
787d144
bump
sabrehagen Mar 11, 2019
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: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "yarn",
"name": "@stemn/yarn",
"installationMethod": "unknown",
"version": "1.14.0-0",
"version": "1.14.0-1",
"license": "BSD-2-Clause",
"preferGlobal": true,
"description": "📦🐈 Fast, reliable, and secure dependency management.",
Expand Down
13 changes: 13 additions & 0 deletions src/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import {version} from '../util/yarn-version.js';
import handleSignals from '../util/signal-handler.js';
import {boolify, boolifyWithDefault} from '../util/conversion.js';

// STEMN import
import {benchmark, debug} from './logging.js';

function findProjectRoot(base: string): string {
let prev = null;
let dir = base;
Expand All @@ -41,6 +44,7 @@ function findProjectRoot(base: string): string {
return base;
}

/* [STEMN]: main function here (multiple threads executed) */
export async function main({
startArgs,
args,
Expand Down Expand Up @@ -246,6 +250,8 @@ export async function main({
const outputWrapperEnabled = boolifyWithDefault(process.env.YARN_WRAP_OUTPUT, true);
const shouldWrapOutput = outputWrapperEnabled && !commander.json && command.hasWrapper(commander, commander.args);



if (shouldWrapOutput) {
reporter.header(commandName, {name: 'yarn', version});
}
Expand Down Expand Up @@ -283,6 +289,10 @@ export async function main({
if (shouldWrapOutput) {
reporter.footer(false);
}

/* [STEMN]: Possible hook here for exitCode conditional code */


return exitCode;
});
};
Expand Down Expand Up @@ -478,6 +488,9 @@ export async function main({
if (errorReportLoc) {
reporter.info(reporter.lang('bugReport', errorReportLoc));
}

/* [STEMN]: Warn in logs about unexpected error -> inconsistencies */
debug(">>>>>>>> WARNING: LOGS MAY BE INCONSISTENT DUE TO ERROR <<<<<<<<\n");
}

function writeErrorReport(log): ?string {
Expand Down
70 changes: 70 additions & 0 deletions src/cli/logging.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const fs = require('fs');
const rl = require("readline");
const spawn = require('child_process').spawnSync;



// outputs a string to the main CSV file
export function benchmark(str: string) {
let log_location = process.env["YARN_LOG_PATH"] || "/tmp/yarn.csv";
fs.appendFileSync(log_location, str, function(err){if (err) throw err;});
}

// outputs a string to the debugging log file
export function debug(str: string) {
let log_location = process.env["YARN_DEBUG_PATH"] || "/tmp/debug.log";
fs.appendFileSync(log_location, str, function(err){if (err) throw err;});
}

// post processes the debug log information into a more span-like format
export function post_process() {
let log_location = process.env["YARN_DEBUG_PATH"] || "/tmp/debug.log";

// run $(column) on data and
let results = [];
let child = spawn("column", ["-s", "," , "-t", log_location]);
results = child.stdout.toString().split("\n");
if(!results) { console.error("Make sure column is installed and in $PATH !"); }

results = results.filter(String); // remove empty string

let depth = 1;
results.forEach( function(s, index) {

// change the indenting (conditional)
let indent_depth = depth;

// BEGIN and END of same process should be on same indent
if(results[index].match("END") && results[index-1].match("BEGIN")) {
indent_depth = depth - 1;
depth--;
}

if(results[index].match("BEGIN") && index > 0 && results[index-1].match("END")) {
indent_depth = depth + 1;
depth++;
}

results[index] = `(${indent_depth-1})\t` + " ".repeat(indent_depth-1) + s;
results[index] = results[index].replace(/\]\t/, "]\t\t");

// increase/decrease indent for next line
if(s.match("BEGIN")) {
depth++;
} else if (s.match("END")) {
depth--;
} else { throw new Error('Regex mismatch !'); }
});

// change BEGIN and END to new separators
results.forEach( function(s, index) {
results[index] = results[index].replace(/ *(BEGIN|END) */,"^");
});

// run $(column) a second time
child = spawn("column", ["-s", "^", "-t"], {input: results.join("\n") + "\n"});

// write output to file
fs.writeFileSync(log_location, child.stdout.toString(), function(err){if (err) throw err;});

}
35 changes: 35 additions & 0 deletions src/reporters/console/console-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import {sortTrees, recurseTree, getFormattedOutput} from './helpers/tree-helper.
import inquirer from 'inquirer';
import Table from 'cli-table3';

// STEMN import
import {benchmark, debug, post_process} from '../../cli/logging.js';
const fs = require('fs');

const {inspect} = require('util');
const readline = require('readline');
const chalk = require('chalk');
Expand Down Expand Up @@ -159,20 +163,51 @@ export default class ConsoleReporter extends BaseReporter {
}
}

/* [STEMN]: header reporter. Hook to clean logs */
header(command: string, pkg: Package) {
this.log(this.format.bold(`${pkg.name} ${command} v${pkg.version}`));

if(!process.env.YARN_LOG_PATH) {
this._logCategory('LOGGING', 'magenta', "YARN_LOG_PATH env var not found.\tDefaulting to \'/tmp/yarn.csv\'");
}

if(!process.env.YARN_DEBUG_PATH) {
this._logCategory('LOGGING', 'magenta', "YARN_DEBUG_PATH env var not found.\tDefaulting to \'/tmp/debug.log\'");
}

// we perform our own reporting as well
this._logCategory('LOGGING', 'magenta', "Cleaning logs of previous run...");
this._logCategory('LOGGING', 'magenta', "Truncating and preparing log file...");
let log_location = process.env["YARN_LOG_PATH"] || "/tmp/yarn.csv";
let debug_location = process.env["YARN_DEBUG_PATH"] || "/tmp/debug.log";

fs.writeFile(log_location, '', function(){})
fs.writeFile(debug_location, '', function(){})

var csv_header = "PID,Command,Timestamp,Duration,PWD\n";
fs.writeFileSync(log_location, csv_header, function (err) {
if (err) throw err;
});

}

/* [STEMN]: footer reporter. Hook to do log post-processing */
footer(showPeakMemory?: boolean) {
this.stopProgress();

let log_location = process.env["YARN_LOG_PATH"] || "/tmp/yarn.csv";

const totalTime = (this.getTotalTime() / 1000).toFixed(2);
let msg = `Done in ${totalTime}s.`;
if (showPeakMemory) {
const peakMemory = (this.peakMemory / 1024 / 1024).toFixed(2);
msg += ` Peak memory usage ${peakMemory}MB.`;
}
this.log(this._prependEmoji(msg, '✨'));

this._logCategory('LOGGING', 'magenta', "Post-processing logs into suitable format...");
post_process();
this._logCategory('LOGGING', 'magenta', "Output file: " + this.format.underline(log_location));
}

log(msg: string, {force = false}: {force?: boolean} = {}) {
Expand Down
52 changes: 52 additions & 0 deletions src/util/child.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import BlockingQueue from './blocking-queue.js';
import {ProcessSpawnError, ProcessTermError} from '../errors.js';
import {promisify} from './promise.js';

// STEMN import
import {benchmark, debug} from '../cli/logging.js';

const child = require('child_process');

export const queue = new BlockingQueue('child', constants.CHILD_CONCURRENCY);
Expand Down Expand Up @@ -58,6 +61,7 @@ type ProcessFn = (
done: () => void,
) => void;

/* [STEMN]: Trace for subprocesses ie. script files */
export function spawn(
program: string,
args: Array<string>,
Expand All @@ -72,6 +76,26 @@ export function spawn(
const proc = child.spawn(program, args, opts);
spawnedProcesses[key] = proc;

let first_timestamp = (new Date() / 1000);
let trace = "";
let duration = "-";
let cwd = key;

// if we ever decide to do parent-child relationships
// trace += `${process.ppid } spawned ${process.pid} spawned ${proc.pid}`

trace += `[${proc.pid}],`;
trace += `BEGIN,`;
trace += `[${program}],`;
//trace += `[${first_timestamp}],`;
trace += `[${duration}],`;
trace += `[${cwd}]\n`;

// only log it if the subprocess has ".sh"
if(program.indexOf(".sh") > -1) {
debug(trace);
}

let processingDone = false;
let processClosed = false;
let err = null;
Expand All @@ -95,6 +119,34 @@ export function spawn(

function finish() {
delete spawnedProcesses[key];


/* [STEMN]: Trace script when finishing execution */
let final_timestamp = ((new Date() / 1000)).toFixed(3);
let duration = (final_timestamp - first_timestamp).toFixed(3);
let trace = "";
trace += `[${proc.pid}],`;
trace += `END,`;
trace += `[${program}],`;
//trace += `[${final_timestamp}],`;
trace += `[${duration}],`;
trace += `[${cwd}]\n`;

// only log it if the subprocess has ".sh"
if(program.indexOf(".sh") > -1) {
debug(trace);

// Add the finished process to the stack for printing
let csv_line = "";
csv_line += `${proc.pid},`;
csv_line += `\"${program}\",`
csv_line += `${first_timestamp},`
csv_line += `${duration},`
csv_line += `\"${key}\"\n`;

benchmark(csv_line);
}

if (err) {
reject(err);
} else {
Expand Down
45 changes: 45 additions & 0 deletions src/util/execute-lifecycle-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {registries} from '../resolvers/index.js';
import {fixCmdWinSlashes} from './fix-cmd-win-slashes.js';
import {getBinFolder as getGlobalBinFolder, run as globalRun} from '../cli/commands/global.js';

// STEMN import
import {benchmark, debug} from '../cli/logging.js';

const path = require('path');

export type LifecycleReturn = Promise<{
Expand Down Expand Up @@ -356,7 +359,23 @@ export async function execCommand({
customShell?: string,
}): Promise<void> {
const {reporter} = config;

/* [STEMN]: Trace execCommand start execution time */
let first_timestamp = (new Date() / 1000).toFixed(3);
let duration = "-"; // no duration at the start

try {

let trace = "";
trace += `[${process.pid}],`;
trace += `BEGIN,`;
trace += `[${stage}],`;
//trace += `[${first_timestamp}],`;
trace += `[${duration}],`;
trace += `[${cwd}]\n`;

debug(trace);

reporter.command(cmd);
await executeLifecycleScript({stage, config, cwd, cmd, isInteractive, customShell});
return Promise.resolve();
Expand All @@ -370,5 +389,31 @@ export async function execCommand({
} else {
throw err;
}
} finally {

/* [STEMN]: Trace execCommand finish exeuction time */

//var trace = `[${process.ppid}]->[${process.pid}][${process.uptime()}] >END<`

let final_timestamp = ((new Date() / 1000).toFixed(3));
let duration = (final_timestamp - first_timestamp).toFixed(2);
let trace = "";
trace += `[${process.pid}],`;
trace += `END,`;
trace += `[${stage}],`;
//trace += `[${final_timestamp}],`;
trace += `[${duration}],`;
trace += `[${cwd}]\n`;

debug(trace);

// PID, STAGE, TIMESTAMP, DURATION, CWD
let csv_line = "";
csv_line = `${process.pid},`;
csv_line += `\"${stage}\",`;
csv_line += `${first_timestamp},`;
csv_line += `${duration},`;
csv_line += `\"${cwd}\"\n`;
benchmark(csv_line);
}
}