C-Core SDK 7.0.0 migration guide
This guide summarizes the differences between 6.X.X versions and 7.0.0 and shows how to migrate to C-Core SDK 7.0.0.
C-Core SDK version 7.0.0 makes DNS server configuration per-context, replaces the logging subsystem with an advanced pluggable logger architecture, and adds logging methods to the C++ wrapper class. This applies to all C-Core SDK flavors: C-Core, POSIX C, POSIX C++, Windows C, Windows C++, FreeRTOS, and Mbed.
Earlier migration guides
If you are upgrading from a version before 6.0.0, read the C-Core SDK 6.0.0 migration guide first.
What has changed
See the major differences between versions:
| Feature | C-Core SDK 6.X.X | C-Core SDK 7.0.0 |
|---|---|---|
| DNS server functions | Global (no context parameter) | Per-context (pubnub_t* pb added as first parameter) |
| Logging header | #include "core/pubnub_log.h" | #include "core/pubnub_logger.h" |
| Logging functions | PUBNUB_LOG_PRINTF(...) macros | pubnub_log_text(), pubnub_log_text_formatted(), pubnub_log_object(), pubnub_log_error() |
| Log level enum | Sequential: NONE=0, ERROR=1, ... TRACE=5 | Bitmask: TRACE=1, DEBUG=2, INFO=4, WARNING=8, ERROR=16, NONE=32 |
| Compile-time level macro | PUBNUB_LOG_LEVEL | PUBNUB_LOG_MIN_LEVEL |
| Custom output / runtime callback | Override PUBNUB_LOG_PRINTF macro or pubnub_set_log_callback(fn) | Register custom pubnub_logger_t with pubnub_logger_add(pb, logger) |
| WATCH_* macros | WATCH_INT(x), WATCH_STR(x), etc. | Removed. Use structured logging (pubnub_log_object) |
| C++ wrapper (POSIX C++, Windows C++) | No logging methods | New methods: logger_add, logger_remove, set_log_level, log_text, log_object, log_error |
| Feature flags | Always compiled in | PUBNUB_USE_LOGGER, PUBNUB_USE_DEFAULT_LOGGER |
Breaking changes
| Change | Platforms affected |
|---|---|
| DNS server API | All (C-Core, POSIX C, POSIX C++, Windows C, Windows C++, FreeRTOS, Mbed) |
| Logging subsystem | All |
| Log level changes | All |
| Build configuration | All |
| C++ wrapper | POSIX C++, Windows C++ |
| Platform-specific default loggers | POSIX C, POSIX C++, Windows C, Windows C++, FreeRTOS, Microchip Harmony |
DNS server API
Applies to: All platforms
Starting with 7.0.0, all 14 DNS server functions in core/pubnub_dns_servers.h require a pubnub_t* context as their first parameter. Previously, these functions operated on global state. Now DNS server configuration is per-context.
This change affects all functions guarded by PUBNUB_SET_DNS_SERVERS.
IPv4 functions
| Function | C-Core SDK 6.X.X | C-Core SDK 7.0.0 |
|---|---|---|
pubnub_dns_set_primary_server_ipv4 | (struct pubnub_ipv4_address ipv4) | (pubnub_t* pb, struct pubnub_ipv4_address ipv4) |
pubnub_dns_set_secondary_server_ipv4 | (struct pubnub_ipv4_address ipv4) | (pubnub_t* pb, struct pubnub_ipv4_address ipv4) |
pubnub_dns_set_primary_server_ipv4_str | (char const* ipv4_str) | (pubnub_t* pb, char const* ipv4_str) |
pubnub_dns_set_secondary_server_ipv4_str | (char const* ipv4_str) | (pubnub_t* pb, char const* ipv4_str) |
pubnub_get_dns_primary_server_ipv4 | (struct pubnub_ipv4_address* o_ipv4) | (pubnub_t* pb, struct pubnub_ipv4_address* o_ipv4) |
pubnub_get_dns_secondary_server_ipv4 | (struct pubnub_ipv4_address* o_ipv4) | (pubnub_t* pb, struct pubnub_ipv4_address* o_ipv4) |
pubnub_dns_read_system_servers_ipv4 | (struct pubnub_ipv4_address* o_ipv4, size_t n) | (pubnub_t* pb, struct pubnub_ipv4_address* o_ipv4, size_t n) |
IPv6 functions (require PUBNUB_USE_IPV6)
| Function | C-Core SDK 6.X.X | C-Core SDK 7.0.0 |
|---|---|---|
pubnub_dns_set_primary_server_ipv6 | (struct pubnub_ipv6_address ipv6) | (pubnub_t* pb, struct pubnub_ipv6_address ipv6) |
pubnub_dns_set_secondary_server_ipv6 | (struct pubnub_ipv6_address ipv6) | (pubnub_t* pb, struct pubnub_ipv6_address ipv6) |
pubnub_dns_set_primary_server_ipv6_str | (char const* ipv6_str) | (pubnub_t* pb, char const* ipv6_str) |
pubnub_dns_set_secondary_server_ipv6_str | (char const* ipv6_str) | (pubnub_t* pb, char const* ipv6_str) |
pubnub_get_dns_primary_server_ipv6 | (struct pubnub_ipv6_address* o_ipv6) | (pubnub_t* pb, struct pubnub_ipv6_address* o_ipv6) |
pubnub_get_dns_secondary_server_ipv6 | (struct pubnub_ipv6_address* o_ipv6) | (pubnub_t* pb, struct pubnub_ipv6_address* o_ipv6) |
pubnub_dns_read_system_servers_ipv6 | N/A (new in 6.2.0) | (pubnub_t* pb, struct pubnub_ipv6_address* o_ipv6, size_t n) |
Fallback macros
The fallback macros (when PUBNUB_SET_DNS_SERVERS is disabled) also gained the pb parameter, so code using the macro forms also needs updating.
- Before (6.X.X)
- After (7.0.0)
#include "core/pubnub_dns_servers.h"
/* DNS servers were global — no context needed */
struct pubnub_ipv4_address dns = {{8, 8, 8, 8}};
pubnub_dns_set_primary_server_ipv4(dns);
pubnub_dns_set_secondary_server_ipv4_str("8.8.4.4");
/* Read system DNS servers */
struct pubnub_ipv4_address servers[4];
int count = pubnub_dns_read_system_servers_ipv4(servers, 4);
#include "core/pubnub_dns_servers.h"
/* DNS servers are now per-context — pass pubnub_t* as first argument */
pubnub_t* pb = pubnub_alloc();
pubnub_init(pb, "pub-key", "sub-key");
struct pubnub_ipv4_address dns = {{8, 8, 8, 8}};
pubnub_dns_set_primary_server_ipv4(pb, dns);
pubnub_dns_set_secondary_server_ipv4_str(pb, "8.8.4.4");
/* Read system DNS servers — also requires context now */
struct pubnub_ipv4_address servers[4];
int count = pubnub_dns_read_system_servers_ipv4(pb, servers, 4);
/* IPv6 system DNS discovery (new in 6.2.0, requires PUBNUB_USE_IPV6) */
show all 17 linesLogging subsystem
Applies to: All platforms
Starting with 7.0.0, the SDK replaces its legacy logging subsystem (core/pubnub_log.h) with a new advanced logging system (core/pubnub_logger.h). The new system introduces per-context logging, multiple simultaneous logger support, structured data logging, network request/response logging, and runtime log level control.
The files core/pubnub_log.h and core/pubnub_log.c are deleted. Any direct references to them cause compilation errors.
Removed APIs
The following are deleted and cause compilation errors if referenced:
| Removed API | Replacement |
|---|---|
#include "core/pubnub_log.h" | #include "core/pubnub_logger.h" |
PUBNUB_LOG_PRINTF(...) | pubnub_log_text_formatted(pb, level, location, format, ...) |
PUBNUB_LOG_ERROR(...), PUBNUB_LOG_WARNING(...), PUBNUB_LOG_INFO(...), PUBNUB_LOG_DEBUG(...), PUBNUB_LOG_TRACE(...) | pubnub_log_text_formatted(pb, level, location, format, ...) |
WATCH_INT(x), WATCH_STR(x), WATCH_ENUM(x), WATCH_ULONG(x) | pubnub_log_object(pb, level, location, value, details) |
pubnub_set_log_callback(fn) / PUBNUB_USE_LOG_CALLBACK | Create a custom pubnub_logger_t and register with pubnub_logger_add(pb, logger). PUBNUB_USE_LOGGER controls whether the logging subsystem is compiled in. |
PUBNUB_LOG_LEVEL (compile-time macro) | PUBNUB_LOG_MIN_LEVEL |
New logging public API
All functions are part of the public C API in core/pubnub_logger.h.
Logger lifecycle
| Function | Description |
|---|---|
pubnub_logger_alloc(vtable, user_data) | Create a custom logger with a vtable and optional user data. Returns NULL on failure. |
pubnub_logger_user_data(logger) | Retrieve user data associated with a custom logger. |
pubnub_logger_free(logger) | Free a custom logger. Calls the logger's destroy() callback if provided. Sets *logger to NULL. |
Logger registration
| Function | Description |
|---|---|
pubnub_logger_add(pb, logger) | Register a custom logger with a PubNub context. Multiple loggers can be registered. Returns 0 on success. |
pubnub_logger_remove(pb, logger) | Unregister a custom logger. Caller must still call pubnub_logger_free(). Returns 0 on success. |
pubnub_logger_remove_all(pb) | Unregister all custom loggers. Caller must free each logger individually. |
Log level control
| Function | Description |
|---|---|
pubnub_logger_set_log_level(pb, level) | Set the minimum log level. Messages below this level are not dispatched. |
pubnub_logger_log_level(pb) | Get the current minimum log level. Default: PUBNUB_LOG_LEVEL_DEBUG. |
Logging functions
| Function | Description |
|---|---|
pubnub_log_text(pb, level, location, message) | Log a plain text message. |
pubnub_log_text_formatted(pb, level, location, format, ...) | Log a formatted text message (printf-style). |
pubnub_log_object(pb, level, location, value, details) | Log a structured object/data. |
pubnub_log_error(pb, location, error_code, error_message, details) | Log an error. Level is always PUBNUB_LOG_LEVEL_ERROR. |
Replace logging macros
- Before (6.X.X)
- After (7.0.0)
#include "core/pubnub_log.h"
PUBNUB_LOG_ERROR("Failed to publish: %d", result);
PUBNUB_LOG_DEBUG("Channel: %s", channel);
#include "core/pubnub_logger.h"
pubnub_log_text_formatted(pb, PUBNUB_LOG_LEVEL_ERROR, "app.c:42",
"Failed to publish: %d", result);
pubnub_log_text_formatted(pb, PUBNUB_LOG_LEVEL_DEBUG, "app.c:50",
"Channel: %s", channel);
/* Or use pubnub_log_text() for non-formatted messages */
pubnub_log_text(pb, PUBNUB_LOG_LEVEL_INFO, "app.c:60",
"Subscription connected");
Replace PUBNUB_LOG_PRINTF override
- Before (6.X.X)
- After (7.0.0)
/* Compile-time macro override */
#define PUBNUB_LOG_PRINTF(...) my_log_func(__VA_ARGS__)
#include "core/pubnub_logger.h"
/* Runtime custom logger registration */
static void my_logger_handler(const pubnub_logger_t* logger,
const pubnub_log_message_t* message) {
if (message->message_type == PUBNUB_LOG_MESSAGE_TYPE_TEXT) {
const pubnub_log_message_text_t* text =
(const pubnub_log_message_text_t*)message;
my_log_func("[%s] %s\n", message->pubnub_id, text->message);
}
}
static const struct pubnub_logger_interface my_vtable = {
.trace = my_logger_handler,
.debug = my_logger_handler,
show all 24 linesReplace pubnub_set_log_callback
- Before (6.X.X)
- After (7.0.0)
void my_callback(enum pubnub_log_level level, const char* message) {
fprintf(log_file, "[%d] %s", level, message);
}
pubnub_set_log_callback(my_callback);
#include "core/pubnub_logger.h"
typedef struct {
FILE* file;
} my_context;
static void my_handler(const pubnub_logger_t* logger,
const pubnub_log_message_t* message) {
my_context* ctx = (my_context*)pubnub_logger_user_data(
(pubnub_logger_t*)logger);
if (message->message_type == PUBNUB_LOG_MESSAGE_TYPE_TEXT) {
const pubnub_log_message_text_t* text =
(const pubnub_log_message_text_t*)message;
fprintf(ctx->file, "[%s] %s\n", message->pubnub_id, text->message);
}
show all 33 linesReplace WATCH_* macros
- Before (6.X.X)
- After (7.0.0)
WATCH_INT(result);
WATCH_STR(channel);
#include "core/pubnub_log_value.h"
pubnub_log_value_t params = pubnub_log_value_map_init();
PUBNUB_LOG_MAP_SET_NUMBER(¶ms, result)
PUBNUB_LOG_MAP_SET_STRING(¶ms, channel)
pubnub_log_object(pb, PUBNUB_LOG_LEVEL_DEBUG, "app.c:42",
¶ms, "debug values");
Structured logging scope
All pubnub_log_value_t structures and their string pointers live on the stack. All values, containers, and the log call must be in the same scope. If a value goes out of scope before the logging function reads it, you get undefined behavior.
Log level changes
Applies to: All platforms
The log level enum changed from sequential integers with reversed ordering to bitmask powers of 2 with natural ordering.
- Before (6.X.X)
- After (7.0.0)
/* Sequential integers, REVERSED ordering (NONE is lowest) */
enum pubnub_log_level {
PUBNUB_LOG_LEVEL_NONE = 0, /* Logging disabled */
PUBNUB_LOG_LEVEL_ERROR = 1,
PUBNUB_LOG_LEVEL_WARNING = 2,
PUBNUB_LOG_LEVEL_INFO = 3,
PUBNUB_LOG_LEVEL_DEBUG = 4,
PUBNUB_LOG_LEVEL_TRACE = 5 /* Most verbose */
};
/* Filter: if (level <= PUBNUB_LOG_LEVEL) → emit */
/* Bitmask powers of 2, NATURAL ordering (TRACE is lowest) */
enum pubnub_log_level {
PUBNUB_LOG_LEVEL_TRACE = (1 << 0), /* 1 — Most verbose */
PUBNUB_LOG_LEVEL_DEBUG = (1 << 1), /* 2 */
PUBNUB_LOG_LEVEL_INFO = (1 << 2), /* 4 */
PUBNUB_LOG_LEVEL_WARNING = (1 << 3), /* 8 */
PUBNUB_LOG_LEVEL_ERROR = (1 << 4), /* 16 */
PUBNUB_LOG_LEVEL_NONE = (1 << 5), /* 32 — Logging disabled */
};
/* Filter: if (level >= minimum_level) → emit */
Comparison direction changed
If your code compares log level values numerically (for example, if (level <= PUBNUB_LOG_LEVEL_INFO)), the comparison direction has changed. In the old system NONE < ERROR < TRACE. In the new system TRACE < DEBUG < INFO < WARNING < ERROR < NONE.
Build configuration
Applies to: All platforms
Compile-time log level stripping
The compile-time macro for log level filtering has changed.
- Before (6.X.X)
- After (7.0.0)
# Old build flag
-DPUBNUB_LOG_LEVEL=PUBNUB_LOG_LEVEL_WARNING
# New build flag — uses short level names
-DPUBNUB_LOG_MIN_LEVEL=WARNING
# Other examples:
-DPUBNUB_LOG_MIN_LEVEL=TRACE # Maximum verbosity
-DPUBNUB_LOG_MIN_LEVEL=DEBUG # Default
-DPUBNUB_LOG_MIN_LEVEL=NONE # Disable all logging at compile time
C++ wrapper
Applies to: POSIX C++, Windows C++
New methods are added to the pubnub::context class in cpp/pubnub_common.hpp, guarded by #if PUBNUB_USE_LOGGER. These delegate directly to the C public API functions.
| Method | Description |
|---|---|
logger_add(pubnub_logger_t* logger) | Register a custom logger. Returns 0 on success. |
logger_remove(pubnub_logger_t* logger) | Unregister a custom logger. Returns 0 on success. |
logger_remove_all() | Unregister all custom loggers. |
set_log_level(pubnub_log_level level) | Set minimum log level for this context. |
log_level() | Get current minimum log level. Default: PUBNUB_LOG_LEVEL_DEBUG. |
log_text(pubnub_log_level level, char const* location, char const* message) | Log a plain text message. |
log_text(pubnub_log_level level, char const* location, std::string const& message) | Log a text message from std::string. |
log_object(pubnub_log_level level, char const* location, pubnub_log_value_t const* message, char const* details) | Log a structured object with optional details. |
log_error(char const* location, int error_code, char const* error_message, char const* details) | Log an error (always PUBNUB_LOG_LEVEL_ERROR). |
Basic C++ logging
#include "pubnub_common.hpp"
pubnub::context ctx("demo", "demo");
/* Log simple text messages */
ctx.log_text(PUBNUB_LOG_LEVEL_INFO,
"main.cpp:10",
"PubNub context initialized");
/* Log with std::string */
std::string msg = "Subscribing to channel: " + channel_name;
ctx.log_text(PUBNUB_LOG_LEVEL_DEBUG, "main.cpp:15", msg);
/* Log an error */
ctx.log_error("main.cpp:25", -1, "Connection failed", "Timeout after 30s");
Custom logger in C++
#include "pubnub_common.hpp"
#include "core/pubnub_logger.h"
static void my_info_handler(const pubnub_logger_t* logger,
const pubnub_log_message_t* message) {
if (message->message_type == PUBNUB_LOG_MESSAGE_TYPE_TEXT) {
const pubnub_log_message_text_t* text =
(const pubnub_log_message_text_t*)message;
std::cout << "[INFO] " << text->message << std::endl;
}
}
static const struct pubnub_logger_interface my_vtable = {
.trace = NULL,
.debug = NULL,
show all 37 linesFeature flags
Two new macros control the logging subsystem. Both are defined in each platform's pubnub_config.h and default to 1 (enabled).
| Macro | Default | Description |
|---|---|---|
PUBNUB_USE_LOGGER | 1 | Enable/disable the entire logging subsystem. When 0, all logging macros become no-ops and logger API functions are not compiled. |
PUBNUB_USE_DEFAULT_LOGGER | 1 | Enable/disable the built-in default platform logger. When 0, no logger is registered automatically — you must register your own via pubnub_logger_add(). |
New source files
If you maintain custom build scripts or Makefiles, add the following files.
Always required when PUBNUB_USE_LOGGER=1
| File | Purpose |
|---|---|
core/pubnub_logger.c | Public logger API implementation |
core/pbcc_logger_manager.c | Logger manager (dispatches to registered loggers) |
core/pubnub_log_value.c | Structured log value types |
Required only when PUBNUB_USE_DEFAULT_LOGGER=1
Add exactly one platform-specific default logger:
| Platform | File |
|---|---|
| POSIX / Windows | core/pubnub_stdio_logger.c |
| FreeRTOS | freertos/pubnub_freertos_logger.c |
| Microchip Harmony | microchip_harmony/pubnub_harmony_logger.c |
Platform-specific default loggers
Applies to: All platforms (each platform uses its own logger implementation)
When PUBNUB_USE_DEFAULT_LOGGER is 1 (default), each new PubNub context automatically registers a platform-appropriate logger.
| Platform | File | Output | Timestamps |
|---|---|---|---|
| POSIX / Windows | core/pubnub_stdio_logger.c | fprintf(stdout) for TRACE/DEBUG/INFO/WARN; fprintf(stderr) for ERROR | ISO 8601 with milliseconds |
| FreeRTOS | freertos/pubnub_freertos_logger.c | printf() for all levels | ISO 8601 when wall-clock available; xTaskGetTickCount() tick-based fallback |
| Microchip Harmony | microchip_harmony/pubnub_harmony_logger.c | SYS_CONSOLE_PRINT() for all levels | Raw Unix timestamp; SYS_TMR_TickCountGet() fallback |
Output format example (POSIX/Windows)
2026-03-03T10:11:31.456Z PubNub-a1b2c3d4 DEBUG core/pubnub_coreapi.c:123 Publishing to channel 'my-channel'
Migration steps
To migrate to C-Core SDK 7.0.0:
-
Update DNS server function calls. Add
pubnub_t*context as the first argument to all DNS server functions:Action Description Add pbas the first argument to allpubnub_dns_set_*,pubnub_get_dns_*, andpubnub_dns_read_system_servers_*callsAll 14 DNS functions (7 IPv4 + 7 IPv6) now require a pubnub_t*context. This also applies to fallback macros whenPUBNUB_SET_DNS_SERVERSis disabled. -
Update logging includes:
Action Description Replace #include "core/pubnub_log.h"with#include "core/pubnub_logger.h"The old header file is deleted. For structured log values and convenience macros, also include core/pubnub_log_value.h. -
Replace old logging macros with public API functions:
Action Description Replace PUBNUB_LOG_ERROR(...),PUBNUB_LOG_WARNING(...), etc. withpubnub_log_text_formatted()The new function requires a pubnub_t*context, a log level, a location string, and a format string with arguments.Replace pubnub_log_text()for non-formatted messagesUse when you don't need printf-style formatting. -
Replace
PUBNUB_LOG_PRINTFoverride with runtime custom logger registration:Action Description Remove #define PUBNUB_LOG_PRINTF(...)overridesCreate a pubnub_logger_interfacevtable and register a custom logger at runtime usingpubnub_logger_alloc()andpubnub_logger_add(). -
Replace
pubnub_set_log_callbackwith custom logger:Action Description Remove pubnub_set_log_callback()callsCreate a custom logger with a vtable and register it with pubnub_logger_add(). Usepubnub_logger_user_data()to access custom state from within callbacks. -
Replace
WATCH_*macros with structured logging:Action Description Replace WATCH_INT(x),WATCH_STR(x), etc.Use pubnub_log_value_ttypes andpubnub_log_object(). Convenience macros likePUBNUB_LOG_MAP_SET_NUMBERandPUBNUB_LOG_MAP_SET_STRINGare available incore/pubnub_log_value.h. -
Update compile-time level configuration:
Action Description Replace -DPUBNUB_LOG_LEVEL=PUBNUB_LOG_LEVEL_WARNINGwith-DPUBNUB_LOG_MIN_LEVEL=WARNINGThe new macro uses short level names: TRACE,DEBUG,INFO,WARNING,ERROR,NONE. -
Update runtime level filtering:
Action Description Use pubnub_logger_set_log_level(pb, level)to control runtime filteringThe old system only supported compile-time filtering. The new system supports both compile-time stripping and runtime filtering per context. -
(C++ only) Use new context methods for logging:
Action Description Use ctx.logger_add(),ctx.set_log_level(),ctx.log_text(), etc.The pubnub::contextclass inpubnub_common.hppprovides C++ wrappers for all logging API functions. No include changes needed —core/pubnub_logger.his automatically included whenPUBNUB_USE_LOGGERis enabled. -
Update build scripts. Add new source files if you maintain custom build scripts:
Action Description Add core/pubnub_logger.c,core/pbcc_logger_manager.c,core/pubnub_log_value.cAlways required when PUBNUB_USE_LOGGER=1(default).Add exactly one platform-specific default logger file Required when PUBNUB_USE_DEFAULT_LOGGER=1(default). See New source files for platform-specific file names. -
Clean up custom loggers before freeing the PubNub context:
Action Description Call pubnub_logger_remove(pb, logger)andpubnub_logger_free(&logger)beforepubnub_free(pb)Custom loggers must be unregistered and freed before the context is freed. pubnub_logger_free()calls the logger'sdestroy()callback if provided. -
Test your application. Pay special attention to DNS configuration, logging output, and any custom logging integrations.
Additional resources
For API details, see the C-Core SDK documentation. For the full logging reference, see Logging. For questions or issues, contact PubNub support.