forked from wikimedia/mediawiki-php-excimer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
excimer_log.h
215 lines (183 loc) · 5.28 KB
/
excimer_log.h
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/* Copyright 2018 Wikimedia Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EXCIMER_LOG_H
#define EXCIMER_LOG_H
/**
* Structure representing a unique location in the code and its backtrace
*/
typedef struct _excimer_log_frame {
/** The filename, or may be fake e.g. "php shell code" */
zend_string *filename;
/** The executing line number within the filename */
uint32_t lineno;
/**
* If the function was a closure, the "start line" of its definition.
* Zero if the function was not a closure.
*/
uint32_t closure_line;
/** The class name, or NULL if there was no class name. */
zend_string *class_name;
/**
* The function name, or NULL if there was no function name, or a
* fake thing like "eval()'d code".
*/
zend_string *function_name;
/**
* The index within excimer_log.frames of the calling frame.
*/
uint32_t prev_index;
} excimer_log_frame;
/**
* Structure representing a log entry
*/
typedef struct _excimer_log_entry {
/**
* The index within excimer_log.frames of the frame associated with this event.
*/
uint32_t frame_index;
/**
* The number of times the timer elapsed before the log entry was finally registered.
*/
zend_long event_count;
/**
* The wall clock time at which the event occurred. The interpretation is
* caller-defined, but in Excimer it is the number of nanoseconds since boot.
*/
uint64_t timestamp;
} excimer_log_entry;
/**
* Structure representing the entire log
*/
typedef struct _excimer_log {
/** Array of log entries */
excimer_log_entry *entries;
/** Size of the "entries" array */
size_t entries_size;
/** Array of frames */
excimer_log_frame *frames;
/* Size of the "frames" array */
size_t frames_size;
/**
* A hashtable where the key is a unique frame identifier combining some
* elements of the frame object, and the value is the frame index. Used
* for deduplication of frames.
*/
HashTable *reverse_frames;
/**
* The maximum stack depth of collected frames. If this is exceeded, the
* backtrace is truncated.
*/
zend_long max_depth;
/**
* This is used by ExcimerProfiler to store the creation time of the
* ExcimerProfiler object.
*/
uint64_t epoch;
/**
* The nominal period in nanoseconds
*/
uint64_t period;
/**
* The sum of the event counts of all contained log entries
*/
zend_long event_count;
} excimer_log;
/**
* Initialise the log object.
*
* @param log Valid memory location at which to place the object
*/
void excimer_log_init(excimer_log *log);
/**
* Destroy the log object. This frees internal objects but does not free the
* excimer_log itself.
*
* @param log The log object to destroy
*/
void excimer_log_destroy(excimer_log *log);
/**
* Set the max depth
*
* @param log The log object
* @param depth The new depth
*/
void excimer_log_set_max_depth(excimer_log *log, zend_long depth);
/**
* Copy persistent options to another log. This is used during log rotation.
*
* @param dest The destination log object
* @param src The source log object
*/
void excimer_log_copy_options(excimer_log *dest, excimer_log *src);
/**
* Add a log entry
*
* @param log The log object
* @param execute_data The VM state
* @param event_count The number of times the timer expired
* @param timestamp The timestamp to store in the log entry
*/
void excimer_log_add(excimer_log *log, zend_execute_data *execute_data,
zend_long event_count, uint64_t timestamp);
/**
* Get the number of entries in the log
*
* @param log The log object
* @return The number of entries in the log
*/
zend_long excimer_log_get_size(excimer_log *log);
/**
* Get a log entry
*
* @param log The log object
* @param i The index of the entry
* @return The log entry, or NULL if the index is out of range
*/
excimer_log_entry *excimer_log_get_entry(excimer_log *log, zend_long i);
/**
* Get a frame by index
*
* @param log The log object
* @param i The index
* @return The frame, or NULL if the index is out of range
*/
excimer_log_frame *excimer_log_get_frame(excimer_log *log, zend_long i);
/**
* Format the log in flamegraph.pl collapsed format
*
* @param log The log object
* @return A new zend_string owned by the caller
*/
zend_string *excimer_log_format_collapsed(excimer_log *log);
/**
* Get an array in speedscope format
*
* @param log The log object
* @param zp_data The destination
*/
void excimer_log_get_speedscope_data(excimer_log *log, zval *zp_data);
/**
* Aggregate the log producing self/inclusive statistics as an array
*/
HashTable *excimer_log_aggr_by_func(excimer_log *log);
/**
* Convert a frame to a backtrace array for returning to the user
*
* @param log The log object
* @param l_frame_index The frame index
* @return A new hashtable, owned by the caller
*/
HashTable *excimer_log_trace_to_array(excimer_log *log, zend_long l_frame_index);
#endif