log.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
  2. *
  3. * Data Differential Utility library
  4. *
  5. * Copyright (C) 2012 Data Differential, http://datadifferential.com/
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are
  9. * met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * * Redistributions in binary form must reproduce the above
  15. * copyright notice, this list of conditions and the following disclaimer
  16. * in the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * * The names of its contributors may not be used to endorse or
  20. * promote products derived from this software without specific prior
  21. * written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  26. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  27. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  28. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  29. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  30. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  33. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. */
  36. #pragma once
  37. #include <cerrno>
  38. #include <cstdarg>
  39. #include <cstdio>
  40. #include <fcntl.h>
  41. #include <iostream>
  42. #include <string>
  43. #include <syslog.h>
  44. #define UTIL_MAX_ERROR_SIZE 2048
  45. namespace datadifferential {
  46. namespace util {
  47. /** Verbosity levels.
  48. */
  49. enum verbose_t
  50. {
  51. // Logging this will cause shutdown
  52. VERBOSE_FATAL= LOG_EMERG, // syslog:LOG_EMERG
  53. VERBOSE_ALERT= LOG_ALERT, // syslog:LOG_ALERT
  54. VERBOSE_CRITICAL= LOG_CRIT, // syslog:LOG_CRIT
  55. VERBOSE_ERROR= LOG_ERR, // syslog:LOG_ERR
  56. VERBOSE_WARN= LOG_WARNING, // syslog:LOG_WARNING
  57. VERBOSE_NOTICE= LOG_NOTICE, // syslog:LOG_NOTICE
  58. VERBOSE_INFO= LOG_INFO, // syslog:LOG_INFO
  59. VERBOSE_DEBUG= LOG_DEBUG // syslog:LOG_DEBUG
  60. };
  61. struct log_info_st
  62. {
  63. std::string name;
  64. std::string filename;
  65. int fd;
  66. bool opt_syslog;
  67. bool opt_file;
  68. bool init_success;
  69. log_info_st(const std::string& name_arg, const std::string &filename_arg, bool syslog_arg) :
  70. name(name_arg),
  71. filename(filename_arg),
  72. fd(-1),
  73. opt_syslog(syslog_arg),
  74. opt_file(false),
  75. init_success(false)
  76. {
  77. if (opt_syslog)
  78. {
  79. openlog(name.c_str(), LOG_PID | LOG_NDELAY, LOG_USER);
  80. }
  81. init();
  82. }
  83. void init()
  84. {
  85. if (filename.size())
  86. {
  87. if (filename.compare("stderr") == 0)
  88. {
  89. fd= STDERR_FILENO;
  90. }
  91. else
  92. {
  93. fd= open(filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0644);
  94. if (fd == -1)
  95. {
  96. if (opt_syslog)
  97. {
  98. char buffer[1024];
  99. char *getcwd_ret= getcwd(buffer, sizeof(buffer));
  100. syslog(LOG_ERR, "Could not open log file \"%.*s\", from \"%s\", open failed with (%s)",
  101. int(filename.size()), filename.c_str(),
  102. getcwd_ret,
  103. strerror(errno));
  104. }
  105. std::cerr << "Could not open log file for writing, switching to stderr." << std::endl;
  106. fd= STDERR_FILENO;
  107. }
  108. }
  109. opt_file= true;
  110. }
  111. init_success= true;
  112. }
  113. bool initialized() const
  114. {
  115. return init_success;
  116. }
  117. int file() const
  118. {
  119. return fd;
  120. }
  121. void write(verbose_t verbose, const char *format, ...)
  122. {
  123. if (opt_file or opt_syslog)
  124. {
  125. va_list args;
  126. va_start(args, format);
  127. char mesg[BUFSIZ];
  128. int mesg_length= vsnprintf(mesg, sizeof(mesg), format, args);
  129. va_end(args);
  130. if (opt_file)
  131. {
  132. char buffer[UTIL_MAX_ERROR_SIZE];
  133. int buffer_length= snprintf(buffer, sizeof(buffer), "%7s %.*s\n", verbose_name(verbose), mesg_length, mesg);
  134. if (::write(file(), buffer, buffer_length) == -1)
  135. {
  136. std::cerr << "Could not write to log file." << std::endl;
  137. syslog(LOG_EMERG, "gearmand could not open log file %s, got error %s", filename.c_str(), strerror(errno));
  138. }
  139. }
  140. if (opt_syslog)
  141. {
  142. syslog(int(verbose), "%7s %.*s", verbose_name(verbose), mesg_length, mesg);
  143. }
  144. }
  145. }
  146. ~log_info_st()
  147. {
  148. if (fd != -1 and fd != STDERR_FILENO)
  149. {
  150. close(fd);
  151. }
  152. if (opt_syslog)
  153. {
  154. closelog();
  155. }
  156. }
  157. private:
  158. const char *verbose_name(verbose_t verbose)
  159. {
  160. switch (verbose)
  161. {
  162. case VERBOSE_FATAL:
  163. return "FATAL";
  164. case VERBOSE_ALERT:
  165. return "ALERT";
  166. case VERBOSE_CRITICAL:
  167. return "CRITICAL";
  168. case VERBOSE_ERROR:
  169. return "ERROR";
  170. case VERBOSE_WARN:
  171. return "WARNING";
  172. case VERBOSE_NOTICE:
  173. return "NOTICE";
  174. case VERBOSE_INFO:
  175. return "INFO";
  176. case VERBOSE_DEBUG:
  177. return "DEBUG";
  178. default:
  179. break;
  180. }
  181. return "UNKNOWN";
  182. }
  183. };
  184. } // namespace util
  185. } // namespace datadifferential