123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- /**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow
- * @format
- */
- 'use strict';
- const Systrace = require('../Performance/Systrace');
- const infoLog = require('./infoLog');
- const performanceNow =
- global.nativeQPLTimestamp ||
- global.nativePerformanceNow ||
- require('fbjs/lib/performanceNow');
- type Timespan = {
- description?: string,
- totalTime?: number,
- startTime?: number,
- endTime?: number,
- ...
- };
- export type IPerformanceLogger = {
- addTimespan(string, number, string | void): void,
- startTimespan(string, string | void): void,
- stopTimespan(string, options?: {update?: boolean}): void,
- clear(): void,
- clearCompleted(): void,
- clearExceptTimespans(Array<string>): void,
- currentTimestamp(): number,
- getTimespans(): {[key: string]: Timespan, ...},
- hasTimespan(string): boolean,
- logTimespans(): void,
- addTimespans(Array<number>, Array<string>): void,
- setExtra(string, any): void,
- getExtras(): {[key: string]: any, ...},
- removeExtra(string): ?any,
- logExtras(): void,
- markPoint(string, number | void): void,
- getPoints(): {[key: string]: number, ...},
- logPoints(): void,
- logEverything(): void,
- ...
- };
- const _cookies: {[key: string]: number, ...} = {};
- const PRINT_TO_CONSOLE: false = false; // Type as false to prevent accidentally committing `true`;
- /**
- * This function creates performance loggers that can be used to collect and log
- * various performance data such as timespans, points and extras.
- * The loggers need to have minimal overhead since they're used in production.
- */
- function createPerformanceLogger(): IPerformanceLogger {
- const result: IPerformanceLogger & {
- _timespans: {[key: string]: Timespan, ...},
- _extras: {[key: string]: any, ...},
- _points: {[key: string]: number, ...},
- ...
- } = {
- _timespans: {},
- _extras: {},
- _points: {},
- addTimespan(key: string, lengthInMs: number, description?: string) {
- if (this._timespans[key]) {
- if (PRINT_TO_CONSOLE && __DEV__) {
- infoLog(
- 'PerformanceLogger: Attempting to add a timespan that already exists ',
- key,
- );
- }
- return;
- }
- this._timespans[key] = {
- description: description,
- totalTime: lengthInMs,
- };
- },
- startTimespan(key: string, description?: string) {
- if (this._timespans[key]) {
- if (PRINT_TO_CONSOLE && __DEV__) {
- infoLog(
- 'PerformanceLogger: Attempting to start a timespan that already exists ',
- key,
- );
- }
- return;
- }
- this._timespans[key] = {
- description: description,
- startTime: performanceNow(),
- };
- _cookies[key] = Systrace.beginAsyncEvent(key);
- if (PRINT_TO_CONSOLE) {
- infoLog('PerformanceLogger.js', 'start: ' + key);
- }
- },
- stopTimespan(key: string, options?: {update?: boolean}) {
- const timespan = this._timespans[key];
- if (!timespan || !timespan.startTime) {
- if (PRINT_TO_CONSOLE && __DEV__) {
- infoLog(
- 'PerformanceLogger: Attempting to end a timespan that has not started ',
- key,
- );
- }
- return;
- }
- if (timespan.endTime && !options?.update) {
- if (PRINT_TO_CONSOLE && __DEV__) {
- infoLog(
- 'PerformanceLogger: Attempting to end a timespan that has already ended ',
- key,
- );
- }
- return;
- }
- timespan.endTime = performanceNow();
- timespan.totalTime = timespan.endTime - (timespan.startTime || 0);
- if (PRINT_TO_CONSOLE) {
- infoLog('PerformanceLogger.js', 'end: ' + key);
- }
- if (_cookies[key] != null) {
- Systrace.endAsyncEvent(key, _cookies[key]);
- delete _cookies[key];
- }
- },
- clear() {
- this._timespans = {};
- this._extras = {};
- this._points = {};
- if (PRINT_TO_CONSOLE) {
- infoLog('PerformanceLogger.js', 'clear');
- }
- },
- clearCompleted() {
- for (const key in this._timespans) {
- if (this._timespans[key].totalTime) {
- delete this._timespans[key];
- }
- }
- this._extras = {};
- this._points = {};
- if (PRINT_TO_CONSOLE) {
- infoLog('PerformanceLogger.js', 'clearCompleted');
- }
- },
- clearExceptTimespans(keys: Array<string>) {
- this._timespans = Object.keys(this._timespans).reduce(function(
- previous,
- key,
- ) {
- if (keys.indexOf(key) !== -1) {
- previous[key] = this._timespans[key];
- }
- return previous;
- },
- {});
- this._extras = {};
- this._points = {};
- if (PRINT_TO_CONSOLE) {
- infoLog('PerformanceLogger.js', 'clearExceptTimespans', keys);
- }
- },
- currentTimestamp() {
- return performanceNow();
- },
- getTimespans() {
- return this._timespans;
- },
- hasTimespan(key: string) {
- return !!this._timespans[key];
- },
- logTimespans() {
- if (PRINT_TO_CONSOLE) {
- for (const key in this._timespans) {
- if (this._timespans[key].totalTime) {
- infoLog(key + ': ' + this._timespans[key].totalTime + 'ms');
- }
- }
- }
- },
- addTimespans(newTimespans: Array<number>, labels: Array<string>) {
- for (let ii = 0, l = newTimespans.length; ii < l; ii += 2) {
- const label = labels[ii / 2];
- this.addTimespan(label, newTimespans[ii + 1] - newTimespans[ii], label);
- }
- },
- setExtra(key: string, value: any) {
- if (this._extras[key]) {
- if (PRINT_TO_CONSOLE && __DEV__) {
- infoLog(
- 'PerformanceLogger: Attempting to set an extra that already exists ',
- {key, currentValue: this._extras[key], attemptedValue: value},
- );
- }
- return;
- }
- this._extras[key] = value;
- },
- getExtras() {
- return this._extras;
- },
- removeExtra(key: string): ?any {
- const value = this._extras[key];
- delete this._extras[key];
- return value;
- },
- logExtras() {
- if (PRINT_TO_CONSOLE) {
- infoLog(this._extras);
- }
- },
- markPoint(key: string, timestamp?: number) {
- if (this._points[key]) {
- if (PRINT_TO_CONSOLE && __DEV__) {
- infoLog(
- 'PerformanceLogger: Attempting to mark a point that has been already logged ',
- key,
- );
- }
- return;
- }
- this._points[key] = timestamp ?? performanceNow();
- },
- getPoints() {
- return this._points;
- },
- logPoints() {
- if (PRINT_TO_CONSOLE) {
- for (const key in this._points) {
- infoLog(key + ': ' + this._points[key] + 'ms');
- }
- }
- },
- logEverything() {
- this.logTimespans();
- this.logExtras();
- this.logPoints();
- },
- };
- return result;
- }
- module.exports = createPerformanceLogger;
|