access.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package log
  2. import (
  3. "log"
  4. "os"
  5. )
  6. // AccessStatus is the status of an access request from clients.
  7. type AccessStatus string
  8. const (
  9. AccessAccepted = AccessStatus("accepted")
  10. AccessRejected = AccessStatus("rejected")
  11. )
  12. type accessLogger interface {
  13. Log(from, to string, status AccessStatus, reason string)
  14. }
  15. type noOpAccessLogger struct {
  16. }
  17. func (logger *noOpAccessLogger) Log(from, to string, status AccessStatus, reason string) {
  18. // Swallow
  19. }
  20. type accessLog struct {
  21. From string
  22. To string
  23. Status AccessStatus
  24. Reason string
  25. }
  26. type fileAccessLogger struct {
  27. queue chan *accessLog
  28. logger *log.Logger
  29. file *os.File
  30. }
  31. func (logger *fileAccessLogger) close() {
  32. logger.file.Close()
  33. }
  34. func (logger *fileAccessLogger) Log(from, to string, status AccessStatus, reason string) {
  35. select {
  36. case logger.queue <- &accessLog{
  37. From: from,
  38. To: to,
  39. Status: status,
  40. Reason: reason,
  41. }:
  42. default:
  43. // We don't expect this to happen, but don't want to block main thread as well.
  44. }
  45. }
  46. func (logger *fileAccessLogger) Run() {
  47. for entry := range logger.queue {
  48. logger.logger.Println(entry.From + " " + string(entry.Status) + " " + entry.To + " " + entry.Reason)
  49. }
  50. }
  51. func newFileAccessLogger(path string) accessLogger {
  52. file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
  53. if err != nil {
  54. log.Printf("Unable to create or open file (%s): %v\n", path, err)
  55. return nil
  56. }
  57. return &fileAccessLogger{
  58. queue: make(chan *accessLog, 16),
  59. logger: log.New(file, "", log.Ldate|log.Ltime),
  60. file: file,
  61. }
  62. }
  63. var accessLoggerInstance accessLogger = &noOpAccessLogger{}
  64. // InitAccessLogger initializes the access logger to write into the give file.
  65. func InitAccessLogger(file string) {
  66. logger := newFileAccessLogger(file)
  67. if logger != nil {
  68. go logger.(*fileAccessLogger).Run()
  69. accessLoggerInstance = logger
  70. }
  71. }
  72. // Access writes an access log.
  73. func Access(from, to string, status AccessStatus, reason string) {
  74. accessLoggerInstance.Log(from, to, status, reason)
  75. }