-
Notifications
You must be signed in to change notification settings - Fork 214
Expand file tree
/
Copy pathperformance.js
More file actions
127 lines (118 loc) · 3.66 KB
/
performance.js
File metadata and controls
127 lines (118 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import logger from './logger-instance'
export const PERFORMANCE_MARKS = {
total: 'ssr.total',
renderToString: 'ssr.render-to-string',
routeMatching: 'ssr.route-matching',
loadComponent: 'ssr.load-component',
fetchStrategies: 'ssr.fetch-strategies',
reactQueryPrerender: 'ssr.fetch-strategies.react-query.pre-render',
reactQueryUseQuery: 'ssr.fetch-strategies.react-query.use-query',
getProps: 'ssr.fetch-strategies.get-prop'
}
/**
* This is an SDK internal class that is responsible for measuring server side performance.
*
* This class manages two types of performance marks: start and end.
*
* By default, this timer is disabled. Only certain environment variables and feature flags turns it on.
*
* @private
*/
export default class PerformanceTimer {
MARKER_TYPES = {
START: 'start',
END: 'end'
}
constructor(options = {}) {
this.enabled = options.enabled || false
this.marks = {
start: new Map(),
end: new Map()
}
this.metrics = []
}
/**
* This is a utility function to build the Server-Timing header.
* The function receives an array of performance metrics and returns a string that represents the Server-Timing header.
*
* see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing
*
* @function
* @private
*
* @return {String}
*/
buildServerTimingHeader() {
const header = this.metrics
.map((metric) => {
return `${metric.name};dur=${metric.duration.toFixed(2)}`
})
.join(', ')
return header
}
/**
* A utility function to format and log the performance metrics.
*
* @function
* @private
*/
log() {
this.metrics.forEach((metric) => {
logger.info(`${metric.name} - ${metric.duration}ms ${metric.detail || ''}`, {
namespace: 'performance'
})
})
}
/**
* This is a utility function to create performance marks.
* The data will be used in console logs and the http response header `server-timing`.
*
* @function
* @private
*/
mark(name, type, options = {}) {
if (!this.enabled) {
return
}
if (!name) {
logger.warn('Performance mark cannot be created because the name is undefined.', {
namespace: 'performance'
})
return
}
if (type !== this.MARKER_TYPES.START && type !== this.MARKER_TYPES.END) {
logger.warn(
'Performance mark cannot be created because the type must be either "start" or "end".',
{
namespace: 'performance'
}
)
return
}
const timestamp = performance.now()
const isEnd = type === this.MARKER_TYPES.END
const storage = isEnd ? this.marks.end : this.marks.start
storage.set(name, {
name,
timestamp,
detail: options.detail
})
if (isEnd) {
const startMark = this.marks.start.get(name)
if (startMark) {
const measurement = {
name,
duration: timestamp - startMark.timestamp,
detail: options.detail
}
this.metrics.push(measurement)
}
}
}
}