One quite effective approach to handling log string literals in a C/C++ environment is to allocate them to a distinct linker section, which is stripped from the final binary.
The log statements are defined in such a way as to compile to pointers to these strings, and it's the pointer values themselves (or offsets from a base address if this saves space) that are stored in the log.
The stripped strings section can then be used to reconstruct the full log string from the values in the abbreviated log.
Naturally, the specific means of achieving this varies between platforms, toolchains, etc, and is complicated by the inclusion of non-literal data in the log entries - but all quite feasible in an embedded context.