0
# Message Handling
1
2
Comprehensive message and event system for progress reporting, error handling, and structured logging throughout the AutoRest generation process. The message system provides detailed feedback about processing stages, validation results, and any issues encountered.
3
4
## Capabilities
5
6
### Message Interface
7
8
Core message structure for all communication within AutoRest.
9
10
```typescript { .api }
11
/**
12
* Message structure for AutoRest communication
13
* Represents all types of messages generated during processing
14
*/
15
interface Message {
16
/** Message severity and type */
17
Channel: Channel;
18
19
/** Message text content */
20
Text: string;
21
22
/** Optional message key for categorization */
23
Key?: Iterable<string>;
24
25
/** Additional message details */
26
Details?: any;
27
28
/** Source locations where message originated */
29
Source?: Array<SourceLocation>;
30
31
/** Source ranges for precise location */
32
Range?: Iterable<Range>;
33
34
/** Plugin that generated the message */
35
Plugin?: string;
36
37
/** Pre-formatted message text */
38
FormattedMessage?: string;
39
}
40
```
41
42
### Channel Enumeration
43
44
Message severity and type classification system.
45
46
```typescript { .api }
47
/**
48
* Message channel enumeration
49
* Defines the severity and type of messages
50
*/
51
enum Channel {
52
/** Information is considered the mildest of responses; not necessarily actionable */
53
Information = "information",
54
55
/** Warnings are considered important for best practices, but not catastrophic */
56
Warning = "warning",
57
58
/** Errors are considered blocking issues that block successful operation */
59
Error = "error",
60
61
/** Debug messages are designed for developer communication of internal details */
62
Debug = "debug",
63
64
/** Verbose messages give the user additional clarity on the process */
65
Verbose = "verbose",
66
67
/** Catastrophic failure, likely abending the process */
68
Fatal = "fatal",
69
70
/** Hint messages offer guidance or support without forcing action */
71
Hint = "hint",
72
73
/** File represents a file output from an extension */
74
File = "file",
75
76
/** Configuration represents an update/creation of a configuration file */
77
Configuration = "configuration"
78
}
79
```
80
81
### Source Location Types
82
83
Precise location information for messages and errors.
84
85
```typescript { .api }
86
/**
87
* Source location information
88
* Identifies where in source documents messages originated
89
*/
90
interface SourceLocation {
91
/** Document URI where the location exists */
92
document: string;
93
94
/** Position within the document */
95
Position: EnhancedPosition;
96
}
97
98
/**
99
* Range information for multi-character spans
100
* Defines a range within a source document
101
*/
102
interface Range {
103
/** Document URI containing the range */
104
document: string;
105
106
/** Start position of the range */
107
start: Position;
108
109
/** End position of the range */
110
end: Position;
111
}
112
113
/**
114
* Position within a document
115
* Standard line/column position information
116
*/
117
interface Position {
118
/** Line number (0-based) */
119
line: number;
120
121
/** Column number (0-based) */
122
column: number;
123
}
124
125
/**
126
* Enhanced position with additional metadata
127
* Extends Position with source mapping information
128
*/
129
interface EnhancedPosition extends Position {
130
/** Additional position metadata */
131
[key: string]: any;
132
}
133
```
134
135
### Artifact Messages
136
137
Specialized message type for file generation events.
138
139
```typescript { .api }
140
/**
141
* Artifact message for file generation events
142
* Extends Message with artifact-specific details
143
*/
144
interface ArtifactMessage extends Message {
145
/** Artifact details including source map information */
146
Details: Artifact & {
147
/** Optional source map for generated content */
148
sourceMap?: Mappings | RawSourceMap
149
};
150
}
151
```
152
153
**Usage Examples:**
154
155
```typescript
156
import { AutoRest, Channel, Message } from "@microsoft.azure/autorest-core";
157
158
const autorest = new AutoRest();
159
160
// Subscribe to all messages
161
autorest.Message.Subscribe((source, message) => {
162
console.log(`[${message.Channel}] ${message.Text}`);
163
164
// Handle source location information
165
if (message.Source && message.Source.length > 0) {
166
message.Source.forEach(location => {
167
console.log(` at ${location.document}:${location.Position.line}:${location.Position.column}`);
168
});
169
}
170
171
// Handle additional details
172
if (message.Details) {
173
console.log(` Details: ${JSON.stringify(message.Details, null, 2)}`);
174
}
175
});
176
177
// Channel-specific handling
178
autorest.Message.Subscribe((_, message) => {
179
switch (message.Channel) {
180
case Channel.Fatal:
181
case Channel.Error:
182
console.error(`π¨ ERROR: ${message.Text}`);
183
if (message.Source) {
184
message.Source.forEach(loc => {
185
console.error(` at ${loc.document}:${loc.Position.line + 1}:${loc.Position.column + 1}`);
186
});
187
}
188
break;
189
190
case Channel.Warning:
191
console.warn(`β οΈ WARNING: ${message.Text}`);
192
break;
193
194
case Channel.Information:
195
console.info(`βΉοΈ INFO: ${message.Text}`);
196
break;
197
198
case Channel.Debug:
199
if (process.env.DEBUG) {
200
console.debug(`π DEBUG: ${message.Text}`);
201
}
202
break;
203
204
case Channel.Verbose:
205
if (process.env.VERBOSE) {
206
console.log(`π VERBOSE: ${message.Text}`);
207
}
208
break;
209
210
case Channel.Hint:
211
console.log(`π‘ HINT: ${message.Text}`);
212
break;
213
214
case Channel.File:
215
console.log(`π FILE: ${message.Text}`);
216
break;
217
218
case Channel.Configuration:
219
console.log(`βοΈ CONFIG: ${message.Text}`);
220
break;
221
}
222
});
223
```
224
225
### Message Filtering and Processing
226
227
```typescript
228
// Collect messages by type
229
const errors: Message[] = [];
230
const warnings: Message[] = [];
231
const infos: Message[] = [];
232
233
autorest.Message.Subscribe((_, message) => {
234
switch (message.Channel) {
235
case Channel.Error:
236
case Channel.Fatal:
237
errors.push(message);
238
break;
239
case Channel.Warning:
240
warnings.push(message);
241
break;
242
case Channel.Information:
243
case Channel.Verbose:
244
infos.push(message);
245
break;
246
}
247
});
248
249
// Process results after completion
250
autorest.Finished.Subscribe((_, result) => {
251
console.log(`\nProcessing completed with ${errors.length} errors, ${warnings.length} warnings`);
252
253
if (errors.length > 0) {
254
console.log("\nErrors:");
255
errors.forEach((error, index) => {
256
console.log(`${index + 1}. ${error.Text}`);
257
if (error.Source) {
258
error.Source.forEach(loc => {
259
console.log(` Location: ${loc.document}:${loc.Position.line + 1}:${loc.Position.column + 1}`);
260
});
261
}
262
});
263
}
264
265
if (warnings.length > 0) {
266
console.log("\nWarnings:");
267
warnings.forEach((warning, index) => {
268
console.log(`${index + 1}. ${warning.Text}`);
269
});
270
}
271
});
272
```
273
274
### Structured Logging
275
276
```typescript
277
// Create structured logger
278
class AutoRestLogger {
279
private errors: Message[] = [];
280
private warnings: Message[] = [];
281
private debug: Message[] = [];
282
283
constructor(autorest: AutoRest) {
284
autorest.Message.Subscribe((_, message) => {
285
this.handleMessage(message);
286
});
287
}
288
289
private handleMessage(message: Message): void {
290
// Store messages
291
switch (message.Channel) {
292
case Channel.Error:
293
case Channel.Fatal:
294
this.errors.push(message);
295
break;
296
case Channel.Warning:
297
this.warnings.push(message);
298
break;
299
case Channel.Debug:
300
this.debug.push(message);
301
break;
302
}
303
304
// Log to appropriate output
305
this.logMessage(message);
306
}
307
308
private logMessage(message: Message): void {
309
const timestamp = new Date().toISOString();
310
const logEntry = {
311
timestamp,
312
channel: message.Channel,
313
text: message.Text,
314
plugin: message.Plugin,
315
key: message.Key ? Array.from(message.Key) : undefined,
316
source: message.Source,
317
details: message.Details
318
};
319
320
// Output as JSON for structured logging
321
console.log(JSON.stringify(logEntry));
322
}
323
324
getErrors(): Message[] { return [...this.errors]; }
325
getWarnings(): Message[] { return [...this.warnings]; }
326
hasErrors(): boolean { return this.errors.length > 0; }
327
hasWarnings(): boolean { return this.warnings.length > 0; }
328
}
329
330
// Usage
331
const autorest = new AutoRest();
332
const logger = new AutoRestLogger(autorest);
333
334
const result = await autorest.Process().finish;
335
336
if (logger.hasErrors()) {
337
console.error("Processing failed with errors:");
338
logger.getErrors().forEach(error => {
339
console.error(`- ${error.Text}`);
340
});
341
process.exit(1);
342
}
343
344
if (logger.hasWarnings()) {
345
console.warn(`Processing completed with ${logger.getWarnings().length} warnings`);
346
}
347
```
348
349
### Message Analysis
350
351
```typescript
352
// Analyze messages for patterns
353
function analyzeMessages(messages: Message[]): void {
354
const byPlugin = new Map<string, Message[]>();
355
const byDocument = new Map<string, Message[]>();
356
357
messages.forEach(msg => {
358
// Group by plugin
359
if (msg.Plugin) {
360
if (!byPlugin.has(msg.Plugin)) {
361
byPlugin.set(msg.Plugin, []);
362
}
363
byPlugin.get(msg.Plugin)!.push(msg);
364
}
365
366
// Group by document
367
if (msg.Source) {
368
msg.Source.forEach(loc => {
369
if (!byDocument.has(loc.document)) {
370
byDocument.set(loc.document, []);
371
}
372
byDocument.get(loc.document)!.push(msg);
373
});
374
}
375
});
376
377
console.log("Messages by plugin:");
378
byPlugin.forEach((msgs, plugin) => {
379
console.log(` ${plugin}: ${msgs.length} messages`);
380
});
381
382
console.log("Messages by document:");
383
byDocument.forEach((msgs, doc) => {
384
console.log(` ${doc}: ${msgs.length} messages`);
385
});
386
}
387
```
388
389
### Custom Message Formatting
390
391
```typescript
392
// Custom message formatter
393
function formatMessage(message: Message): string {
394
let formatted = `[${message.Channel.toUpperCase()}]`;
395
396
if (message.Plugin) {
397
formatted += ` (${message.Plugin})`;
398
}
399
400
formatted += ` ${message.Text}`;
401
402
if (message.Source && message.Source.length > 0) {
403
const locations = message.Source.map(loc =>
404
`${loc.document}:${loc.Position.line + 1}:${loc.Position.column + 1}`
405
).join(', ');
406
formatted += `\n at ${locations}`;
407
}
408
409
if (message.Key) {
410
const keys = Array.from(message.Key).join('.');
411
formatted += `\n key: ${keys}`;
412
}
413
414
return formatted;
415
}
416
417
// Use custom formatter
418
autorest.Message.Subscribe((_, message) => {
419
console.log(formatMessage(message));
420
});
421
```