Skip to content

Examples ThreadContext

Eduard Mishkurov edited this page Apr 24, 2026 · 7 revisions

ThreadContext example

ThreadContext

This example shows thread-local logging context helpers.

What it demonstrates

  • Setting a default channel for the current thread
  • Setting a default override for the current thread
  • Routing logs from code that does not know anything about channels
  • Mixing explicit-channel and channel-less logging

Notes

  • Thread context is convenient for libraries and worker threads where passing channel parameters through every function is undesirable.

Console output

2026-04-24 21:26:29:736   Worker 1: explicit channel
2026-04-24 21:26:29:736   Worker 0: explicit channel
2026-04-24 21:26:29:736   Worker 1: printf style
2026-04-24 21:26:29:736   Worker 0: printf style
2026-04-24 21:26:29:736   Worker 0: std::format style
2026-04-24 21:26:29:736   Worker 1: std::format style
2026-04-24 21:26:29:736   LibraryWork: start
2026-04-24 21:26:29:736 W LibraryWork warn: start
2026-04-24 21:26:29:736   LibraryWork: start
2026-04-24 21:26:29:736 W LibraryWork warn: start
2026-04-24 21:26:29:736   Worker 2: explicit channel
2026-04-24 21:26:29:736   Worker 2: printf style
2026-04-24 21:26:29:736   Worker 2: std::format style
2026-04-24 21:26:29:736   LibraryWork: start
2026-04-24 21:26:29:736 W LibraryWork warn: start
2026-04-24 21:26:29:736   Worker 3: explicit channel
2026-04-24 21:26:29:736   Worker 3: printf style
2026-04-24 21:26:29:736   Worker 3: std::format style
2026-04-24 21:26:29:736   LibraryWork: start
2026-04-24 21:26:29:736 W LibraryWork warn: start

Source code

Sources

Repository folder: examples/ThreadContext

ThreadContext.cpp

Open in repository

#include <Logme/Logme.h>

#include <thread>
#include <vector>

#if defined(_MSC_VER)
#pragma warning(disable: 4840)
#endif

static void LibraryWork(const char* tag)
{
  // This code does not know anything about channels.
  // If the caller sets LogmeThreadChannel, the messages will be routed there.
  LogmeI() << "LibraryWork: " << tag;
  LogmeW("LibraryWork warn: %s", tag);
}

static void Worker(int workerId)
{
  // Create a channel with an auto-generated name.
  // Using ChannelPtr is faster in multithreaded systems because it avoids name lookup.
  auto ch = Logme::Instance->CreateChannel();
  ch->AddLink(::CH);

  // Route all channel-less logs in this thread to 'ch'.
  LogmeThreadChannel(ch->GetID());

  Logme::Override ovr;
  ovr.Remove.Method = true;

  // Apply thread override for channel-less logs in this thread.
  LogmeThreadOverride(ovr);

  // Explicit channel (ChannelPtr) usage.
  LogmeI(ch) << "Worker " << workerId << ": explicit channel";
  LogmeI(ch, "Worker %d: printf style", workerId);

#ifndef LOGME_DISABLE_STD_FORMAT
  fLogmeI(ch, "Worker {}: std::format style", workerId);
#endif

  // Library logs without specifying channel/override.
  LibraryWork("start");
}

int main()
{
  const int threads = 4;

  std::vector<std::thread> workers;
  workers.reserve(threads);

  for (int i = 0; i < threads; i++)
  {
    workers.emplace_back(Worker, i);
  }

  for (auto& t : workers)
  {
    t.join();
  }

  return 0;
}

Previous: Procedure

Clone this wiki locally