1.10. logger服务

涉及的结构体为:

struct logger {
    FILE * handle;        //用于存储log的输出,默认是控制台,否则为文档
    char * filename;    //如果是输出文件则保存文件名
    int close;            //标记是否需要关闭文档
};

logger服务主要用于log输出,在前面的1.3节中有介绍到,在函数skynet_start中会创建一个logger服务,在1.4节也介绍了服务的创建过程skynet_context_new,对于logger服务的创建过程为:首先根据配置文件中config->logservice(默认为“logger”)项指定的名称来获取服务动态库指针,然后调用logger_create函数创建一个服务实例,接着调用logger_init函数对实例进行初始化,如果配置文件config->logger这项有配置则用该配置名打开文件将log输入该文件,否则标准输出,注册该服务实例的回调函数,同时将该服务命名为“logger”。

//初始化给定的inst,如果parm不为NULL则创建一个文件用于存储,否则输出到标准输出
//将服务命名为logger
int logger_init(struct logger * inst, struct skynet_context *ctx, const char * parm) {
    if (parm) {        //如果参数不为NULL
        inst->handle = fopen(parm,"w");    //打开parm指定的文件,返回文件句柄
        if (inst->handle == NULL) {
            return 1;
        }
        inst->filename = skynet_malloc(strlen(parm)+1);
        strcpy(inst->filename, parm);    //拷贝文件名
        inst->close = 1;                //标记问需要关闭文档
    } else {
        inst->handle = stdout;            //否则为标准输出,即输出到控制台
    }
    if (inst->handle) {
        skynet_callback(ctx, inst, logger_cb);    //注册该服务实例的回调函数
        skynet_command(ctx, "REG", ".logger");    //将服务命名为logger
        return 0;
    }
    return 1;
}

logger服务的消息处理

关于服务的消息处理在1.6节有介绍,当从服务队列中取出消息进行处理时,如果该服务有注册回调函数则会调用相应的回调函数进行处理,而logger服务在logger_init函数中注册了回调函数logger_cb,所以对于该服务的每一条消息都会调用logger_cb函数进行处理,接下来看一下该函数的工作流程,该函数根据消息的类型对其进行处理,对于消息类型为PTYPE_SYSTEM的消息,该消息一般为输出终端关闭触发SIGHUP事件,定时器线程在处理过程中对该事件进行相应的处理signal_hup函数,即发送PTYPE_SYSTEM类型的消息,将log重定向到inst->filename指定的文件中。对于消息类型为PTYPE_TEXT的消息,即为正常的log输出。代码注释如下:

//处理该服务的消息回调函数
static int logger_cb(struct skynet_context * context, void *ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
    struct logger * inst = ud;
    switch (type) {
    case PTYPE_SYSTEM:        //logger服务的系统消息,以追加的形式重定向log输出到inst->filename指定的文件
        if (inst->filename) {
            inst->handle = freopen(inst->filename, "a", inst->handle);
        }
        break;
    case PTYPE_TEXT:        //正常的log输出
        fprintf(inst->handle, "[:%08x] ",source);    //以“:”+8位十六进制的形式输出服务发送消息的服务handle
        fwrite(msg, sz , 1, inst->handle);            //输出消息内容
        fprintf(inst->handle, "\n");                //回车
        fflush(inst->handle);                        //刷新
        break;
    }
    return 0;
}

skynet错误信息的输出skynet_error也是通过将错误信息以消息的形式压入logger服务的队列中,logger服务通过上述方式将错误信息输出。

results matching ""

    No results matching ""