- Changes in logging and debug output
[public/netxms.git] / src / server / core / log.cpp
1 /*
2 ** Network Management System Core
3 ** Copyright (C) 2003 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** $module: log.cpp
20 **
21 **/
22
23 #include "nms_core.h"
24
25
26 //
27 // Messages generated by mc.pl (for UNIX version only)
28 //
29
30 #ifndef _WIN32
31 extern DWORD g_dwNumMessages;
32 extern char *g_szMessages[];
33 #endif
34
35
36 //
37 // Static data
38 //
39
40 #ifdef _WIN32
41 static HANDLE m_hEventLog = INVALID_HANDLE_VALUE;
42 #endif
43 static FILE *m_hLogFile = NULL;
44 static MUTEX m_mutexLogAccess = INVALID_MUTEX_HANDLE;
45
46
47 //
48 // Initialize log
49 //
50
51 void InitLog(void)
52 {
53 #ifdef _WIN32
54 if (g_dwFlags & AF_USE_EVENT_LOG)
55 {
56 m_hEventLog = RegisterEventSource(NULL, CORE_EVENT_SOURCE);
57 }
58 else
59 {
60 #endif
61 char szTimeBuf[32];
62 struct tm *loc;
63 time_t t;
64
65 m_hLogFile = fopen(g_szLogFile, "a");
66 t = time(NULL);
67 loc = localtime(&t);
68 strftime(szTimeBuf, 32, "%d-%b-%Y %H:%M:%S", loc);
69 fprintf(m_hLogFile, "\n[%s] Log file opened\n", szTimeBuf);
70 fflush(m_hLogFile);
71
72 m_mutexLogAccess = MutexCreate();
73 #ifdef _WIN32
74 }
75 #endif
76 }
77
78
79 //
80 // Close log
81 //
82
83 void CloseLog(void)
84 {
85 #ifdef _WIN32
86 if (g_dwFlags & AF_USE_EVENT_LOG)
87 {
88 DeregisterEventSource(m_hEventLog);
89 }
90 else
91 {
92 #endif
93 if (m_hLogFile != NULL)
94 {
95 char szTimeBuf[32];
96 struct tm *loc;
97 time_t t;
98
99 t = time(NULL);
100 loc = localtime(&t);
101 strftime(szTimeBuf, 32, "%d-%b-%Y %H:%M:%S", loc);
102 fprintf(m_hLogFile, "[%s] Log file closed\n", szTimeBuf);
103 fclose(m_hLogFile);
104 }
105 if (m_mutexLogAccess != INVALID_MUTEX_HANDLE)
106 MutexDestroy(m_mutexLogAccess);
107 #ifdef _WIN32
108 }
109 #endif
110 }
111
112
113 //
114 // Write record to log file
115 //
116
117 static void WriteLogToFile(char *szMessage)
118 {
119 char szBuffer[64];
120 time_t t;
121 struct tm *loc;
122
123 // Prevent simultaneous write to log file
124 MutexLock(m_mutexLogAccess, INFINITE);
125
126 t = time(NULL);
127 loc = localtime(&t);
128 strftime(szBuffer, 32, "[%d-%b-%Y %H:%M:%S]", loc);
129 fprintf(m_hLogFile, "%s %s", szBuffer, szMessage);
130 fflush(m_hLogFile);
131 if (IsStandalone())
132 printf("%s %s", szBuffer, szMessage);
133
134 MutexUnlock(m_mutexLogAccess);
135 }
136
137
138 //
139 // Format message (UNIX version)
140 //
141
142 #ifndef _WIN32
143
144 char *FormatMessageUX(DWORD dwMsgId, char **ppStrings)
145 {
146 char *p, *pMsg;
147 int i, iSize, iLen;
148
149 if (dwMsgId >= g_dwNumMessages)
150 {
151 // No message with this ID
152 pMsg = (char *)malloc(128);
153 sprintf(pMsg, "MSG 0x%08X - Unable to find message text\n", dwMsgId);
154 }
155 else
156 {
157 iSize = strlen(g_szMessages[dwMsgId]) + 2;
158 pMsg = (char *)malloc(iSize);
159
160 for(i = 0, p = g_szMessages[dwMsgId]; *p != 0; p++)
161 if (*p == '%')
162 {
163 p++;
164 if ((*p >= '1') && (*p <= '9'))
165 {
166 iLen = strlen(ppStrings[*p - '1']);
167 iSize += iLen;
168 pMsg = (char *)realloc(pMsg, iSize);
169 strcpy(&pMsg[i], ppStrings[*p - '1']);
170 i += iLen;
171 }
172 else
173 {
174 if (*p == 0) // Handle single % character at the string end
175 break;
176 pMsg[i++] = *p;
177 }
178 }
179 else
180 {
181 pMsg[i++] = *p;
182 }
183 pMsg[i++] = '\n';
184 pMsg[i] = 0;
185 }
186
187 return pMsg;
188 }
189
190 #endif /* ! _WIN32 */
191
192
193 //
194 // Write log record
195 // Parameters:
196 // msg - Message ID
197 // wType - Message type (see ReportEvent() for details)
198 // format - Parameter format string, each parameter represented by one character.
199 // The following format characters can be used:
200 // s - String
201 // d - Decimal integer
202 // x - Hex integer
203 // e - System error code (will appear in log as textual description)
204 // a - IP address in network byte order
205 //
206
207 void WriteLog(DWORD msg, WORD wType, char *format, ...)
208 {
209 va_list args;
210 char *strings[16], *pMsg;
211 int numStrings = 0;
212 DWORD error;
213
214 memset(strings, 0, sizeof(char *) * 16);
215
216 if (format != NULL)
217 {
218 va_start(args, format);
219
220 for(; (format[numStrings] != 0) && (numStrings < 16); numStrings++)
221 {
222 switch(format[numStrings])
223 {
224 case 's':
225 strings[numStrings] = strdup(va_arg(args, char *));
226 break;
227 case 'd':
228 strings[numStrings] = (char *)malloc(16);
229 sprintf(strings[numStrings], "%d", va_arg(args, LONG));
230 break;
231 case 'x':
232 strings[numStrings] = (char *)malloc(16);
233 sprintf(strings[numStrings], "0x%08X", va_arg(args, DWORD));
234 break;
235 case 'a':
236 strings[numStrings] = (char *)malloc(20);
237 IpToStr(va_arg(args, DWORD), strings[numStrings]);
238 break;
239 case 'e':
240 error = va_arg(args, DWORD);
241 #ifdef _WIN32
242 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
243 FORMAT_MESSAGE_FROM_SYSTEM |
244 FORMAT_MESSAGE_IGNORE_INSERTS,
245 NULL, error,
246 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), // Default language
247 (LPSTR)&pMsg,0,NULL)>0)
248 {
249 pMsg[strcspn(pMsg,"\r\n")] = 0;
250 strings[numStrings]=(char *)malloc(strlen(pMsg) + 1);
251 strcpy(strings[numStrings], pMsg);
252 LocalFree(pMsg);
253 }
254 else
255 {
256 strings[numStrings] = (char *)malloc(64);
257 sprintf(strings[numStrings], "MSG 0x%08X - Unable to find message text", error);
258 }
259 #else /* _WIN32 */
260 strings[numStrings] = strdup(strerror(error));
261 #endif
262 break;
263 default:
264 strings[numStrings] = (char *)malloc(32);
265 sprintf(strings[numStrings], "BAD FORMAT (0x%08X)", va_arg(args, DWORD));
266 break;
267 }
268 }
269 va_end(args);
270 }
271
272 #ifdef _WIN32
273 if (g_dwFlags & AF_USE_EVENT_LOG)
274 {
275 ReportEvent(m_hEventLog, wType, 0, msg, NULL, numStrings, 0, (const char **)strings, NULL);
276 }
277 else
278 {
279 LPVOID lpMsgBuf;
280
281 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
282 NULL, msg, 0, (LPTSTR)&lpMsgBuf, 0, strings)>0)
283 {
284 char *pCR;
285
286 // Replace trailing CR/LF pair with LF
287 pCR = strchr((char *)lpMsgBuf, '\r');
288 if (pCR != NULL)
289 {
290 *pCR = '\n';
291 pCR++;
292 *pCR = 0;
293 }
294 WriteLogToFile((char *)lpMsgBuf);
295 LocalFree(lpMsgBuf);
296 }
297 else
298 {
299 char message[64];
300
301 sprintf(message,"MSG 0x%08X - Unable to find message text\n",msg);
302 WriteLogToFile(message);
303 }
304 }
305 #else /* _WIN32 */
306 pMsg = FormatMessageUX(msg, strings);
307 if (g_dwFlags & AF_USE_EVENT_LOG)
308 {
309 }
310 else
311 {
312 WriteLogToFile(pMsg);
313 }
314 free(pMsg);
315 #endif /* _WIN32 */
316
317 while(--numStrings >= 0)
318 free(strings[numStrings]);
319 }