1 /*
2 * test_rollingfile_appender.c
3 *
4 * This file demonstrates how to programatically use the rolling
5 * file appender and tests it in a multi-threaded environment. See
6 * also the API documentation for the appender_type_rollingfile.h file.
7 *
8 * It is possible to be more terse here if you accept the default values,
9 * but we spell it out explicitly.
10 *
11 * See the COPYING file for the terms of usage and distribution.
12 */
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include <stdio.h>
19 #ifdef HAVE_SYS_TIME_H
20 #include <sys/time.h>
21 #endif
22 #ifdef HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25 #ifdef HAVE_PTHREAD_H
26 #include <pthread.h>
27 #endif
28 #include <string.h>
29 #include <stdlib.h>
30 #include <log4c.h>
31 #include <log4c/appender_type_rollingfile.h>
32 #include <log4c/rollingpolicy_type_sizewin.h>
33
34 /*
35 * Include sd_xplatform to pick up handy xplatform macros.
36 * This file is not part of the distribution of log4c so an application using the
37 * distribution of log4c must handle it's own x-platform issues: eg. threading,
38 * the slight differences between the c functions etc.
39 */
40 #include <sd/sd_xplatform.h>
41
42 /*********************** Parameters **********************************
43 *
44 * could be taken from the command line to facilitate testing
45 *
46 */
47
48 /*
49 * rolling file specific params
50 */
51 char *param_log_dir = ROLLINGFILE_DEFAULT_LOG_DIR;
52 char* param_log_prefix = ROLLINGFILE_DEFAULT_LOG_PREFIX"rfmt";
53 long param_max_file_size = 10*1024; /* 0 means 'no_limit' */
54 long param_max_num_files = 6;
55
56 /*
57 * Other Logging params
58 */
59 char *param_layout_to_use = "basic"; /* could also be "dated" */
60 #define PARAM_NUM_THREADS 10
61 int param_loops_per_thread = 100;
62
63 /*******************************************************************
64 *
65 * Globals
66 *
67 */
68 log4c_category_t* root = NULL;
69 log4c_appender_t* file_appender = NULL;
70 log4c_layout_t* basic_layout = NULL;
71 /******************************************************************************
72 *
73 * Local functions
74 */
75
76 typedef XP_UINT64 usec_t;
now(void)77 static usec_t now(void)
78 {
79 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)
80 FILETIME tv;
81 ULARGE_INTEGER li;
82 #else
83 struct timeval tv;
84 #endif
85
86 SD_GETTIMEOFDAY(&tv, NULL);
87
88 #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)
89 memcpy(&li, &tv, sizeof(FILETIME));
90 li.QuadPart /= 10; /* In microseconds */
91 /* printf("timestampstamp usec %I64u\n", li.QuadPart);*/
92 return li.QuadPart;
93 #else
94 return (usec_t) (tv.tv_sec * 1000000 + tv.tv_usec);
95 #endif
96
97 }
98
99 /******************************************************************************/
100
101 /*
102 * Init log4c and configure a rolling file appender
103 *
104 */
init_log4c_with_rollingfile_appender()105 static void init_log4c_with_rollingfile_appender(){
106 int rc = 2;
107 rollingfile_udata_t *rfup = NULL;
108 log4c_rollingpolicy_t *policyp = NULL;
109 rollingpolicy_sizewin_udata_t *sizewin_confp = NULL;
110
111 printf("using the rolling file appender with multiple logging threads"
112 "to write test log files\n"
113 "to log directory '%s', log file prefix is '%s'"
114 ", max file size is '%ld'\n"
115 "max num files is '%ld'\n",
116 param_log_dir, param_log_prefix, param_max_file_size,
117 param_max_num_files);
118
119 if ( (rc = log4c_init()) == 0 ) {
120 printf("log4c init success\n");
121 } else {
122 printf("log4c init failed--error %d\n", rc);
123 return;
124 }
125
126 /*
127 * Get a reference to the root category
128 */
129 root = log4c_category_get("root");
130 log4c_category_set_priority(root,
131 LOG4C_PRIORITY_WARN);
132
133 /*
134 * Get a file appender and set the type to rollingfile
135 */
136 file_appender = log4c_appender_get("aname");
137 log4c_appender_set_type(file_appender,
138 log4c_appender_type_get("rollingfile"));
139
140 /*
141 * Make a rolling file conf object and set the basic parameters
142 */
143 rfup = rollingfile_make_udata();
144 rollingfile_udata_set_logdir(rfup, param_log_dir);
145 rollingfile_udata_set_files_prefix(rfup, param_log_prefix);
146
147 /*
148 * Get a new rollingpolicy
149 * type defaults to "sizewin" but set the type explicitly here
150 * to show how to do it.
151 */
152 policyp = log4c_rollingpolicy_get("a_policy_name");
153 log4c_rollingpolicy_set_type(policyp,
154 log4c_rollingpolicy_type_get("sizewin"));
155
156 /*
157 * Get a new sizewin policy type and configure it.
158 * Then attach it to the policy object.
159 */
160 sizewin_confp = sizewin_make_udata();
161 sizewin_udata_set_file_maxsize(sizewin_confp, param_max_file_size);
162 sizewin_udata_set_max_num_files(sizewin_confp, param_max_num_files);
163 log4c_rollingpolicy_set_udata(policyp,sizewin_confp);
164
165 /*
166 * Configure our rolling policy, then use that to configure
167 * our rolling file appender.
168 */
169
170 rollingfile_udata_set_policy(rfup, policyp);
171 log4c_appender_set_udata(file_appender, rfup);
172
173 /*
174 * Open the rollingfile appender. This will also trigger
175 * the initialization of the rollingpolicy.
176 * Log4c is not thread safe with respect to creation/initialization
177 * of categories and appenders, so we must call the open
178 * once, before all the threads kick in logging with this appender.
179 * Calling open as a side effect of the first call to append does
180 * not work in a MT environment.
181 *
182 * For info, could also call init directly on the rollingpolicy here:
183 * log4c_rollingpolicy_init(policyp, rfup);
184 *
185 *
186 */
187 log4c_appender_open(file_appender);
188
189 /*
190 * Configure a layout for the rolling file appender
191 * (could also have chosen "basic" here, for example)
192 */
193 log4c_appender_set_layout(file_appender,
194 log4c_layout_get(param_layout_to_use) );
195
196 /*
197 * Configure the root category with our rolling file appender...
198 * and we can then start logging to it.
199 *
200 */
201 log4c_category_set_appender(root,file_appender );
202
203 log4c_dump_all_instances(stderr);
204
205
206 }
207
208 /*
209 * thread function to log messages
210 *
211 */
212 #ifdef _WIN32
thread_log_messages(void * arg)213 unsigned int thread_log_messages(void *arg)
214 #else
215 void * thread_log_messages(void *arg)
216 #endif
217 {
218
219 int loop;
220 usec_t stop_time;
221 usec_t start_time;
222 unsigned long elapsed;
223 int tid,j;
224 char buf[1024];
225
226 tid= *((int *)arg);
227
228 loop = 0 ;
229 while (loop < param_loops_per_thread) {
230
231 /* Now start the transaction measurement. */
232 start_time = now();
233
234 /* Do a bit of work, fabricate a string containing the thread id */
235 buf[0] = '\0';
236 j = 0;
237 while( j < 128) {
238 snprintf(&buf[strlen(buf)], 1024-strlen(buf), "%d", tid);
239 j++;
240 }
241 sleep(1);
242
243 stop_time = now();
244 elapsed = (unsigned long)(((usec_t)stop_time - (usec_t)start_time)/1000);
245 /*printf("Hello world--thread(%d)! (loop %d of %d) sleeping for 1 second"
246 "--measured time %lld--%s\n", tid, loop, param_loops_per_thread,
247 stop_time-start_time,buf);*/
248 log4c_category_fatal(root,
249 "Hello world--thread(%d)! (loop %d of %d) sleeping for 1 second"
250 "--measured tme %ld ms--%s\n", tid, loop, param_loops_per_thread,
251 elapsed,buf);
252
253 loop++;
254 }
255 #ifndef _WIN32
256 return(NULL);
257 #else
258 return(0);
259 #endif
260 }
261
262
main(int argc,char * argv[])263 int main(int argc, char *argv[])
264 {
265
266 int rc = 0;
267 pthread_t tid[PARAM_NUM_THREADS];
268 int i;
269
270 init_log4c_with_rollingfile_appender();
271
272
273 /* Simple start/stop example. */
274 printf("Launching %d threads to log messages\n", PARAM_NUM_THREADS);
275 for ( i = 0; i < PARAM_NUM_THREADS; i++){
276 int * this_thread_arg =
277 NULL;
278
279 if ((this_thread_arg = (int *)malloc(sizeof(int))) == NULL){
280 exit(1);
281 }
282 *this_thread_arg = i;
283 rc = pthread_create(&tid[i], NULL, thread_log_messages,
284 (void *)this_thread_arg);
285 if ( tid[i] == 0 ) {
286 printf("Error creating thead %d...exiting\n", i);
287 exit(1);
288 }
289 }
290
291 for ( i = 0; i < PARAM_NUM_THREADS; i++){
292 pthread_join(tid[i], NULL);
293 }
294
295 /* Explicitly call the log4c cleanup routine */
296 if ( log4c_fini()){
297 printf("log4c_fini() failed");
298 }
299
300 return rc;
301 }
302
303