Using esp_log_set_vprintf() function

kartikkman
Posts: 15
Joined: Wed Jul 19, 2017 11:27 am

Using esp_log_set_vprintf() function

Postby kartikkman » Sat Dec 16, 2017 8:09 am

Hi I am trying to do Remote Logging for the esp32 .
I have implemented a function to convert the LOG data to the string which I will be sending over the Network .

The problem I am stuck here is to use the esp_log_set_vprintf() ??
DO you have any example or what for the above ??

Code: Select all

void LOG_TO_STRING(const char *format,...)
{
    ESP_LOGI("NO TAG","Call Accepted ");

        char *string;//printf result will be sotred in this     
        va_list arguments_list;
        va_start(arguments_list,format);//Initialiasing the List 
        
                    //Calculating & Allocating Size 
        
                    size_t size_string=snprintf(NULL,0,format,arguments_list);//Calculating the size of the formed string 
                    string=(char *)malloc(size_string+4);//Initialising the string 
                   

                    vsnprintf(string,size_string,format,arguments_list);//Storing the outptut into the string 
                     va_end(arguments_list);//Deinitializing the List 

                     ESP_LOGI("NO TAG","Converted String is :  %s",string);

    free(string);
}

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: Using esp_log_set_vprintf() function

Postby kolban » Tue Jun 12, 2018 6:31 pm

I think to register your function as the logger you would then call:

Code: Select all

esp_log_set_vprintf(LOG_TO_STRING);
in your app code.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

User avatar
fly135
Posts: 599
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: Using esp_log_set_vprintf() function

Postby fly135 » Tue Jun 12, 2018 6:39 pm

Won't this cause a recursive loop?

Code: Select all

void LOG_TO_STRING(const char *format,...)
{
    ESP_LOGI("NO TAG","Call Accepted ");

papaluna
Posts: 44
Joined: Tue Jan 30, 2018 11:27 am

Re: Using esp_log_set_vprintf() function

Postby papaluna » Wed Jun 13, 2018 8:33 am

kartikkmann,

Maybe this example helps, this one writes to SPIFFS.

Code: Select all

    ESP_LOGI(TAG, "  ***Redirecting log output BACK to only UART0 (not to the SPIFFS log file anymore)");
    esp_log_set_vprintf(&vprintf);

Code: Select all

    ESP_LOGI(TAG, "***Redirecting log output to SPIFFS log file (also keep sending logs to UART0)");
    esp_log_set_vprintf(&_log_vprintf);

Code: Select all

// This function will be called by the ESP log library every time ESP_LOG needs to be performed.
//      @important Do NOT use the ESP_LOG* macro's in this function ELSE recursive loop and stack overflow! So use printf() instead for debug messages.
int _log_vprintf(const char *fmt, va_list args) {
    static bool static_fatal_error = false;
    static const uint32_t WRITE_CACHE_CYCLE = 5;
    static uint32_t counter_write = 0;
    int iresult;

    // #1 Write to SPIFFS
    if (_log_remote_fp == NULL) {
        printf("%s() ABORT. file handle _log_remote_fp is NULL\n", __FUNCTION__);
        return -1;
    }
    if (static_fatal_error == false) {
        iresult = vfprintf(_log_remote_fp, fmt, args);
        if (iresult < 0) {
            printf("%s() ABORT. failed vfprintf() -> disable future vfprintf(_log_remote_fp) \n", __FUNCTION__);
            // MARK FATAL
            static_fatal_error = true;
            return iresult;
        }

        // #2 Smart commit after x writes
        counter_write++;
        if (counter_write % WRITE_CACHE_CYCLE == 0) {
            /////printf("%s() fsync'ing log file on SPIFFS (WRITE_CACHE_CYCLE=%u)\n", WRITE_CACHE_CYCLE);
            fsync(fileno(_log_remote_fp));
        }
    }

    // #3 ALWAYS Write to stdout!
    return vprintf(fmt, args);
}
--
Paul.

User avatar
Vader_Mester
Posts: 228
Joined: Tue Dec 05, 2017 8:28 pm
Location: Hungary
Contact:

Re: Using esp_log_set_vprintf() function

Postby Vader_Mester » Thu Jun 14, 2018 6:52 am

kolban wrote:I think to register your function as the logger you would then call:

Code: Select all

esp_log_set_vprintf(LOG_TO_STRING);
in your app code.
I found this interesting. I'm not 100% sure I get how it works.
It basically sets my own function as the LOG output, so whenever I call any ESP_LOG function it will output using the function I set here?

Correct me if I wrong.
If this is the case, then I found what I was looking for :)
There are 2 types of programmer people: The Expert programmer and The Smart programmer

The Expert programmer easily writes any code from scratch.
The Smart programmer uses his google/github powers first ;)

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: Using esp_log_set_vprintf() function

Postby kolban » Thu Jun 14, 2018 2:13 pm

If we think that in C, a function is compiled piece of code that has an entry address ... then we can loosely say that a function is identified by the address in memory where it starts.

When we define a function ... for example:

Code: Select all

void x() {
   printf("Hello World");
}
Not only does this generate code, it "loosely" generates a variable called "x". The value of that variable is the address of the entry point to the function x().

We can declare a variable that can be explicitly a pointer to a function ... for example:

Code: Select all

void (*y)();
and then we can code:

Code: Select all

y = x;
y();
which says that "y" is a variable which holds a pointer to a function. We then assign y the value of x and then "call" the function that is pointed to by "y".


See also:

https://www.geeksforgeeks.org/function-pointer-in-c/
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

GeorgeFlorian1
Posts: 65
Joined: Thu Jan 31, 2019 2:32 pm

Re: Using esp_log_set_vprintf() function

Postby GeorgeFlorian1 » Tue Mar 12, 2019 3:06 pm

papaluna wrote:
Wed Jun 13, 2018 8:33 am
kartikkmann,

Maybe this example helps, this one writes to SPIFFS.

Code: Select all

    ESP_LOGI(TAG, "  ***Redirecting log output BACK to only UART0 (not to the SPIFFS log file anymore)");
    esp_log_set_vprintf(&vprintf);

Code: Select all

    ESP_LOGI(TAG, "***Redirecting log output to SPIFFS log file (also keep sending logs to UART0)");
    esp_log_set_vprintf(&_log_vprintf);

Code: Select all

// This function will be called by the ESP log library every time ESP_LOG needs to be performed.
//      @important Do NOT use the ESP_LOG* macro's in this function ELSE recursive loop and stack overflow! So use printf() instead for debug messages.
int _log_vprintf(const char *fmt, va_list args) {
    static bool static_fatal_error = false;
    static const uint32_t WRITE_CACHE_CYCLE = 5;
    static uint32_t counter_write = 0;
    int iresult;

    // #1 Write to SPIFFS
    if (_log_remote_fp == NULL) {
        printf("%s() ABORT. file handle _log_remote_fp is NULL\n", __FUNCTION__);
        return -1;
    }
    if (static_fatal_error == false) {
        iresult = vfprintf(_log_remote_fp, fmt, args);
        if (iresult < 0) {
            printf("%s() ABORT. failed vfprintf() -> disable future vfprintf(_log_remote_fp) \n", __FUNCTION__);
            // MARK FATAL
            static_fatal_error = true;
            return iresult;
        }

        // #2 Smart commit after x writes
        counter_write++;
        if (counter_write % WRITE_CACHE_CYCLE == 0) {
            /////printf("%s() fsync'ing log file on SPIFFS (WRITE_CACHE_CYCLE=%u)\n", WRITE_CACHE_CYCLE);
            fsync(fileno(_log_remote_fp));
        }
    }

    // #3 ALWAYS Write to stdout!
    return vprintf(fmt, args);
}
How does this work ?

I've tried using it inside my code but _log_remote_fp and fileno are undefined.

Also, how many logs can the file hold up ? When does it start deleting old logs ?

Deouss
Posts: 382
Joined: Tue Mar 20, 2018 11:36 am

Re: Using esp_log_set_vprintf() function

Postby Deouss » Tue Mar 12, 2019 3:15 pm

Look at my example - I used esp_log_set_vprintf() function to block incoming logs to com port on PC.

viewtopic.php?f=17&p=39926#p39926

I found out that replacing all log func with my own still allows to use printf() except if you don't save the log messages I guess they are lost.

GeorgeFlorian1
Posts: 65
Joined: Thu Jan 31, 2019 2:32 pm

Re: Using esp_log_set_vprintf() function

Postby GeorgeFlorian1 » Wed Mar 13, 2019 9:23 am

Deouss wrote:
Tue Mar 12, 2019 3:15 pm
Look at my example - I used esp_log_set_vprintf() function to block incoming logs to com port on PC.

viewtopic.php?f=17&p=39926#p39926

I found out that replacing all log func with my own still allows to use printf() except if you don't save the log messages I guess they are lost.
Hello ! Thank you for your reply !

Your code is still too complex for me. I don't quite understand it yet. I would love a breakdown of how you've replaced the log functions and with what you've replaced them.

I've yet to read about _log_vprintf.

This is my post: viewtopic.php?f=19&t=9666
It would be great to have you take a look at it.
Thank you !

Deouss
Posts: 382
Joined: Tue Mar 20, 2018 11:36 am

Re: Using esp_log_set_vprintf() function

Postby Deouss » Wed Mar 13, 2019 11:58 am

What I've done is quite simple. I substituted printf() function for any logging using esp_log_set_vprintf()
My procedute simply returns 0

Code: Select all

int printf_func(const char* str, va_list vl)
{
    return 0;
}
It should return something like printf(str,vl) I assume
But any printf directs data to uart0 which may break the transmission for other expected data.
I don't think you should call vprintf - only printf - I just assume but never tried it.
I'd say vprintf acts as logging procedure that discards buffers and log queues after some time.
You must save or hold messages by your own procedures

Who is online

Users browsing this forum: No registered users and 11 guests