注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天道酬勤 玩物丧志

用勇气去改变可以改变的事情,用胸怀去包容无法改变的事情,用智慧去判断两者的区别

 
 
 

日志

 
 

linux c 写日志  

2012-09-04 16:15:59|  分类: 日记 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

[

文件] thread_log.h ~ 2KB    

#include <pthread.h>

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

#define QUEUE_LEN 128 //申请128个空间的队列

#define MAX_STR_LEN 256

 

int run = 1;

 

typedef struct log_queue {

      char data[QUEUE_LEN + 1][MAX_STR_LEN];//浪费一个节点f 用来区分''''

      int front, rear;

} log_queue;

 

typedef struct thread_info{

      struct log_queue lq;

      FILE *f;

} thread_info;

 

// default_size : The size of Linked Queue by deault

void init_queue(thread_info *thin){

      (thin->lq).front = (thin->lq).rear = 0;

}

 

void queue_in(log_queue *lq, char *data){

      if(lq->front == (lq->rear + 1) % (QUEUE_LEN + 1)){

      //      puts("Queue is full\n");

            return;

       }

      lq->rear = (lq->rear + 1) % (QUEUE_LEN + 1);

      strncpy(lq->data[lq->rear], data, strlen(data));

}

 

int queue_out(log_queue *lq){

       int index = 0;

      if(lq->front == lq->rear){

            return -1;

      }

       index = lq->front;

      lq->front = (lq->front + 1) % (QUEUE_LEN + 1);

       return index + 1;

}

 

void *async_fputs(void *arg){

       int index = -1;

       thread_info *thin = (thread_info *)arg;

       while(run){

              //读取队列首中的串, 并写入日志文件

              usleep(1);//交出CPU控制权

              if(-1 != (index = queue_out(&thin->lq))){

                     fputs((thin->lq.data)[index], thin->f);

                     fflush(thin->f);

              }

       }

       pthread_exit((void *)1);

}

 

pthread_t *load_pthread(thread_info *thin){

       pthread_t *child_thread = (pthread_t *)malloc(sizeof(pthread_t));

       pthread_create(child_thread, NULL, async_fputs, (void *)&thin);

       return child_thread;

}//1. 实时写日志  2. 运行过程中写

 

[文件] thread_log.h ~ 2KB    

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <stdarg.h>

#include <time.h>

#include <sys/stat.h>

#include <unistd.h>

#include <dirent.h>

#include <assert.h>

 

#include "logger.h"

#include "thread_log.h"

 

#define MAX         128

#define MAX_SIZE_MB 8.0 //8MB的日志大小

#define MB          1024 * 1024 //1MB

#define QUEUE_LEN   128

#define MAX_STR_LEN 256

#define DATE_FORMAT "[%04d-%02d-%02d %02d:%02d:%02d]"

 

#define ERROR 8

#define DEBUG 4

#define WARN  2

#define INFO  1

 

int log_level;

time_t timer;

struct tm *now;

 

void    info(log_queue *lq, p_stack st, FILE *file, const char *format, ...);

void    size_check(p_stack st, FILE **file, const char *oldname, const char* newname);

void    init_logger(p_stack st, struct stat *s, FILE **f, int level, thread_info *pti);

p_stack init_logger_stack();

p_stack init_stack();

void    push(p_stack st, int year, int month, int day, int flag, const char *name);

void    pop(p_stack st);

void    put_stack(p_stack st);

 

int main(int argc, char *argv[]){

       thread_info ti;

       pthread_t pt;

       FILE *f;

       struct stat s;

       run = 1;

       p_stack st = init_logger_stack();

       init_queue(&ti);

       init_logger(st, &s, &f, DEBUG, &ti);//init_logger(*stack, ctime struct, log files, folder, level)

       pthread_create(&pt, NULL, async_fputs, (void *)&ti);

       info(&ti.lq, st, f, "%s, Line:%d, string:%s int:%d", __FILE__, __LINE__, "test", 2012);

       info(&ti.lq, st, f, "%s, Line:%d, string:%s int:%d", __FILE__, __LINE__, "test", 2012);

       info(&ti.lq, st, f, "%s, Line:%d, string:%s int:%d", __FILE__, __LINE__, "test", 2012);

       info(&ti.lq, st, f, "%s, Line:%d, string:%s int:%d", __FILE__, __LINE__, "test", 2012);

       info(&ti.lq, st, f, "%s, Line:%d, string:%s int:%d", __FILE__, __LINE__, "test", 2012);

       info(&ti.lq, st, f, "%s, Line:%d, string:%s int:%d", __FILE__, __LINE__, "test", 2012);

       pthread_join(pt, NULL);

       return 0;

}

 

void init_logger(p_stack st, struct stat *s, FILE **file, int level, thread_info *pti){//f既是形参,也算是返回值

       char temp[128] = {0}, new_name[128] = {0};

       log_level = level;//全局日志级别log_level

       time(&timer);

       now = localtime(&timer);

       sprintf(temp, "%s/%4d-%02d-%02d.log", "log", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);//生成日志log/2012-01-05.log

       sprintf(new_name, "%s.%d", temp, st->data.flag + 1);//log/2012-01-05.log.max+1

 

       if(-1 == stat("log", s)){

              puts("[warn]文件夹不存在");

              mkdir("log", 777);

       }

 

       if(!(*file = fopen(temp, "a+"))){

              puts("[error]open log file failed");

              exit(-1);

       }else{

              pti->f = *file;

              size_check(st, file, temp, new_name);

       }

}

 

void info(log_queue *lq, p_stack st, FILE *file, const char *format, ...){// 一整天过去之后怎么轮转日志???

       char src[MAX] = {'\0'}, dateformat[MAX] = {'\0'}, temp[128] = {0}, new_name[128] = {0};//顺序遍历format

       va_list argp = NULL;

       time(&timer);

       now = localtime(&timer);

       sprintf(dateformat, DATE_FORMAT, now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);

       sprintf(temp, "%s/%4d-%02d-%02d.log", "log", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);//生成日志log/2012-01-05.log.10

       sprintf(new_name, "%s.%d", temp, st->data.flag + 1);//log/2012-01-05.log.max+1

      

       va_start(argp, format);

       vsprintf(src, format, argp);

       va_end(argp);

 

       switch(log_level){//log_level每个级别宏定义一下更好

              case ERROR://error级别

              case DEBUG://debug级别

              case WARN://warn级别

              case INFO://info级别

              // 线程维护的循环队列 里面插入要写入的串

                     sprintf(dateformat, "%s [INFO]:%s \r\n", dateformat, src);

                     queue_in(lq, dateformat);

              default:

                     break;

       }

       size_check(st, &file, temp, new_name);

}

 

void size_check(p_stack st, FILE **file, const char *oldname, const char *newname){

       int size;

       float mb;

       fseek(*file, 0, SEEK_END);

       size = ftell(*file);

       rewind(*file);

       if(size / MB >= MAX_SIZE_MB){

              fclose(*file);

              rename(oldname, newname);//  重命名log/2012-01-05.log ==> log/2012-01-05.log.max+1

              if((*file = fopen(oldname, "a+")) != NULL){

                     puts("[error]open log file failed");

                     exit(-1);

              }//返回值不可能为NULL

              push(st, now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, st->data.flag + 1, newname);//log/2012-01-05.log.max+1入栈

       }

}

 

 

[文件] logger.h ~ 2KB

#ifndef _LOGGER_H_

#define _LOGGER_H_

 

#include <stdio.h>

#include <time.h>

#include <stdlib.h>

#include <string.h>

#include <dirent.h>

 

#define MAX_NAME_LEN 256

#define USHORT unsigned short

 

typedef struct log_inf {

       int year;

       int month;

       int day;

       int flag;//结尾符

       char log_name[MAX_NAME_LEN];

} log_inf, *p_inf;

 

typedef struct stack {

       log_inf data;

       struct stack *next;

       unsigned int top;

} stack, *p_stack;

 

//初始化链栈

p_stack init_stack(){

       p_stack p = (stack *)malloc(sizeof(stack));

       if(NULL == p)

              puts("malloc failed");

       p->data.flag = 0;//头结点的flag 用来 保存max_flag

       p->next = NULL;

       p->top  = 0;

       return p;

}

 

//入链栈

void push(p_stack st, int year, int month, int day, int flag, const char *name){

       stack *node = (stack *)malloc(sizeof(stack));

       if(NULL == node)

              puts("malloc failed");

       node->data.year  = year;

       node->data.month = month;

       node->data.day   = day;

       node->data.flag  = flag;

       strncpy(node->data.log_name, name, strlen(name));

       if(flag > st->data.flag){

              st->data.flag = flag;

       }

       node->next       = st->next;

       st->next         = node;

       ++(st->top);

}

 

//出栈, 销毁节点

void pop(p_stack st){

       stack *tmp = st->next;

       st->next   = st->next->next;

       free(tmp);

}

 

//打印整个栈

void put_stack(p_stack st){

       stack *head = st->next;//不能修改*head

       while(head){

              puts(head->data.log_name);

              head = head->next;

       }

}

 

//取当日所有日志文件来  初始化链栈

p_stack init_logger_stack(){

       log_inf li;

       p_stack st = init_stack();

       DIR *dir;

       time_t timer;

       struct tm *now;

       struct dirent *dptr;

       if(!(dir = opendir("log"))){

              puts("[error]open dir failed");

              exit(-1);

       }

       time(&timer);

       now = (struct tm *)localtime(&timer);

       while(dptr = readdir(dir)){

              if(dptr->d_type != DT_DIR){

                     sscanf(dptr->d_name, "%4d-%02d-%02d.log.%d", &li.year, &li.month, &li.day, &li.flag);

                     if((now->tm_year + 1900 == li.year) && (now->tm_mon + 1 == li.month) && (now->tm_mday == li.day)){//我们只取当天的日志文件 入链栈

                            push(st, li.year, li.month, li.day, li.flag, dptr->d_name);

                     }

              }

       }

       return st;

}

 

#endif

 

参考: http://www.oschina.net/code/snippet_227071_8076

  评论这张
 
阅读(1249)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018