| 74 | ) |
| 75 | |
| 76 | func NewFileAccessLogger(parent task.Parent, file File, anyCfg AnyConfig) AccessLogger { |
| 77 | cfg := anyCfg.ToConfig() |
| 78 | if cfg.RotateInterval == 0 { |
| 79 | cfg.RotateInterval = defaultRotateInterval |
| 80 | } |
| 81 | |
| 82 | name := file.Name() |
| 83 | l := &fileAccessLogger{ |
| 84 | task: parent.Subtask("accesslog."+name, true), |
| 85 | cfg: cfg, |
| 86 | bufSize: InitialBufferSize, |
| 87 | errRateLimiter: rate.NewLimiter(rate.Every(errRateLimit), errBurst), |
| 88 | logger: log.With().Str("file", name).Logger(), |
| 89 | } |
| 90 | |
| 91 | l.writeLock, _ = writerLocks.LoadOrStore(name, &sync.Mutex{}) |
| 92 | |
| 93 | l.writer = ioutils.NewBufferedWriter(file, InitialBufferSize) |
| 94 | l.file = file |
| 95 | if _, ok := file.(activeLogRotater); ok { |
| 96 | registerFileLogger(name, l) |
| 97 | } |
| 98 | |
| 99 | if cfg.req != nil { |
| 100 | switch cfg.req.Format { |
| 101 | case FormatCommon: |
| 102 | l.RequestFormatter = CommonFormatter{cfg: &cfg.req.Fields} |
| 103 | case FormatCombined: |
| 104 | l.RequestFormatter = CombinedFormatter{CommonFormatter{cfg: &cfg.req.Fields}} |
| 105 | case FormatJSON: |
| 106 | l.RequestFormatter = JSONFormatter{cfg: &cfg.req.Fields} |
| 107 | default: // should not happen, validation has done by validate tags |
| 108 | panic("invalid access log format") |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | go l.start() |
| 113 | return l |
| 114 | } |
| 115 | |
| 116 | func (l *fileAccessLogger) Config() *Config { |
| 117 | return l.cfg |