0
# Segments & Timing
1
2
Create custom timing segments for specific operations and code blocks within transactions.
3
4
## Capabilities
5
6
### Start Segment
7
8
Wrap a function in a segment to track its execution time and optionally record it as a metric.
9
10
```javascript { .api }
11
/**
12
* Wraps a function in a segment for custom timing. Must be called within an active transaction.
13
* @param {string} name - The name for the segment and optional metric
14
* @param {boolean} record - Whether to record the segment as a metric
15
* @param {Function} handler - The function to track as a segment
16
* @param {Function} [callback] - Optional callback for async operations
17
* @returns {*} The return value of the handler function
18
*/
19
function startSegment(name, record, handler, callback);
20
```
21
22
**Usage Examples:**
23
24
```javascript
25
const newrelic = require('newrelic');
26
27
// Simple synchronous segment
28
function processData(data) {
29
return newrelic.startSegment('DataProcessing', true, () => {
30
// This work will be timed and recorded as a metric
31
return performExpensiveCalculation(data);
32
});
33
}
34
35
// Asynchronous segment with callback
36
function fetchUserData(userId, callback) {
37
newrelic.startSegment('FetchUser', true, (cb) => {
38
database.getUser(userId, cb);
39
}, callback);
40
}
41
42
// Asynchronous segment with promises
43
async function processOrder(orderId) {
44
return newrelic.startSegment('OrderProcessing', true, async () => {
45
const order = await database.getOrder(orderId);
46
const processed = await processPayment(order);
47
await updateInventory(order.items);
48
return processed;
49
});
50
}
51
52
// Segment without metric recording (for tracing only)
53
function validateInput(input) {
54
return newrelic.startSegment('InputValidation', false, () => {
55
return validator.validate(input);
56
});
57
}
58
```
59
60
## Segment Behavior
61
62
### Recording vs. Non-Recording Segments
63
64
- **Recording segments** (`record: true`): Create metrics that appear in transaction breakdown and server breakdown graphs
65
- **Non-recording segments** (`record: false`): Only appear in transaction traces for detailed timing information
66
67
### Automatic Timing
68
69
Segments automatically:
70
- Start timing when the handler function begins execution
71
- End timing when the handler function completes
72
- Handle both synchronous and asynchronous operations
73
- Preserve return values and thrown exceptions
74
75
### Context Requirements
76
77
- Must be called within an active transaction
78
- If called outside a transaction, the handler executes normally but no segment is created
79
- Warning is logged when called outside transaction context
80
81
## Common Usage Patterns
82
83
### Database Operation Timing
84
85
```javascript
86
async function getUserWithProfile(userId) {
87
const user = await newrelic.startSegment('Database/GetUser', true, async () => {
88
return await database.users.findById(userId);
89
});
90
91
const profile = await newrelic.startSegment('Database/GetProfile', true, async () => {
92
return await database.profiles.findByUserId(userId);
93
});
94
95
return { user, profile };
96
}
97
```
98
99
### External Service Calls
100
101
```javascript
102
async function callPaymentService(paymentData) {
103
return newrelic.startSegment('External/PaymentService', true, async () => {
104
const response = await httpClient.post('/api/payments', paymentData);
105
return response.data;
106
});
107
}
108
109
async function callMultipleServices(data) {
110
const [userService, orderService, notificationService] = await Promise.all([
111
newrelic.startSegment('External/UserService', true, () =>
112
userServiceClient.updateUser(data.user)
113
),
114
newrelic.startSegment('External/OrderService', true, () =>
115
orderServiceClient.createOrder(data.order)
116
),
117
newrelic.startSegment('External/NotificationService', true, () =>
118
notificationClient.sendEmail(data.notification)
119
)
120
]);
121
122
return { userService, orderService, notificationService };
123
}
124
```
125
126
### Complex Business Logic Timing
127
128
```javascript
129
async function processComplexWorkflow(workflowData) {
130
// Validate input (trace only, no metric)
131
const validatedData = newrelic.startSegment('Workflow/Validation', false, () => {
132
return validateWorkflowData(workflowData);
133
});
134
135
// Initialize workflow (recorded as metric)
136
const workflow = await newrelic.startSegment('Workflow/Initialize', true, async () => {
137
return await initializeWorkflow(validatedData);
138
});
139
140
// Execute each step with timing
141
const results = [];
142
for (let i = 0; i < workflow.steps.length; i++) {
143
const step = workflow.steps[i];
144
const result = await newrelic.startSegment(`Workflow/Step${i + 1}`, true, async () => {
145
return await executeWorkflowStep(step, results);
146
});
147
results.push(result);
148
}
149
150
// Finalize workflow
151
return newrelic.startSegment('Workflow/Finalize', true, async () => {
152
return await finalizeWorkflow(workflow, results);
153
});
154
}
155
```
156
157
### Cache Operations
158
159
```javascript
160
async function getCachedData(key) {
161
// Check cache (trace timing but don't record as metric)
162
let data = newrelic.startSegment('Cache/Get', false, () => {
163
return cache.get(key);
164
});
165
166
if (!data) {
167
// Cache miss - fetch from database (record as metric)
168
data = await newrelic.startSegment('Database/FetchForCache', true, async () => {
169
return await database.getData(key);
170
});
171
172
// Store in cache (trace only)
173
newrelic.startSegment('Cache/Set', false, () => {
174
cache.set(key, data, 3600); // 1 hour TTL
175
});
176
}
177
178
return data;
179
}
180
```
181
182
### File System Operations
183
184
```javascript
185
const fs = require('fs').promises;
186
187
async function processFile(filePath) {
188
// Read file with timing
189
const content = await newrelic.startSegment('FileSystem/Read', true, async () => {
190
return await fs.readFile(filePath, 'utf8');
191
});
192
193
// Process content
194
const processed = newrelic.startSegment('FileProcessing/Parse', true, () => {
195
return parseFileContent(content);
196
});
197
198
// Transform data
199
const transformed = newrelic.startSegment('FileProcessing/Transform', true, () => {
200
return transformData(processed);
201
});
202
203
// Write result
204
await newrelic.startSegment('FileSystem/Write', true, async () => {
205
const outputPath = filePath.replace('.input', '.output');
206
return await fs.writeFile(outputPath, JSON.stringify(transformed));
207
});
208
209
return transformed;
210
}
211
```
212
213
### CPU-Intensive Operations
214
215
```javascript
216
function performAnalytics(dataset) {
217
// Data preparation
218
const prepared = newrelic.startSegment('Analytics/DataPrep', true, () => {
219
return dataset.map(item => normalizeData(item));
220
});
221
222
// Statistical calculations
223
const stats = newrelic.startSegment('Analytics/Statistics', true, () => {
224
return {
225
mean: calculateMean(prepared),
226
median: calculateMedian(prepared),
227
standardDeviation: calculateStdDev(prepared)
228
};
229
});
230
231
// Generate report
232
const report = newrelic.startSegment('Analytics/ReportGeneration', true, () => {
233
return generateAnalyticsReport(prepared, stats);
234
});
235
236
return report;
237
}
238
```
239
240
### Error Handling in Segments
241
242
```javascript
243
async function robustOperation(data) {
244
try {
245
return await newrelic.startSegment('RobustOperation/Execute', true, async () => {
246
const validated = validateData(data);
247
const processed = await processData(validated);
248
return processed;
249
});
250
} catch (error) {
251
// Errors are automatically captured by the segment
252
// Add additional context if needed
253
newrelic.addCustomAttribute('operationFailed', true);
254
newrelic.noticeError(error, {
255
operation: 'RobustOperation',
256
dataSize: data?.length || 0
257
});
258
throw error;
259
}
260
}
261
```
262
263
### Nested Segments
264
265
```javascript
266
async function nestedOperations(data) {
267
return newrelic.startSegment('MainOperation', true, async () => {
268
269
// Level 1 nested segment
270
const prepared = await newrelic.startSegment('MainOperation/Preparation', true, async () => {
271
272
// Level 2 nested segments
273
const cleaned = newrelic.startSegment('Preparation/DataCleaning', false, () => {
274
return cleanData(data);
275
});
276
277
const validated = newrelic.startSegment('Preparation/Validation', false, () => {
278
return validateData(cleaned);
279
});
280
281
return { cleaned, validated };
282
});
283
284
// Another level 1 segment
285
const result = await newrelic.startSegment('MainOperation/Processing', true, async () => {
286
return await processData(prepared.validated);
287
});
288
289
return result;
290
});
291
}
292
```
293
294
### Conditional Segment Recording
295
296
```javascript
297
function adaptiveSegmentRecording(data, options = {}) {
298
const shouldRecord = options.recordMetrics !== false;
299
const segmentName = options.segmentName || 'AdaptiveOperation';
300
301
return newrelic.startSegment(segmentName, shouldRecord, () => {
302
if (data.length > 1000) {
303
// For large datasets, add sub-segments
304
return newrelic.startSegment(`${segmentName}/LargeDataset`, shouldRecord, () => {
305
return processLargeDataset(data);
306
});
307
} else {
308
return processSmallDataset(data);
309
}
310
});
311
}
312
```