Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP log backend #486

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/esp_idf/hello/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_GOLIOTH_AUTO_LOG_TO_CLOUD=1
CONFIG_GOLIOTH_COAP_REQUEST_QUEUE_MAX_ITEMS=20

# Uncomment to automatically upload ESP_LOGX statements to Golioth Logs service
# CONFIG_GOLIOTH_ESPLOG_AUTO_LOG_TO_CLOUD=1

# To enable hardcode credentials, set to y
CONFIG_GOLIOTH_SAMPLE_HARDCODED_CREDENTIALS=n

Expand Down
1 change: 1 addition & 0 deletions port/esp_idf/components/golioth_sdk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ idf_component_register(
SRCS
"${sdk_port}/freertos/golioth_sys_freertos.c"
"${sdk_port}/esp_idf/fw_update_esp_idf.c"
"${sdk_port}/esp_idf/golioth_log_esp_idf.c"
"${sdk_src}/golioth_status.c"
"${sdk_src}/coap_client.c"
"${sdk_src}/coap_client_libcoap.c"
Expand Down
16 changes: 15 additions & 1 deletion port/esp_idf/components/golioth_sdk/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,18 @@ menu "Golioth SDK Configuration"

rsource '../../../../src/Kconfig'

endmenu # Golioth SDK Configuration
config GOLIOTH_ESPLOG_AUTO_LOG_TO_CLOUD
int "Option to send logs to cloud"
default 0
help
If set to 1, ESP_LOGX statements will automatically upload to
Golioth cloud

config GOLIOTH_ESPLOG_MAX_BUFF_SIZE
int "Maximum log buffer size allowed for ESP log backend"
default 128
help
Maximum log buffer size allowed for ESP log backend to be sent to
Golioth cloud

endmenu # Golioth SDK Configuration
107 changes: 107 additions & 0 deletions port/esp_idf/golioth_log_esp_idf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2024 Golioth, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <golioth/golioth_debug.h>
#include "golioth_log_esp_idf.h"
#include <golioth/log.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "string.h"

static vprintf_like_t original_log_func;

static struct golioth_client *_client = NULL;

static int golioth_log_espidf(const char *format, va_list args)
{
if (!CONFIG_GOLIOTH_AUTO_LOG_TO_CLOUD)
{
return -1;
}

if (!_client)
{
return -1;
}

// The 7th character in the format tells the log level as
// E = Error, W = Warning, I = info, D = Debug, V = Verbose
char log_level = format[7];

// Temporary buffer to store the message
char msg_buffer[CONFIG_GOLIOTH_ESPLOG_MAX_BUFF_SIZE] = {0};
vsnprintf(msg_buffer, CONFIG_GOLIOTH_ESPLOG_MAX_BUFF_SIZE, format, args);
printf("%s", msg_buffer);

// The formatted string looks like this: "[0;32mI (%lu) %s: Actual Log %d [0m"
// The start and end characters convey formatting and color information
// This information should not be sent to the cloud.
// Insert a null char 5 places behind to remove ESC[0m at the end of the string
// Here strlen(msg_buffer) - 5 will not go out of bounds because the format will
// always have at least 5 characters, even with an empty string
msg_buffer[strlen(msg_buffer) - 5] = '\0';

// Find ) and : characters in the string for extracting tag
char tag_str[64] = {0};
const char *tag = strchr(msg_buffer, ')');
const char *msg_str = strchr(msg_buffer, ':');
if (tag != NULL && msg_str != NULL)
{
tag = tag + 1; // Skip space after )
strncpy(tag_str, tag, msg_str - tag);
// Ignore everything before ':'
msg_str = msg_str + 2; // Skip ':' and space
}

// Log to Golioth asynchronously.
switch (log_level)
{
case 'E':
golioth_log_error_async(_client, tag_str, msg_str, NULL, NULL);
break;
case 'W':
golioth_log_warn_async(_client, tag_str, msg_str, NULL, NULL);
break;
case 'I':
golioth_log_info_async(_client, tag_str, msg_str, NULL, NULL);
break;
case 'V': // fallthrough
case 'D':
golioth_log_debug_async(_client, tag_str, msg_str, NULL, NULL);
break;
default:
break;
}

return 0;
}

vprintf_like_t golioth_log_set_esp_vprintf(void *client)
{
_client = client;
return esp_log_set_vprintf(golioth_log_espidf);
}

vprintf_like_t golioth_log_reset_esp_vprintf(vprintf_like_t original_log_func)
{
return esp_log_set_vprintf(original_log_func);
}

void golioth_sys_client_connected(void *client)
{
if (CONFIG_GOLIOTH_ESPLOG_AUTO_LOG_TO_CLOUD == 1)
{
original_log_func = golioth_log_set_esp_vprintf(client);
}
}

void golioth_sys_client_disconnected(void *client)
{
if (CONFIG_GOLIOTH_ESPLOG_AUTO_LOG_TO_CLOUD == 1)
{
golioth_log_reset_esp_vprintf(original_log_func);
}
}
11 changes: 11 additions & 0 deletions port/esp_idf/golioth_log_esp_idf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2024 Golioth, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include <golioth/golioth_sys.h>

vprintf_like_t golioth_log_set_esp_vprintf(void *client);
vprintf_like_t golioth_log_reset_esp_vprintf(vprintf_like_t original_log_func);
61 changes: 32 additions & 29 deletions port/esp_idf/golioth_port_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,36 @@
} \
} while (0)

// TODO - should we hook into the ESP logging backend via esp_log_set_vprintf?
// This would enable all logs to be sent to Golioth (not just the GLTH_LOGX logs).

#define GLTH_LOGX(COLOR, LEVEL, LEVEL_STR, TAG, ...) \
do { \
if ((LEVEL) <= golioth_debug_get_log_level()) { \
uint64_t now_ms = golioth_sys_now_ms(); \
switch (LEVEL) { \
case GOLIOTH_DEBUG_LOG_LEVEL_ERROR: \
ESP_LOGE(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_WARN: \
ESP_LOGW(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_INFO: \
ESP_LOGI(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_DEBUG: \
ESP_LOGD(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_VERBOSE: \
ESP_LOGV(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_NONE: \
default: \
break; \
} \
golioth_debug_printf(now_ms, LEVEL, TAG, __VA_ARGS__); \
} \
#define GLTH_LOGX(COLOR, LEVEL, LEVEL_STR, TAG, ...) \
do \
{ \
if ((LEVEL) <= golioth_debug_get_log_level()) \
{ \
switch (LEVEL) \
{ \
case GOLIOTH_DEBUG_LOG_LEVEL_ERROR: \
ESP_LOGE(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_WARN: \
ESP_LOGW(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_INFO: \
ESP_LOGI(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_DEBUG: \
ESP_LOGD(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_VERBOSE: \
ESP_LOGV(TAG, __VA_ARGS__); \
break; \
case GOLIOTH_DEBUG_LOG_LEVEL_NONE: \
default: \
break; \
} \
if (!CONFIG_GOLIOTH_ESPLOG_AUTO_LOG_TO_CLOUD) \
{ \
uint64_t now_ms = golioth_sys_now_ms(); \
golioth_debug_printf(now_ms, LEVEL, TAG, __VA_ARGS__); \
} \
} \
} while (0)
4 changes: 0 additions & 4 deletions port/freertos/golioth_sys_freertos.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,3 @@ void golioth_sys_thread_destroy(golioth_sys_thread_t thread) {
/*--------------------------------------------------
* Misc
*------------------------------------------------*/

void golioth_sys_client_connected(void* client) {}

void golioth_sys_client_disconnected(void* client) {}
10 changes: 10 additions & 0 deletions port/modus_toolbox/golioth_sys_modus.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright (c) 2024 Golioth, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <golioth/golioth_sys.h>

void golioth_sys_client_connected(void *client) {}

void golioth_sys_client_disconnected(void *client) {}