0
# Exception Handling
1
2
Comprehensive exception hierarchy with specific error codes and handling patterns for robust error management in Nacos operations. Essential for building resilient applications with proper error handling and recovery mechanisms.
3
4
## Capabilities
5
6
### NacosException
7
8
Main exception class for all Nacos operations providing structured error information with specific error codes and detailed error messages.
9
10
```java { .api }
11
/**
12
* Main exception class for Nacos operations
13
*/
14
class NacosException extends Exception {
15
/** Error code for this exception */
16
private int errCode = SERVER_ERROR;
17
18
/** Error message */
19
private String errMsg;
20
21
/** Client error codes (negative values) */
22
public static final int CLIENT_INVALID_PARAM = -400;
23
public static final int CLIENT_OVER_THRESHOLD = -503;
24
public static final int CLIENT_DISCONNECT = -401;
25
public static final int CLIENT_INVALID_SERVER_STATUS = -402;
26
public static final int CLIENT_NOT_SUPPORT = -403;
27
28
/** Server error codes (positive values) */
29
public static final int INVALID_PARAM = 400;
30
public static final int NO_RIGHT = 403;
31
public static final int NOT_FOUND = 404;
32
public static final int CONFLICT = 409;
33
public static final int SERVER_ERROR = 500;
34
public static final int BAD_GATEWAY = 502;
35
public static final int OVER_THRESHOLD = 503;
36
public static final int ASYNC_TIMEOUT = 504;
37
38
/**
39
* Default constructor with generic server error
40
*/
41
public NacosException();
42
43
/**
44
* Constructor with error code and message
45
* @param errCode Specific error code
46
* @param errMsg Error message
47
*/
48
public NacosException(int errCode, String errMsg);
49
50
/**
51
* Constructor with error code and cause
52
* @param errCode Specific error code
53
* @param throwable Underlying cause
54
*/
55
public NacosException(int errCode, Throwable throwable);
56
57
/**
58
* Constructor with error code, message, and cause
59
* @param errCode Specific error code
60
* @param errMsg Error message
61
* @param throwable Underlying cause
62
*/
63
public NacosException(int errCode, String errMsg, Throwable throwable);
64
65
/**
66
* Get error code
67
* @return Error code
68
*/
69
public int getErrCode();
70
71
/**
72
* Set error code
73
* @param errCode Error code
74
*/
75
public void setErrCode(int errCode);
76
77
/**
78
* Get error message
79
* @return Error message
80
*/
81
public String getErrMsg();
82
83
/**
84
* Set error message
85
* @param errMsg Error message
86
*/
87
public void setErrMsg(String errMsg);
88
89
/**
90
* Check if error is client-side
91
* @return true if error code is negative (client error)
92
*/
93
public boolean isClientError();
94
95
/**
96
* Check if error is server-side
97
* @return true if error code is positive (server error)
98
*/
99
public boolean isServerError();
100
101
/**
102
* Get formatted error message including error code
103
*/
104
@Override
105
public String getMessage();
106
107
/**
108
* Convert to string representation
109
*/
110
@Override
111
public String toString();
112
}
113
```
114
115
### Runtime Exceptions
116
117
Runtime exception classes for situations that don't require explicit handling but provide specific error information.
118
119
```java { .api }
120
/**
121
* Runtime exception for Nacos operations that don't require explicit handling
122
*/
123
class NacosRuntimeException extends RuntimeException {
124
/** Error code */
125
private int errorCode;
126
127
/**
128
* Default constructor
129
*/
130
public NacosRuntimeException();
131
132
/**
133
* Constructor with message
134
* @param message Error message
135
*/
136
public NacosRuntimeException(String message);
137
138
/**
139
* Constructor with message and cause
140
* @param message Error message
141
* @param cause Underlying cause
142
*/
143
public NacosRuntimeException(String message, Throwable cause);
144
145
/**
146
* Constructor with cause
147
* @param cause Underlying cause
148
*/
149
public NacosRuntimeException(Throwable cause);
150
151
/**
152
* Constructor with error code and message
153
* @param errorCode Specific error code
154
* @param message Error message
155
*/
156
public NacosRuntimeException(int errorCode, String message);
157
158
/**
159
* Constructor with error code, message, and cause
160
* @param errorCode Specific error code
161
* @param message Error message
162
* @param cause Underlying cause
163
*/
164
public NacosRuntimeException(int errorCode, String message, Throwable cause);
165
166
/**
167
* Get error code
168
* @return Error code
169
*/
170
public int getErrorCode();
171
172
/**
173
* Set error code
174
* @param errorCode Error code
175
*/
176
public void setErrorCode(int errorCode);
177
}
178
179
/**
180
* API-specific exception for invalid API usage
181
*/
182
class NacosApiException extends NacosRuntimeException {
183
/**
184
* Constructor with message
185
* @param message Error message
186
*/
187
public NacosApiException(String message);
188
189
/**
190
* Constructor with message and cause
191
* @param message Error message
192
* @param cause Underlying cause
193
*/
194
public NacosApiException(String message, Throwable cause);
195
196
/**
197
* Constructor with error code and message
198
* @param errorCode Specific error code
199
* @param message Error message
200
*/
201
public NacosApiException(int errorCode, String message);
202
}
203
```
204
205
### Serialization Exceptions
206
207
Specialized exceptions for data serialization and deserialization operations.
208
209
```java { .api }
210
/**
211
* Exception for serialization errors
212
*/
213
class NacosSerializationException extends NacosRuntimeException {
214
/**
215
* Constructor with message
216
* @param message Error message
217
*/
218
public NacosSerializationException(String message);
219
220
/**
221
* Constructor with message and cause
222
* @param message Error message
223
* @param cause Underlying cause
224
*/
225
public NacosSerializationException(String message, Throwable cause);
226
227
/**
228
* Constructor with cause
229
* @param cause Underlying cause
230
*/
231
public NacosSerializationException(Throwable cause);
232
}
233
234
/**
235
* Exception for deserialization errors
236
*/
237
class NacosDeserializationException extends NacosRuntimeException {
238
/** Target class that failed to deserialize */
239
private final Class<?> targetClass;
240
241
/**
242
* Constructor with message
243
* @param message Error message
244
*/
245
public NacosDeserializationException(String message);
246
247
/**
248
* Constructor with message and cause
249
* @param message Error message
250
* @param cause Underlying cause
251
*/
252
public NacosDeserializationException(String message, Throwable cause);
253
254
/**
255
* Constructor with target class and cause
256
* @param targetClass Class that failed to deserialize
257
* @param cause Underlying cause
258
*/
259
public NacosDeserializationException(Class<?> targetClass, Throwable cause);
260
261
/**
262
* Constructor with message, target class, and cause
263
* @param message Error message
264
* @param targetClass Class that failed to deserialize
265
* @param cause Underlying cause
266
*/
267
public NacosDeserializationException(String message, Class<?> targetClass, Throwable cause);
268
269
/**
270
* Get target class that failed to deserialize
271
* @return Target class
272
*/
273
public Class<?> getTargetClass();
274
}
275
```
276
277
### Error Code Utilities
278
279
Utility classes for working with error codes and exception classification.
280
281
```java { .api }
282
/**
283
* Utility class for error code operations
284
*/
285
class ErrorCodeUtils {
286
/**
287
* Check if error code represents a client error
288
* @param errorCode Error code to check
289
* @return true if client error (negative)
290
*/
291
public static boolean isClientError(int errorCode);
292
293
/**
294
* Check if error code represents a server error
295
* @param errorCode Error code to check
296
* @return true if server error (positive)
297
*/
298
public static boolean isServerError(int errorCode);
299
300
/**
301
* Check if error code represents a timeout
302
* @param errorCode Error code to check
303
* @return true if timeout error
304
*/
305
public static boolean isTimeoutError(int errorCode);
306
307
/**
308
* Check if error code represents a parameter validation error
309
* @param errorCode Error code to check
310
* @return true if parameter error
311
*/
312
public static boolean isParameterError(int errorCode);
313
314
/**
315
* Check if error code represents an authentication/authorization error
316
* @param errorCode Error code to check
317
* @return true if auth error
318
*/
319
public static boolean isAuthError(int errorCode);
320
321
/**
322
* Get human-readable error type description
323
* @param errorCode Error code
324
* @return Error type description
325
*/
326
public static String getErrorTypeDescription(int errorCode);
327
328
/**
329
* Create NacosException from error code
330
* @param errorCode Error code
331
* @param message Error message
332
* @return New NacosException instance
333
*/
334
public static NacosException createException(int errorCode, String message);
335
336
/**
337
* Create NacosException from error code with cause
338
* @param errorCode Error code
339
* @param message Error message
340
* @param cause Underlying cause
341
* @return New NacosException instance
342
*/
343
public static NacosException createException(int errorCode, String message, Throwable cause);
344
}
345
346
/**
347
* Exception factory for creating common Nacos exceptions
348
*/
349
class NacosExceptionFactory {
350
/**
351
* Create invalid parameter exception
352
* @param paramName Parameter name that is invalid
353
* @param paramValue Parameter value that is invalid
354
* @return NacosException for invalid parameter
355
*/
356
public static NacosException invalidParameter(String paramName, Object paramValue);
357
358
/**
359
* Create service not found exception
360
* @param serviceName Service name that was not found
361
* @return NacosException for service not found
362
*/
363
public static NacosException serviceNotFound(String serviceName);
364
365
/**
366
* Create configuration not found exception
367
* @param dataId Configuration data ID
368
* @param group Configuration group
369
* @return NacosException for configuration not found
370
*/
371
public static NacosException configNotFound(String dataId, String group);
372
373
/**
374
* Create connection timeout exception
375
* @param timeoutMs Timeout in milliseconds
376
* @return NacosException for timeout
377
*/
378
public static NacosException connectionTimeout(long timeoutMs);
379
380
/**
381
* Create server unavailable exception
382
* @param serverAddr Server address that is unavailable
383
* @return NacosException for server unavailable
384
*/
385
public static NacosException serverUnavailable(String serverAddr);
386
387
/**
388
* Create permission denied exception
389
* @param resource Resource that access was denied to
390
* @param operation Operation that was denied
391
* @return NacosException for permission denied
392
*/
393
public static NacosException permissionDenied(String resource, String operation);
394
}
395
```
396
397
## Usage Examples
398
399
### Basic Exception Handling
400
401
```java
402
import com.alibaba.nacos.api.exception.NacosException;
403
import com.alibaba.nacos.api.config.ConfigService;
404
import com.alibaba.nacos.api.naming.NamingService;
405
406
public class BasicExceptionHandling {
407
408
// Configuration operations with exception handling
409
public String getConfigSafely(ConfigService configService, String dataId, String group) {
410
try {
411
return configService.getConfig(dataId, group, 5000);
412
413
} catch (NacosException e) {
414
System.err.printf("Failed to get config %s:%s - Error %d: %s%n",
415
group, dataId, e.getErrCode(), e.getErrMsg());
416
417
// Handle specific error cases
418
switch (e.getErrCode()) {
419
case NacosException.NOT_FOUND:
420
System.out.println("Configuration not found, using default values");
421
return getDefaultConfig(dataId);
422
423
case NacosException.ASYNC_TIMEOUT:
424
System.out.println("Request timed out, retrying with longer timeout");
425
return retryGetConfig(configService, dataId, group);
426
427
case NacosException.NO_RIGHT:
428
System.err.println("Permission denied, check authentication");
429
throw new RuntimeException("Authentication required", e);
430
431
case NacosException.SERVER_ERROR:
432
System.err.println("Server error, will retry later");
433
return getCachedConfig(dataId, group);
434
435
default:
436
System.err.println("Unexpected error occurred");
437
throw new RuntimeException("Configuration retrieval failed", e);
438
}
439
}
440
}
441
442
// Service registration with comprehensive error handling
443
public boolean registerServiceSafely(NamingService namingService, String serviceName,
444
String ip, int port) {
445
try {
446
namingService.registerInstance(serviceName, ip, port);
447
System.out.printf("Successfully registered %s at %s:%d%n", serviceName, ip, port);
448
return true;
449
450
} catch (NacosException e) {
451
System.err.printf("Failed to register service %s - Error %d: %s%n",
452
serviceName, e.getErrCode(), e.getErrMsg());
453
454
if (e.isClientError()) {
455
// Client-side errors (negative error codes)
456
handleClientError(e, serviceName, ip, port);
457
} else if (e.isServerError()) {
458
// Server-side errors (positive error codes)
459
handleServerError(e, serviceName, ip, port);
460
}
461
462
return false;
463
}
464
}
465
466
private void handleClientError(NacosException e, String serviceName, String ip, int port) {
467
switch (e.getErrCode()) {
468
case NacosException.CLIENT_INVALID_PARAM:
469
System.err.printf("Invalid parameters for service registration: %s at %s:%d%n",
470
serviceName, ip, port);
471
// Validate and fix parameters
472
break;
473
474
case NacosException.CLIENT_DISCONNECT:
475
System.err.println("Client disconnected from server, attempting reconnection");
476
// Trigger reconnection logic
477
break;
478
479
case NacosException.CLIENT_OVER_THRESHOLD:
480
System.err.println("Client request rate exceeded, backing off");
481
// Implement backoff strategy
482
break;
483
484
default:
485
System.err.println("Unknown client error: " + e.getErrMsg());
486
break;
487
}
488
}
489
490
private void handleServerError(NacosException e, String serviceName, String ip, int port) {
491
switch (e.getErrCode()) {
492
case NacosException.SERVER_ERROR:
493
System.err.println("Server internal error, will retry registration");
494
// Schedule retry
495
break;
496
497
case NacosException.OVER_THRESHOLD:
498
System.err.println("Server overloaded, backing off");
499
// Implement exponential backoff
500
break;
501
502
case NacosException.BAD_GATEWAY:
503
System.err.println("Bad gateway, checking server connectivity");
504
// Check network connectivity
505
break;
506
507
default:
508
System.err.println("Unknown server error: " + e.getErrMsg());
509
break;
510
}
511
}
512
}
513
```
514
515
### Exception Classification and Recovery
516
517
```java
518
import com.alibaba.nacos.api.exception.ErrorCodeUtils;
519
import com.alibaba.nacos.api.exception.NacosExceptionFactory;
520
521
public class ExceptionClassificationExample {
522
523
// Classify exceptions for different handling strategies
524
public void handleExceptionWithClassification(NacosException e, String operation) {
525
System.out.printf("Operation '%s' failed with error %d: %s%n",
526
operation, e.getErrCode(), e.getErrMsg());
527
528
// Classify error type
529
if (ErrorCodeUtils.isTimeoutError(e.getErrCode())) {
530
handleTimeoutError(e, operation);
531
} else if (ErrorCodeUtils.isParameterError(e.getErrCode())) {
532
handleParameterError(e, operation);
533
} else if (ErrorCodeUtils.isAuthError(e.getErrCode())) {
534
handleAuthError(e, operation);
535
} else if (ErrorCodeUtils.isClientError(e.getErrCode())) {
536
handleGenericClientError(e, operation);
537
} else if (ErrorCodeUtils.isServerError(e.getErrCode())) {
538
handleGenericServerError(e, operation);
539
} else {
540
handleUnknownError(e, operation);
541
}
542
}
543
544
private void handleTimeoutError(NacosException e, String operation) {
545
System.out.println("Timeout detected, implementing retry with backoff");
546
547
// Implement exponential backoff retry
548
RetryPolicy.builder()
549
.withMaxAttempts(3)
550
.withExponentialBackoff(1000, 5000)
551
.retry(() -> retryOperation(operation));
552
}
553
554
private void handleParameterError(NacosException e, String operation) {
555
System.err.println("Parameter validation failed:");
556
System.err.println(" Error: " + ErrorCodeUtils.getErrorTypeDescription(e.getErrCode()));
557
System.err.println(" Suggestion: Check input parameters and API documentation");
558
559
// Log parameter details for debugging
560
logParameterValidationFailure(operation, e);
561
}
562
563
private void handleAuthError(NacosException e, String operation) {
564
System.err.println("Authentication/Authorization failed:");
565
System.err.println(" Check credentials and permissions");
566
567
// Attempt to refresh authentication
568
if (refreshAuthentication()) {
569
System.out.println("Authentication refreshed, retrying operation");
570
retryOperation(operation);
571
} else {
572
System.err.println("Authentication refresh failed, manual intervention required");
573
alertAdministrator("Authentication failure for operation: " + operation);
574
}
575
}
576
577
private void handleGenericClientError(NacosException e, String operation) {
578
System.err.printf("Client error %d: %s%n", e.getErrCode(), e.getErrMsg());
579
580
// Log for debugging
581
logClientError(operation, e);
582
583
// Most client errors are not recoverable automatically
584
throw new RuntimeException("Client error in operation: " + operation, e);
585
}
586
587
private void handleGenericServerError(NacosException e, String operation) {
588
System.err.printf("Server error %d: %s%n", e.getErrCode(), e.getErrMsg());
589
590
// Server errors might be transient, implement retry
591
if (isRetriableServerError(e.getErrCode())) {
592
System.out.println("Retriable server error, scheduling retry");
593
scheduleRetry(operation, calculateBackoffDelay(e.getErrCode()));
594
} else {
595
System.err.println("Non-retriable server error, alerting administrators");
596
alertAdministrator("Server error in operation: " + operation + " - " + e.getErrMsg());
597
}
598
}
599
600
private void handleUnknownError(NacosException e, String operation) {
601
System.err.printf("Unknown error %d: %s%n", e.getErrCode(), e.getErrMsg());
602
603
// Log for investigation
604
logUnknownError(operation, e);
605
606
// Conservative approach - don't retry unknown errors
607
throw new RuntimeException("Unknown error in operation: " + operation, e);
608
}
609
}
610
```
611
612
### Custom Exception Handling Framework
613
614
```java
615
import java.util.concurrent.CompletableFuture;
616
import java.util.function.Supplier;
617
import java.util.function.Function;
618
619
public class NacosExceptionHandler {
620
621
// Generic exception handling wrapper
622
public static <T> CompletableFuture<T> handleAsync(Supplier<T> operation, String operationName) {
623
return CompletableFuture.supplyAsync(() -> {
624
try {
625
return operation.get();
626
} catch (NacosException e) {
627
throw new RuntimeException(createDetailedErrorMessage(e, operationName), e);
628
}
629
});
630
}
631
632
// Exception handling with retry policy
633
public static <T> T handleWithRetry(Supplier<T> operation, String operationName,
634
int maxRetries, long delayMs) throws NacosException {
635
NacosException lastException = null;
636
637
for (int attempt = 0; attempt <= maxRetries; attempt++) {
638
try {
639
return operation.get();
640
641
} catch (NacosException e) {
642
lastException = e;
643
644
// Don't retry on certain error types
645
if (!isRetriableError(e)) {
646
throw e;
647
}
648
649
if (attempt < maxRetries) {
650
System.out.printf("Attempt %d/%d failed for %s, retrying in %dms%n",
651
attempt + 1, maxRetries + 1, operationName, delayMs);
652
653
try {
654
Thread.sleep(delayMs * (attempt + 1)); // Linear backoff
655
} catch (InterruptedException ie) {
656
Thread.currentThread().interrupt();
657
throw new NacosException(NacosException.CLIENT_DISCONNECT,
658
"Operation interrupted", ie);
659
}
660
} else {
661
System.err.printf("All %d attempts failed for %s%n",
662
maxRetries + 1, operationName);
663
}
664
}
665
}
666
667
throw lastException;
668
}
669
670
// Exception handling with circuit breaker pattern
671
public static class CircuitBreakerExceptionHandler {
672
private final AtomicInteger failureCount = new AtomicInteger(0);
673
private volatile long lastFailureTime = 0;
674
private volatile boolean circuitOpen = false;
675
676
private final int failureThreshold;
677
private final long circuitOpenTimeMs;
678
679
public CircuitBreakerExceptionHandler(int failureThreshold, long circuitOpenTimeMs) {
680
this.failureThreshold = failureThreshold;
681
this.circuitOpenTimeMs = circuitOpenTimeMs;
682
}
683
684
public <T> T execute(Supplier<T> operation, String operationName) throws NacosException {
685
// Check if circuit is open
686
if (isCircuitOpen()) {
687
throw NacosExceptionFactory.serverUnavailable(
688
"Circuit breaker is open for operation: " + operationName);
689
}
690
691
try {
692
T result = operation.get();
693
694
// Success - reset circuit
695
resetCircuit();
696
return result;
697
698
} catch (NacosException e) {
699
// Record failure
700
recordFailure();
701
702
// Check if circuit should open
703
if (shouldOpenCircuit()) {
704
openCircuit();
705
System.err.printf("Circuit breaker opened for %s after %d failures%n",
706
operationName, failureCount.get());
707
}
708
709
throw e;
710
}
711
}
712
713
private boolean isCircuitOpen() {
714
if (circuitOpen) {
715
// Check if circuit should close (half-open state)
716
if (System.currentTimeMillis() - lastFailureTime > circuitOpenTimeMs) {
717
circuitOpen = false;
718
failureCount.set(0);
719
System.out.println("Circuit breaker half-open, allowing test request");
720
}
721
}
722
723
return circuitOpen;
724
}
725
726
private void recordFailure() {
727
failureCount.incrementAndGet();
728
lastFailureTime = System.currentTimeMillis();
729
}
730
731
private boolean shouldOpenCircuit() {
732
return failureCount.get() >= failureThreshold;
733
}
734
735
private void openCircuit() {
736
circuitOpen = true;
737
}
738
739
private void resetCircuit() {
740
failureCount.set(0);
741
circuitOpen = false;
742
lastFailureTime = 0;
743
}
744
}
745
746
// Utility methods
747
private static String createDetailedErrorMessage(NacosException e, String operationName) {
748
StringBuilder sb = new StringBuilder();
749
sb.append("Operation '").append(operationName).append("' failed");
750
sb.append(" [Error ").append(e.getErrCode()).append("]: ").append(e.getErrMsg());
751
752
if (e.getCause() != null) {
753
sb.append(" (Caused by: ").append(e.getCause().getMessage()).append(")");
754
}
755
756
return sb.toString();
757
}
758
759
private static boolean isRetriableError(NacosException e) {
760
// Define which errors are retriable
761
switch (e.getErrCode()) {
762
case NacosException.ASYNC_TIMEOUT:
763
case NacosException.SERVER_ERROR:
764
case NacosException.BAD_GATEWAY:
765
case NacosException.OVER_THRESHOLD:
766
case NacosException.CLIENT_DISCONNECT:
767
return true;
768
769
case NacosException.INVALID_PARAM:
770
case NacosException.NO_RIGHT:
771
case NacosException.NOT_FOUND:
772
case NacosException.CLIENT_INVALID_PARAM:
773
return false; // Don't retry validation or auth errors
774
775
default:
776
return false; // Conservative approach for unknown errors
777
}
778
}
779
}
780
```
781
782
### Exception Monitoring and Alerting
783
784
```java
785
import java.util.concurrent.ConcurrentHashMap;
786
import java.util.concurrent.atomic.LongAdder;
787
import java.time.LocalDateTime;
788
import java.time.format.DateTimeFormatter;
789
790
public class ExceptionMonitor {
791
792
private final Map<Integer, LongAdder> errorCounts = new ConcurrentHashMap<>();
793
private final Map<String, LongAdder> operationErrorCounts = new ConcurrentHashMap<>();
794
private final List<ExceptionRecord> recentExceptions = new CopyOnWriteArrayList<>();
795
796
// Record exception occurrence
797
public void recordException(NacosException e, String operation) {
798
// Count by error code
799
errorCounts.computeIfAbsent(e.getErrCode(), k -> new LongAdder()).increment();
800
801
// Count by operation
802
String key = operation + ":" + e.getErrCode();
803
operationErrorCounts.computeIfAbsent(key, k -> new LongAdder()).increment();
804
805
// Keep recent exceptions for analysis
806
ExceptionRecord record = new ExceptionRecord(e, operation, LocalDateTime.now());
807
recentExceptions.add(record);
808
809
// Keep only last 1000 exceptions
810
while (recentExceptions.size() > 1000) {
811
recentExceptions.remove(0);
812
}
813
814
// Check for alerting conditions
815
checkAlertConditions(e, operation);
816
}
817
818
// Generate exception statistics report
819
public String generateReport() {
820
StringBuilder report = new StringBuilder();
821
report.append("=== Nacos Exception Statistics ===\n");
822
report.append("Generated at: ").append(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)).append("\n\n");
823
824
// Error code statistics
825
report.append("Error Code Counts:\n");
826
errorCounts.entrySet().stream()
827
.sorted(Map.Entry.<Integer, LongAdder>comparingByValue((a, b) -> Long.compare(b.sum(), a.sum())))
828
.forEach(entry -> {
829
int errorCode = entry.getKey();
830
long count = entry.getValue().sum();
831
String errorType = ErrorCodeUtils.getErrorTypeDescription(errorCode);
832
report.append(String.format(" %d (%s): %d occurrences%n", errorCode, errorType, count));
833
});
834
835
report.append("\nOperation Error Counts:\n");
836
operationErrorCounts.entrySet().stream()
837
.sorted(Map.Entry.<String, LongAdder>comparingByValue((a, b) -> Long.compare(b.sum(), a.sum())))
838
.limit(10) // Top 10 operation errors
839
.forEach(entry -> {
840
String operation = entry.getKey();
841
long count = entry.getValue().sum();
842
report.append(String.format(" %s: %d occurrences%n", operation, count));
843
});
844
845
// Recent critical errors
846
report.append("\nRecent Critical Errors:\n");
847
recentExceptions.stream()
848
.filter(record -> isCriticalError(record.exception.getErrCode()))
849
.sorted((a, b) -> b.timestamp.compareTo(a.timestamp))
850
.limit(5)
851
.forEach(record -> {
852
report.append(String.format(" [%s] %s - Error %d: %s%n",
853
record.timestamp.format(DateTimeFormatter.ofPattern("MM-dd HH:mm:ss")),
854
record.operation,
855
record.exception.getErrCode(),
856
record.exception.getErrMsg()));
857
});
858
859
return report.toString();
860
}
861
862
// Check for conditions that require alerts
863
private void checkAlertConditions(NacosException e, String operation) {
864
// Alert on critical errors
865
if (isCriticalError(e.getErrCode())) {
866
sendAlert(String.format("Critical Nacos error in operation %s: [%d] %s",
867
operation, e.getErrCode(), e.getErrMsg()));
868
}
869
870
// Alert on high error rates
871
String operationKey = operation + ":" + e.getErrCode();
872
long count = operationErrorCounts.get(operationKey).sum();
873
if (count > 0 && count % 10 == 0) { // Every 10th occurrence
874
sendAlert(String.format("High error rate detected: %s has occurred %d times",
875
operationKey, count));
876
}
877
878
// Alert on authentication errors
879
if (ErrorCodeUtils.isAuthError(e.getErrCode())) {
880
sendAlert(String.format("Authentication error in operation %s: %s",
881
operation, e.getErrMsg()));
882
}
883
}
884
885
private boolean isCriticalError(int errorCode) {
886
return errorCode == NacosException.SERVER_ERROR ||
887
errorCode == NacosException.NO_RIGHT ||
888
errorCode == NacosException.CLIENT_DISCONNECT;
889
}
890
891
private void sendAlert(String message) {
892
System.err.println("ALERT: " + message);
893
// Integrate with alerting system (email, Slack, etc.)
894
}
895
896
// Exception record for tracking
897
private static class ExceptionRecord {
898
final NacosException exception;
899
final String operation;
900
final LocalDateTime timestamp;
901
902
ExceptionRecord(NacosException exception, String operation, LocalDateTime timestamp) {
903
this.exception = exception;
904
this.operation = operation;
905
this.timestamp = timestamp;
906
}
907
}
908
909
// Get error rate for specific operation
910
public double getErrorRate(String operation, Duration timeWindow) {
911
LocalDateTime cutoff = LocalDateTime.now().minus(timeWindow);
912
913
long totalOperations = recentExceptions.stream()
914
.filter(record -> record.operation.equals(operation))
915
.filter(record -> record.timestamp.isAfter(cutoff))
916
.count();
917
918
if (totalOperations == 0) {
919
return 0.0;
920
}
921
922
long errorOperations = recentExceptions.stream()
923
.filter(record -> record.operation.equals(operation))
924
.filter(record -> record.timestamp.isAfter(cutoff))
925
.filter(record -> record.exception != null)
926
.count();
927
928
return (double) errorOperations / totalOperations;
929
}
930
931
// Reset statistics
932
public void reset() {
933
errorCounts.clear();
934
operationErrorCounts.clear();
935
recentExceptions.clear();
936
}
937
}