Files
Alexander Abakumov 15e744da49 Initial commit: Complete Software Architecture course with 11 modules
- Added comprehensive course structure with 11 modules
- Included theoretical content, practical examples, and tasks
- Multi-language code examples (Java, Rust, Node.js, Python)
- Detailed analysis of architectural approaches and trade-offs
- Complete caching strategies documentation
- Architecture examples from real-world systems (Twitter, Netflix, Uber)
- Structured navigation and learning path
- Ready for educational use
2025-09-09 22:08:07 +03:00

6.6 KiB

Логирование

Навигация


Принципы логирования

1. Structured Logging

Определение: Логирование в структурированном формате (JSON).

Технический пример - Advanced Structured Logging:

@Slf4j
@RestController
public class OrderController {
    
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private MetricsService metricsService;
    
    @PostMapping("/orders")
    public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
        String correlationId = MDC.get("correlationId");
        String userId = MDC.get("userId");
        
        // Structured logging with business context
        log.info("Order creation started", 
            StructuredLogging.builder()
                .correlationId(correlationId)
                .userId(userId)
                .customerId(request.getCustomerId())
                .orderValue(request.getTotalValue())
                .itemsCount(request.getItems().size())
                .currency(request.getCurrency())
                .paymentMethod(request.getPaymentMethod())
                .build()
        );
        
        Timer.Sample sample = Timer.start();
        
        try {
            Order order = orderService.createOrder(request);
            
            // Success logging with performance metrics
            Duration duration = Duration.ofNanos(sample.stop());
            log.info("Order created successfully", 
                StructuredLogging.builder()
                    .correlationId(correlationId)
                    .userId(userId)
                    .orderId(order.getId())
                    .customerId(request.getCustomerId())
                    .status(order.getStatus())
                    .processingTimeMs(duration.toMillis())
                    .build()
            );
            
            // Record business metrics
            metricsService.recordBusinessEvent("order_created", userId);
            metricsService.recordOrderValue(request.getTotalValue(), request.getCurrency());
            
            return ResponseEntity.ok(order);
            
        } catch (ValidationException e) {
            log.warn("Order validation failed", 
                StructuredLogging.builder()
                    .correlationId(correlationId)
                    .userId(userId)
                    .customerId(request.getCustomerId())
                    .errorType("validation_error")
                    .errorMessage(e.getMessage())
                    .validationErrors(e.getValidationErrors())
                    .build()
            );
            return ResponseEntity.badRequest().body(new ErrorResponse(e.getMessage()));
            
        } catch (PaymentException e) {
            log.error("Payment processing failed", 
                StructuredLogging.builder()
                    .correlationId(correlationId)
                    .userId(userId)
                    .customerId(request.getCustomerId())
                    .errorType("payment_error")
                    .errorMessage(e.getMessage())
                    .paymentMethod(request.getPaymentMethod())
                    .orderValue(request.getTotalValue())
                    .build()
            );
            return ResponseEntity.status(HttpStatus.PAYMENT_REQUIRED)
                .body(new ErrorResponse("Payment processing failed"));
                
        } catch (Exception e) {
            log.error("Unexpected error during order creation", 
                StructuredLogging.builder()
                    .correlationId(correlationId)
                    .userId(userId)
                    .customerId(request.getCustomerId())
                    .errorType("system_error")
                    .errorMessage(e.getMessage())
                    .stackTrace(getStackTrace(e))
                    .build()
            );
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ErrorResponse("Internal server error"));
        }
    }
}

2. Log Levels

  • ERROR — критические ошибки
  • WARN — предупреждения
  • INFO — информационные сообщения
  • DEBUG — отладочная информация
  • TRACE — детальная трассировка

3. Correlation ID

@Component
public class CorrelationIdFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                        FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String correlationId = httpRequest.getHeader("X-Correlation-ID");
        
        if (correlationId == null) {
            correlationId = UUID.randomUUID().toString();
        }
        
        MDC.put("correlationId", correlationId);
        
        try {
            chain.doFilter(request, response);
        } finally {
            MDC.clear();
        }
    }
}

ELK Stack (Elasticsearch, Logstash, Kibana)

Конфигурация Logstash

# logstash.conf
input {
  beats {
    port => 5044
  }
}

filter {
  if [fields][service] == "order-service" {
    grok {
      match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}" }
    }
    
    date {
      match => [ "timestamp", "ISO8601" ]
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "logs-%{+YYYY.MM.dd}"
  }
}

Шаблон индекса Elasticsearch

{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 1
    },
    "mappings": {
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "level": {
          "type": "keyword"
        },
        "message": {
          "type": "text"
        },
        "correlationId": {
          "type": "keyword"
        },
        "service": {
          "type": "keyword"
        }
      }
    }
  }
}

Fluentd

# fluent.conf
<source>
  @type tail
  path /var/log/application.log
  pos_file /var/log/fluentd.log.pos
  tag application.logs
  format json
</source>

<filter application.logs>
  @type record_transformer
  <record>
    service "order-service"
    environment "production"
  </record>
</filter>

<match application.logs>
  @type elasticsearch
  host elasticsearch
  port 9200
  index_name logs
  type_name _doc
</match>