123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- package nginx_log
- import (
- "fmt"
- "os"
- "github.com/0xJacky/Nginx-UI/internal/event"
- "github.com/0xJacky/Nginx-UI/internal/nginx"
- "github.com/0xJacky/Nginx-UI/internal/nginx_log/indexer"
- "github.com/uozi-tech/cosy/logger"
- )
- // FileInfo represents basic file information for internal use
- type FileInfo struct {
- Exists bool `json:"exists"`
- Readable bool `json:"readable"`
- Size int64 `json:"size,omitempty"`
- LastModified int64 `json:"last_modified,omitempty"`
- }
- // TimeRange represents a time range for log data for internal use
- type TimeRange struct {
- Start int64 `json:"start"`
- End int64 `json:"end"`
- }
- // PreflightResponse represents the response from preflight checks for internal use
- type PreflightResponse struct {
- Available bool `json:"available"`
- IndexStatus string `json:"index_status"`
- Message string `json:"message,omitempty"`
- TimeRange *TimeRange `json:"time_range,omitempty"`
- FileInfo *FileInfo `json:"file_info,omitempty"`
- }
- // PreflightService handles preflight checks for log files
- type PreflightService struct{}
- // NewPreflightService creates a new preflight service
- func NewPreflightService() *PreflightService {
- return &PreflightService{}
- }
- // CheckLogPreflight performs preflight checks for a log file
- func (ps *PreflightService) CheckLogPreflight(logPath string) (*PreflightResponse, error) {
- // Use default access log path if logPath is empty
- if logPath == "" {
- defaultLogPath := nginx.GetAccessLogPath()
- if defaultLogPath != "" {
- logPath = defaultLogPath
- logger.Debugf("Using default access log path for preflight: %s", logPath)
- }
- }
- // Get searcher to check index status
- searcherService := GetModernSearcher()
- if searcherService == nil {
- return nil, ErrModernSearcherNotAvailable
- }
- // Check if the specific file is currently being indexed
- processingManager := event.GetProcessingStatusManager()
- currentStatus := processingManager.GetCurrentStatus()
- // First check if the file exists and get file info
- var fileInfo *os.FileInfo
- if logPath != "" {
- if stat, err := os.Stat(logPath); os.IsNotExist(err) {
- // File doesn't exist - check for historical data
- return ps.handleMissingFile(logPath, searcherService)
- } else if err != nil {
- // Permission or other file system error - map to error status
- return &PreflightResponse{
- Available: false,
- IndexStatus: string(indexer.IndexStatusError),
- Message: fmt.Sprintf("Cannot access log file %s: %v", logPath, err),
- FileInfo: &FileInfo{
- Exists: true,
- Readable: false,
- },
- }, nil
- } else {
- fileInfo = &stat
- }
- }
- // Check if searcher is healthy
- searcherHealthy := searcherService.IsHealthy()
- // Get detailed file status from log file manager
- return ps.buildPreflightResponse(logPath, fileInfo, searcherHealthy, ¤tStatus)
- }
- // handleMissingFile handles the case when a log file doesn't exist
- func (ps *PreflightService) handleMissingFile(logPath string, searcherService interface{}) (*PreflightResponse, error) {
- searcherHealthy := searcherService.(interface{ IsHealthy() bool }).IsHealthy()
- logFileManager := GetLogFileManager()
- if logFileManager != nil {
- logGroup, err := logFileManager.GetLogByPath(logPath)
- if err == nil && logGroup != nil && logGroup.LastIndexed > 0 {
- // File has historical index data
- response := &PreflightResponse{
- Available: searcherHealthy,
- IndexStatus: string(indexer.IndexStatusIndexed),
- Message: "File indexed (historical data available)",
- FileInfo: &FileInfo{
- Exists: false,
- Readable: false,
- },
- }
- if logGroup.HasTimeRange {
- response.TimeRange = &TimeRange{
- Start: logGroup.TimeRangeStart,
- End: logGroup.TimeRangeEnd,
- }
- }
- return response, nil
- }
- }
- // File doesn't exist and no historical data
- return &PreflightResponse{
- Available: false,
- IndexStatus: string(indexer.IndexStatusNotIndexed),
- Message: "Log file does not exist",
- FileInfo: &FileInfo{
- Exists: false,
- Readable: false,
- },
- }, nil
- }
- // buildPreflightResponse builds the preflight response for existing files
- func (ps *PreflightService) buildPreflightResponse(logPath string, fileInfo *os.FileInfo, searcherHealthy bool, currentStatus *event.ProcessingStatusData) (*PreflightResponse, error) {
- logFileManager := GetLogFileManager()
- var indexStatus string = string(indexer.IndexStatusNotIndexed)
- var available bool = false
- response := &PreflightResponse{}
- if logFileManager != nil && logPath != "" {
- logGroup, err := logFileManager.GetLogByPath(logPath)
- if err == nil && logGroup != nil {
- // Determine status based on indexing state
- if logGroup.LastIndexed > 0 {
- indexStatus = string(indexer.IndexStatusIndexed)
- available = searcherHealthy
- } else if currentStatus.NginxLogIndexing {
- indexStatus = string(indexer.IndexStatusIndexing)
- available = false
- } else {
- indexStatus = string(indexer.IndexStatusNotIndexed)
- available = false
- }
- response.Available = available
- response.IndexStatus = indexStatus
- // Add time range if available
- if logGroup.HasTimeRange {
- response.TimeRange = &TimeRange{
- Start: logGroup.TimeRangeStart,
- End: logGroup.TimeRangeEnd,
- }
- }
- } else {
- // File not in database or error getting it
- if currentStatus.NginxLogIndexing {
- indexStatus = string(indexer.IndexStatusQueued)
- } else {
- indexStatus = string(indexer.IndexStatusNotIndexed)
- }
- available = false
- response.Available = available
- response.IndexStatus = indexStatus
- response.Message = "Log file not indexed yet"
- }
- } else {
- // Fallback to basic status
- response.Available = searcherHealthy
- response.IndexStatus = string(indexer.IndexStatusNotIndexed)
- }
- // Add file information if available
- if fileInfo != nil {
- response.FileInfo = &FileInfo{
- Exists: true,
- Readable: true,
- Size: (*fileInfo).Size(),
- LastModified: (*fileInfo).ModTime().Unix(),
- }
- }
- logger.Debugf("Preflight response: log_path=%s, available=%v, index_status=%s",
- logPath, response.Available, response.IndexStatus)
- return response, nil
- }
|