source: nscp/modules/FileLogger/FileLogger.cpp @ 8013c0c

0.4.00.4.10.4.2
Last change on this file since 8013c0c was 8013c0c, checked in by Michael Medin <michael@…>, 17 months ago
  • Fixed so NSCAClient parses address correctly
  • settings exception is now derived from exception meaning it will show up more with details (instead of unknown)
  • Added API for handling log level (replaces older debug flag)
  • Added options for settings debug level
  • Changed to --settings is a global argument (meaning you can use it in any mode)
  • Added arguments parsing to test: so you can use global arguments such as --log and --settings.
  • Removed memory leak in settings parsing interface
  • Property mode set to 100644
File size: 8.7 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21
22//#include <config.h>
23
24#include <string>
25#include <iostream>
26#include <fstream>
27
28#include <boost/date_time.hpp>
29
30#include "FileLogger.h"
31
32#include <utils.h>
33
34#include <settings/client/settings_client.hpp>
35#include <settings/macros.h>
36
37namespace sh = nscapi::settings_helper;
38
39FileLogger::FileLogger() : init_(false) {
40}
41FileLogger::~FileLogger() {
42}
43namespace setting_keys {
44
45        namespace log {
46                DEFINE_PATH(SECTION, LOG_SECTION);
47                //DESCRIBE_SETTING_ADVANCED(SECTION, "LOG SECTION", "Configure loggning properties.");
48
49                DEFINE_SETTING_S(FILENAME, LOG_SECTION, "file", "nsclient.log");
50                //DESCRIBE_SETTING_ADVANCED(FILENAME, "SYNTAX", "The file to write log data to. If no directory is used this is relative to the NSClient++ binary.");
51
52                DEFINE_SETTING_S(ROOT, LOG_SECTION, "root", "auto");
53                //DESCRIBE_SETTING_ADVANCED(ROOT, "TODO", "TODO");
54
55                DEFINE_SETTING_S(DATEMASK, LOG_SECTION, "date format", "%Y-%m-%d %H:%M:%S");
56                //DESCRIBE_SETTING_ADVANCED(DATEMASK, "DATEMASK", "The date format used when logging to a file.");
57
58                DEFINE_SETTING_S(LOG_MASK, LOG_SECTION, "log mask", "normal");
59                //DESCRIBE_SETTING_ADVANCED(LOG_MASK, "LOG MASK", "The log mask information, error, warning, critical, debug");
60
61                DEFINE_SETTING_B(DEBUG_LOG, LOG_SECTION, "debug", false);
62                //DESCRIBE_SETTING_ADVANCED(DEBUG_LOG, "DEBUG LOGGING", "Enable debug logging can help track down errors and find problems but will impact overall perfoamnce negativly.");
63        }
64}
65
66#ifdef WIN32
67#ifndef CSIDL_COMMON_APPDATA
68#define CSIDL_COMMON_APPDATA 0x0023
69#endif
70typedef BOOL (WINAPI *fnSHGetSpecialFolderPath)(HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate);
71
72__inline BOOL WINAPI _SHGetSpecialFolderPath(HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate) {
73        static fnSHGetSpecialFolderPath __SHGetSpecialFolderPath = NULL;
74        if (!__SHGetSpecialFolderPath) {
75                HMODULE hDLL = LoadLibrary(_T("shfolder.dll"));
76                if (hDLL != NULL)
77                        __SHGetSpecialFolderPath = (fnSHGetSpecialFolderPath)GetProcAddress(hDLL,"SHGetSpecialFolderPathW");
78        }
79        if(__SHGetSpecialFolderPath)
80                return __SHGetSpecialFolderPath(hwndOwner, lpszPath, nFolder, fCreate);
81        return FALSE;
82}
83#endif
84
85std::wstring getFolder(std::wstring key) {
86        if (key == _T("exe")) {
87                return GET_CORE()->getBasePath();
88        } else {
89#ifdef WIN32
90                if (key == _T("local-app-data")) {
91                        wchar_t buf[MAX_PATH+1];
92                        _SHGetSpecialFolderPath(NULL, buf, CSIDL_COMMON_APPDATA, FALSE);
93                        return buf;
94                }
95#endif
96        }
97        return GET_CORE()->getBasePath();
98}
99std::string FileLogger::getFileName() {
100        if (file_.empty()) {
101                file_ = utf8::cvt<std::string>(cfg_file_);
102                if (file_.empty())
103                        file_ = utf8::cvt<std::string>(setting_keys::log::FILENAME_DEFAULT);
104                if (file_.find("\\") == std::wstring::npos) {
105                        std::string root = utf8::cvt<std::string>(getFolder(cfg_root_));
106                        std::string::size_type pos = root.find_last_not_of('\\');
107                        if (pos != std::wstring::npos) {
108                                //root = root.substr(0, pos);
109                        }
110                        file_ = root + "\\" + file_;
111                }
112        }
113        return file_;
114}
115
116bool FileLogger::loadModule() {
117        return false;
118}
119bool FileLogger::loadModuleEx(std::wstring alias, NSCAPI::moduleLoadMode mode) {
120        //_tzset();
121        try {
122                std::wstring log_mask, file, root;
123
124                sh::settings_registry settings(get_settings_proxy());
125                settings.set_alias(_T("log"), alias);
126
127                settings.alias().add_path_to_settings()
128                        (_T("LOG SECTION"), _T("Configure loggning properties."))
129                        ;
130
131                settings.alias().add_key_to_settings()
132                        //(_T("debug"), sh::bool_key(&debug_, false),
133                        //_T("DEBUG LOGGING"), _T("Enable debug logging can help track down errors and find problems but will impact overall performance negativly."))
134
135                        (_T("log mask"), sh::wstring_key(&log_mask, _T("false")),
136                        _T("LOG MASK"), _T("The log mask information, error, warning, critical, debug"))
137
138                        (_T("root"), sh::wstring_key(&cfg_root_, _T("auto")),
139                        _T("ROOT"), _T("Set this to use a specific syntax string for all commands (that don't specify one)."))
140
141                        (_T("file name"), sh::wstring_key(&cfg_file_),
142                        _T("FILENAME"), _T("The file to write log data to. If no directory is used this is relative to the NSClient++ binary."))
143
144                        (_T("date format"), sh::string_key(&format_, "%Y-%m-%d %H:%M:%S"),
145                        _T("DATEMASK"), _T("The size of the buffer to use when getting messages this affects the speed and maximum size of messages you can recieve."))
146                        ;
147
148                settings.register_all();
149                settings.notify();
150
151                log_mask_ = nscapi::logging::parse(log_mask);
152
153                getFileName();
154
155        } catch (nscapi::nscapi_exception &e) {
156                NSC_LOG_ERROR_STD(_T("Failed to register command: ") + utf8::cvt<std::wstring>(e.what()));
157                return false;
158        } catch (std::exception &e) {
159                NSC_LOG_ERROR_STD(_T("Exception caught: ") + utf8::cvt<std::wstring>(e.what()));
160                return false;
161        } catch (...) {
162                NSC_LOG_ERROR_STD(_T("Failed to register command."));
163                return false;
164        }
165        NSC_LOG_MESSAGE_STD(_T("Using logmask: ") + nscapi::logging::to_string(log_mask_));
166        init_ = true;
167        std::string hello = "Starting to log for: " + utf8::cvt<std::string>(GET_CORE()->getApplicationName()) + " - " + utf8::cvt<std::string>(GET_CORE()->getApplicationVersionString());
168        handleMessage(NSCAPI::log_level::log, __FILE__, __LINE__, hello);
169        handleMessage(NSCAPI::log_level::log, __FILE__, __LINE__, "Log path is: " + file_);
170        return true;
171}
172bool FileLogger::unloadModule() {
173        return true;
174}
175bool FileLogger::hasCommandHandler() {
176        return false;
177}
178bool FileLogger::hasMessageHandler() {
179        return true;
180}
181/*
182HANDLE openAppendOrNew(std::wstring file) {
183        DWORD numberOfBytesWritten = 0;
184        HANDLE hFile = ::CreateFile(file.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
185        if (hFile == INVALID_HANDLE_VALUE) {
186                hFile = ::CreateFile(file.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
187                if (hFile != INVALID_HANDLE_VALUE) {
188                        WORD wBOM = 0xFEFF;
189                        ::WriteFile(hFile, &wBOM, sizeof(WORD), &numberOfBytesWritten, NULL);
190                }
191        }
192        return hFile;
193}
194        if (hFile == INVALID_HANDLE_VALUE) {
195                hFile = ::CreateFile(file.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
196                if (hFile != INVALID_HANDLE_VALUE) {
197                        WORD wBOM = 0xFEFF;
198                        ::WriteFile(hFile, &wBOM, sizeof(WORD), &numberOfBytesWritten, NULL);
199        }
200        return hFile;
201}
202*/
203
204void FileLogger::handleMessage(int msgType, const std::string file, int line, std::string message) {
205        if (!init_) {
206                std::wcout << _T("Discarding: ") << utf8::cvt<std::wstring>(message) << std::endl;
207                return;
208        }
209        if (!nscapi::logging::matches(log_mask_, msgType))
210                return;
211
212        std::ofstream stream(file_.c_str(), std::ios::out|std::ios::app|std::ios::ate);
213        if (!stream) {
214                std::wcout << _T("File could not be opened, Discarding: ") << utf8::cvt<std::wstring>(message) << std::endl;
215        }
216        stream << utf8::cvt<std::string>(get_formated_date())
217                << (": ") << utf8::cvt<std::string>(nscapi::plugin_helper::translateMessageType(msgType))
218                << (":") << file
219                <<(":") << line
220                << (": ") << message << std::endl;
221}
222
223std::wstring FileLogger::get_formated_date() {
224        std::wstringstream ss;
225        boost::posix_time::time_facet *facet = new boost::posix_time::time_facet(format_.c_str());
226        ss.imbue(std::locale(std::cout.getloc(), facet));
227        ss << boost::posix_time::second_clock::local_time();
228        return ss.str();
229}
230
231NSC_WRAP_DLL();
232NSC_WRAPPERS_MAIN_DEF(FileLogger);
233NSC_WRAPPERS_HANDLE_MSG_DEF();
234NSC_WRAPPERS_IGNORE_CMD_DEF();
Note: See TracBrowser for help on using the repository browser.