static void log_sink_console_log()

in v2/src/log_sink_console.c [56:157]


static void log_sink_console_log(LOG_LEVEL log_level, LOG_CONTEXT_HANDLE log_context, const char* file, const char* func, int line, const char* message_format, va_list args)
{

    if (message_format == NULL)
    {
        /* Codes_SRS_LOG_SINK_CONSOLE_01_001: [ If message_format is NULL, log_sink_console.log shall print an error and return. ]*/
        (void)printf("Invalid arguments: LOG_LEVEL log_level=%" PRI_MU_ENUM ", LOG_CONTEXT_HANDLE log_context=%p, const char* file=%s, const char* func=%s, int line=%d, const char* message_format=%s\r\n",
            MU_ENUM_VALUE(LOG_LEVEL, log_level), log_context, MU_P_OR_NULL(file), MU_P_OR_NULL(func), line, MU_P_OR_NULL(message_format));
    }
    else
    {
        /* Codes_SRS_LOG_SINK_CONSOLE_01_021: [ log_sink_console.log shall print at most LOG_MAX_MESSAGE_LENGTH characters including the null terminator (the rest of the context shall be truncated). ]*/
        char temp[LOG_MAX_MESSAGE_LENGTH];
        char* buffer = temp;
        size_t buffer_size = sizeof(temp);

        /* Codes_SRS_LOG_SINK_CONSOLE_01_002: [ log_sink_console.log shall obtain the time by calling time. ]*/
        time_t t = time(NULL);
        /* Codes_SRS_LOG_SINK_CONSOLE_01_024: [ If the call to ctime fails then log_sink_console.log shall print the time as NULL. ]*/
        char* ctime_result = (t == (time_t)-1) ? NULL : ctime(&t);

        /* Codes_SRS_LOG_SINK_CONSOLE_01_003: [ log_sink_console.log shall convert the time to string by calling ctime. ]*/
        /* Codes_SRS_LOG_SINK_CONSOLE_01_004: [ log_sink_console.log shall print a line in the format: {log_level} Time: {formatted time} File:{file}:{line} Func:{func} {optional context information} {formatted message} ]*/
        int snprintf_result = snprintf(buffer, buffer_size, "%s%s Time:%.24s File:%s:%d Func:%s",
            /* Codes_SRS_LOG_SINK_CONSOLE_01_006: [ log_sink_console.log shall color the lines using ANSI color codes (https://en.wikipedia.org/wiki/ANSI_escape_code#Colors), as follows: ]*/
            level_colors[log_level],
            MU_ENUM_TO_STRING(LOG_LEVEL, log_level),
            /* Codes_SRS_LOG_SINK_CONSOLE_01_023: [ If the call to time fails then log_sink_console.log shall print the time as NULL. ]*/
            MU_P_OR_NULL(ctime_result),
            MU_P_OR_NULL(file),
            line,
            MU_P_OR_NULL(func));
        if (snprintf_result < 0)
        {
            /* Codes_SRS_LOG_SINK_CONSOLE_01_022: [ If any encoding error occurs during formatting of the line (i.e. if any printf class functions fails), log_sink_console.log shall print Error formatting log line and return. ]*/
            (void)printf(error_string);
        }
        else
        {
            bool error = false;

            snprintf_result = MIN(snprintf_result, (int)buffer_size);
            buffer += snprintf_result;
            buffer_size -= snprintf_result;

            /* Codes_SRS_LOG_SINK_CONSOLE_01_013: [ If log_context is non-NULL: ]*/
            if (log_context != NULL)
            {
                /* Codes_SRS_LOG_SINK_CONSOLE_01_014: [ log_sink_console.log shall call log_context_get_property_value_pair_count to obtain the count of properties to print. ]*/
                size_t property_value_pair_count = log_context_get_property_value_pair_count(log_context);
                /* Codes_SRS_LOG_SINK_CONSOLE_01_015: [ log_sink_console.log shall call log_context_get_property_value_pairs to obtain the properties to print. ]*/
                const LOG_CONTEXT_PROPERTY_VALUE_PAIR* property_value_pairs = log_context_get_property_value_pairs(log_context);

                /* Codes_SRS_LOG_SINK_CONSOLE_42_001: [ log_sink_console.log shall call log_context_property_to_string to print the properties to the string buffer. ]*/
                int log_n_properties_result = log_context_property_to_string(buffer, buffer_size, property_value_pairs, property_value_pair_count); // lgtm[cpp/unguardednullreturndereference] Tests and code review ensure that NULL access cannot happen
                if (log_n_properties_result < 0)
                {
                    /* Codes_SRS_LOG_SINK_CONSOLE_01_022: [ If any encoding error occurs during formatting of the line (i.e. if any printf class functions fails), log_sink_console.log shall print Error formatting log line and return. ]*/
                    error = true;
                }
                else
                {
                    log_n_properties_result = MIN(log_n_properties_result, (int)buffer_size);
                    buffer += log_n_properties_result;
                    buffer_size -= log_n_properties_result;
                }
            }

            if (!error)
            {
                if (buffer_size > 1)
                {
                    *buffer = ' ';
                    buffer++;
                    buffer_size--;

                    int vsnprintf_result = vsnprintf(buffer, buffer_size, message_format, args);
                    if (vsnprintf_result < 0)
                    {
                        /* Codes_SRS_LOG_SINK_CONSOLE_01_022: [ If any encoding error occurs during formatting of the line (i.e. if any printf class functions fails), log_sink_console.log shall print Error formatting log line and return. ]*/
                        error = true;
                    }
                    else
                    {
                        // all ok
                    }
                }
            }

            if (error)
            {
                (void)printf(error_string);
            }
            else
            {
                /* Codes_SRS_LOG_SINK_CONSOLE_01_005: [ In order to not break the line in multiple parts when displayed on the console, log_sink_console.log shall print the line in such a way that only one printf call is made. ]*/
                /* Codes_SRS_LOG_SINK_CONSOLE_01_012: [ At the end of each line that is printed, the color shall be reset by using the \x1b[0m code. ]*/
                (void)printf("%s%s\r\n", temp, LOG_SINK_CONSOLE_ANSI_COLOR_RESET);
            }
        }
    }
}