Skip to content

Commit 0c9bb55

Browse files
committed
feat: track hooks execution time
1 parent 85e97d8 commit 0c9bb55

File tree

4 files changed

+24
-9
lines changed

4 files changed

+24
-9
lines changed

lib/common/decorators.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { performance } = require('perf_hooks');
1+
import { AnalyticsEventLabelDelimiter } from "../constants";
22

33
/**
44
* Caches the result of the first execution of the method and returns it whenever it is called instead of executing it again.
@@ -91,28 +91,28 @@ export function performanceLog(injector?: IInjector): any {
9191
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor): any {
9292
const originalMethod = descriptor.value;
9393
const className = target.constructor.name;
94-
const trackName = `${className}.${propertyKey}`;
94+
const trackName = `${className}${AnalyticsEventLabelDelimiter}${propertyKey}`;
9595
const performanceService: IPerformanceService = injector.resolve("performanceService");
9696

9797
//needed for the returned function to have the same name as the original - used in hooks decorator
9898
const tempObject = {
9999
[originalMethod.name]: function (...args: Array<any>) {
100-
const start = performance.now();
100+
const start = performanceService.now();
101101
const result = originalMethod.apply(this, args);
102102
const resolvedPromise = Promise.resolve(result);
103103
let end;
104104

105105
if (resolvedPromise !== result) {
106-
end = performance.now();
106+
end = performanceService.now();
107107
performanceService.processExecutionData(trackName, start, end, args);
108108
} else {
109109
resolvedPromise
110110
.then(() => {
111-
end = performance.now();
111+
end = performanceService.now();
112112
performanceService.processExecutionData(trackName, start, end, args);
113113
})
114114
.catch((err) => {
115-
end = performance.now();
115+
end = performanceService.now();
116116
performanceService.processExecutionData(trackName, start, end, args);
117117
});
118118

lib/common/services/hooks-service.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as path from "path";
22
import * as util from "util";
33
import { annotate, getValueFromNestedObject } from "../helpers";
4+
import { AnalyticsEventLabelDelimiter } from "../../constants";
45

56
class Hook implements IHook {
67
constructor(public name: string,
@@ -22,7 +23,8 @@ export class HooksService implements IHooksService {
2223
private $staticConfig: Config.IStaticConfig,
2324
private $injector: IInjector,
2425
private $projectHelper: IProjectHelper,
25-
private $options: IOptions) { }
26+
private $options: IOptions,
27+
private $performanceService: IPerformanceService) { }
2628

2729
public get hookArgsName(): string {
2830
return "hookArgs";
@@ -93,9 +95,11 @@ export class HooksService implements IHooksService {
9395
hookArguments = hookArguments || {};
9496
const results: any[] = [];
9597
const hooks = this.getHooksByName(directoryPath, hookName);
98+
9699
for (let i = 0; i < hooks.length; ++i) {
97100
const hook = hooks[i];
98-
this.$logger.info("Executing %s hook from %s", hookName, hook.fullPath);
101+
const relativePath = path.relative(directoryPath, hook.fullPath);
102+
const trackId = relativePath.replace(new RegExp('\\' + path.sep, 'g'), AnalyticsEventLabelDelimiter);
99103
let command = this.getSheBangInterpreter(hook);
100104
let inProc = false;
101105
if (!command) {
@@ -106,6 +110,7 @@ export class HooksService implements IHooksService {
106110
}
107111
}
108112

113+
const startTime = this.$performanceService.now();
109114
if (inProc) {
110115
this.$logger.trace("Executing %s hook at location %s in-process", hookName, hook.fullPath);
111116
const hookEntryPoint = require(hook.fullPath);
@@ -155,7 +160,11 @@ export class HooksService implements IHooksService {
155160
if (output.exitCode !== 0) {
156161
throw new Error(output.stdout + output.stderr);
157162
}
163+
164+
this.$logger.trace("Finished executing %s hook at location %s with environment ", hookName, hook.fullPath, environment);
158165
}
166+
const endTime = this.$performanceService.now();
167+
this.$performanceService.processExecutionData(trackId, startTime, endTime, [hookArguments]);
159168
}
160169

161170
return results;

lib/declarations.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ interface INodePackageManager {
7777

7878
interface IPerformanceService {
7979
processExecutionData(methodInfo: string, startTime: number, endTime: number, args: any[]): void;
80+
now(): number;
8081
}
8182

8283
interface IPackageInstallationManager {

lib/services/performance-service.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { TrackActionNames } from "../constants";
1+
import { TrackActionNames, AnalyticsEventLabelDelimiter } from "../constants";
22
const EOL = require("os").EOL;
33
import { getFormattedDate } from "../common/helpers";
4+
const { performance } = require('perf_hooks');
45

56
export class PerformanceService implements IPerformanceService {
67
public static LOG_MESSAGE_TEMPLATE = `Execution of method "%s" took %s ms.`;
@@ -25,6 +26,10 @@ export class PerformanceService implements IPerformanceService {
2526
}
2627
}
2728

29+
public now(): number {
30+
return performance.now();
31+
}
32+
2833
private trackAnalyticsData(methodInfo: string, executionTime: number): void {
2934
this.$analyticsService.trackEventActionInGoogleAnalytics({
3035
action: TrackActionNames.Performance,

0 commit comments

Comments
 (0)