static rc_t CC KStsDefaultFormatter( void* self, KWrtHandler* writer, size_t argc, const wrt_nvp_t args[], size_t envc, const wrt_nvp_t envs[] ) { rc_t rc = 0; size_t num_writ, nsize; uint32_t mlen; char buffer[8192], *nbuffer; const char* msg, *mend; /* if writer is null than silence */ if( writer == NULL || writer->writer == NULL ) { return rc; } msg = wrt_nvp_find_value(envc, envs, "message"); if( msg != NULL ) { mend = msg + strlen(msg); /* strip trailing newlines */ while( mend != msg && (*mend == '\n' || *mend == '\r') ) { --mend; } mlen = ( uint32_t ) ( mend - msg ); } else { mlen = 0; } nbuffer = buffer; nsize = sizeof(buffer); do { rc = string_printf(nbuffer, nsize, & num_writ, "%s %s.%s: %.*s\n", wrt_nvp_find_value(envc, envs, "timestamp"), wrt_nvp_find_value(envc, envs, "app"), wrt_nvp_find_value(envc, envs, "version"), ( uint32_t ) mlen, msg); if( num_writ > nsize ) { assert ( nbuffer == buffer ); nbuffer = malloc(nsize = num_writ + 2); if( nbuffer == NULL ) { rc = RC(rcRuntime, rcLog, rcLogging, rcMemory, rcExhausted); break; } continue; } /* replace newlines with spaces, excluding last one */ for(nsize = 0; nsize < num_writ - 1; nsize++) { if( nbuffer[nsize] == '\n' || nbuffer[nsize] == '\r' ) { nbuffer[nsize] = ' '; } } break; } while(true); if( rc == 0 ) { rc = LogFlush(writer, nbuffer, num_writ); } if( nbuffer != buffer ) { free(nbuffer); } return rc; }
static rc_t CC LoaderXMLFormatter( void* data, KWrtHandler* writer, size_t argc, const wrt_nvp_t args[], size_t envc, const wrt_nvp_t envs[]) { rc_t rc = 0; size_t i, remaining, num_writ = 0; XMLFormatterData* self = (XMLFormatterData*)data; char buffer[4096]; const char* severity, *msg_val = NULL; bool severity_std = false; char* pbuffer; const char* const tag_nvp_name = "severity"; const wrt_nvp_t* msg_nvp = NULL; static const char* tags[] = { "fatal", "system", "internal", "error", "warning", "info" }; msg_nvp = wrt_nvp_find(envc, envs, "message"); if( msg_nvp != NULL ) { msg_val = msg_nvp->value; } severity = wrt_nvp_find_value(argc, args, tag_nvp_name); if( severity == NULL ) { severity = wrt_nvp_find_value(envc, envs, tag_nvp_name); if( severity != NULL ) { severity_std = true; /* translate std severity name to full name */ for(i = 0; i < sizeof(tags)/sizeof(tags[0]); i++) { if( strncmp(severity, tags[i], strlen(severity)) == 0 ) { severity = tags[i]; break; } } } } if( severity == NULL ) { severity = "status"; } #define FIX_UP() if(rc != 0){break;} remaining -= num_writ; pbuffer += num_writ pbuffer = buffer; remaining = sizeof(buffer); do { size_t k, pq = envc; const wrt_nvp_t* p = envs; const char* subst = NULL; rc = LogInsertSpace("<", pbuffer, remaining, &num_writ); FIX_UP(); rc = LogInsertSpace(severity, pbuffer, remaining, &num_writ); FIX_UP(); /* print env first and than args! */ for(k = 0; rc == 0 && k < 2; k++) { for(i = 0; i < pq; i++ ) { if( strcmp(p[i].name, tag_nvp_name) == 0 ) { continue; } if( p == args ) { if( i == 0 && msg_nvp != NULL ) { /* grab args attr buffer start */ subst = pbuffer; } if( severity_std ) { /* allow only specific attributes from message into xml log for LOG calls with standard severity */ int x, yes = 0; static const char* allowed_attr[] = { "file", "line", "offset", "spot", "spot_name", "spotname" }; for(x = 0; x < sizeof(allowed_attr)/sizeof(allowed_attr[0]); x++) { if( strcasecmp(p[i].name, allowed_attr[x]) == 0 ) { yes = 1; break; } } if( !yes ) { continue; } } } rc = LogInsertSpace(" ", pbuffer, remaining, &num_writ); FIX_UP(); rc = XMLLogger_Encode(p[i].name, pbuffer, remaining, &num_writ); FIX_UP(); rc = LogInsertSpace("=\"", pbuffer, remaining, &num_writ); FIX_UP(); rc = XMLLogger_Encode(p[i].value, pbuffer, remaining, &num_writ); FIX_UP(); rc = LogInsertSpace("\"", pbuffer, remaining, &num_writ); FIX_UP(); } p = args; pq = argc; } if( subst != NULL && subst[0] != '\0' ) { /* hack 'message' to print curr argv to std log as text attr="value" */ ((wrt_nvp_t*)msg_nvp)->value = subst + 1; /* \0 terminated pre LogInsertSpace behavior */ if( (rc = self->fmt.formatter(self->fmt.data, &self->wrt, 0, NULL, envc, envs)) != 0 ) { break; } ((wrt_nvp_t*)msg_nvp)->value = msg_val; } rc = LogInsertSpace("/>\n", pbuffer, remaining, &num_writ); FIX_UP(); } while(false); if( self->file->file != NULL ) { if( rc != 0 ) { pbuffer = buffer; remaining = sizeof(buffer); rc = string_printf(pbuffer, remaining, & num_writ, "<error severity=\"err\" message=\"XML log failed: %R\"/>\n", rc); pbuffer += num_writ <= remaining ? num_writ : 0; } rc = KFileWrite(self->file->file, self->file->pos, buffer, pbuffer - buffer, &num_writ); self->file->pos += num_writ; } rc = self->fmt.formatter(self->fmt.data, &self->wrt, argc, args, envc, envs); return rc; }