Skip to content
This repository has been archived by the owner on Nov 26, 2024. It is now read-only.

LSW::v4::Logger

Ernesto Luis (aka Lohkdesgds Lhuminury) edited this page Feb 29, 2020 · 3 revisions

LSW::v4::Logger


  • Arquivo: "Logger/logger.h"
  • Tipo: semi-dependente
    • Abort
    • Shared

Logger é o perfeito esquema para se salvar arquivos e registrar coisas ao redor do programa. É, ao mesmo tempo, um std::cout e um gerador de evento de chat, com o bônus de ter cores! Ele funciona com & para definir uma cor para a letra, de [0-9,a-f], como em &7um texto cinza &6ou dourado!.


Enums:

enum class L { EL, SL, SLF, ELF };
enum class E { INFO, WARN, ERRR, DEBUG };
enum class C { BLACK, DARK_BLUE, DARK_GREEN, DARK_AQUA, DARK_RED, DARK_PURPLE, GOLD, GRAY, DARK_GRAY, BLUE, GREEN, AQUA, RED, LIGHT_PURPLE, YELLOW, WHITE};
  • L: S... no início do nome significa Start, usado no início do uso com o operator<<.
  • L: E... no início do nome significa End, usado no final do uso com o operator<<, como o comumente usado std::endl.
  • L: ...F significa "salvar no log" (File), ou seja, além das ferramentas para garantir funcionamento multithread, ele salva no arquivo que você definiu como log.
  • E: uma forma de destacar facilmente se é apenas informações, aviso, erro ou coisas de debug.
  • C: ferramenta usada pelo programa para interpretar os & com as cores [0-9,a-f].

Estrutura de caractere com cor

struct char_c {
  char ch = '\0';
  C cr = C::WHITE;
};
using color_string = std::basic_string<char_c>;

color_string funciona igual a um std::string, só que com um char e um C. Dessa maneira é possível enviar ao redor do programa caracteres com cores diferentes. Essa base é mais usada internamente, não precisa ser usada diretamente, mas pode ser usada em outros lugares se você achar interessante para seu projeto.


Classe Logger

void Logger::init(const std::string);
void Logger::flush();
ALLEGRO_EVENT_SOURCE* Logger::getEvent();
Logger& Logger::operator<<(...);
  • Logger::init(const std::string) é seu ponto de partida. Ao criar seu projeto é extremamente recomendado que uma das suas primeiras linhas de código sejam com essa função. Crie um Logger e defina onde ele deve salvar o log, como, por exemplo, "log.log".
  • Logger::flush() deve ser usado sempre que você quiser garantir que o arquivo esteja salvo. O sistema nem sempre deixa tudo salvo no disco de uma vez (otimizações do próprio sistema), então com isso você garante que mesmo se o programa morra do nada, ele salve os dados até aquele ponto no arquivo de log.
  • Logger::getEvent() é maravilhosamente usado por diversos lugares do código, como no Text para pegar a última linha do log. Toda vez que tiver uma nova linha um novo evento é gerado, e cada evento contém uma string do tipo color_string para que você possa mostrar com as cores previstas.
  • Logger::operator<<(...) recebe praticamente tudo (int, double, char, char*, size_t...) e imprime na tela, gera evento e/ou salva em arquivo. Esse tem muito a cara do std::cout, porque você basicamente faz a mesma coisa.

Funções assistentes:

const std::string fsr(std::string, const E);

Essa função é basicamente sempre usada dentro do programa. O primeiro std::string espera um nome de função (foi planejada assim), então se usa __FUNCSIG__ do Visual Studio, e o E é um código de erro se quiser colocar ao log, com padrão INFO.


Como deve se usar o Logger?

O Logger é para ser uma classe completa e fácil de usar. Se você já usa std::cout bastante em seus programas, vai ver que aqui não é tão diferente disso.

Logger logg;
logg.init("test.log");	
logg << L::SLF << fsr(__FUNCSIG__, E::DEBUG) << "Esse é um &3T&2E&9S&dT&4E &fLMAO" << L::ELF;
for (short u = 0; u < 16; u++) {
  C clr = static_cast<C>(u);
  logg << L::SLF << fsr(__FUNCSIG__, E::DEBUG) << clr << "RAINBOW" << L::ELF;
}

Nesse exemplo é possível ver como é a estrutura do Logger. Normalmente você vai chamá-lo com L::SLF ou L::SL (se quiser salvar no arquivo ou só mostrar na tela / enviar evento, respectivamente), depois fsr para registrar de onde está vindo o texto (opcional, bom para debug e registro) e em seguida tudo que quiser, seja um texto, número ou talvez algo mais complexo. No final você usa o final correspondente: se usou L::SLF, use L::ELF para "fechar" o arquivo (não fecha literalmente, mas fecha o ciclo), senão, se usou L::SL, use L::EL.


Como o evento funciona:

Em cima da biblioteca do Allegro, o programa envia por meio de um ALLEGRO_EVENT_SOURCE* (que você pode registrar num ALLEGRO_EVENT_QUEUE*) um ALLEGRO_EVENT com .user.data1 contendo o ponteiro para uma color_string. O tipo do evento que ele gera é Shared::ro__my_events::CUSTOM_EVENT_LOG_STRING (Shared.h) registrado no .type. De preferência copie os dados o quanto antes, pois o buffer do Logger não é ilimitado (para garantir que não tivesse memory leak, a memória é fixa e reutilizada depois de alguns ciclos diversas vezes).

Exemplo de código usando getEvent():
// include do Allegro e outras coisas suas
#include "Logger/logger.h"

using namespace LSW::v4;

Logger logg;
logg.init("log.log"); // não esqueça de iniciar com algum arquivo!
ALLEGRO_EVENT_QUEUE* ev_qu = al_create_event_queue();
al_register_event_source(logg.getEvent());
// ...
while(1){
  ALLEGRO_EVENT ev;
  al_wait_for_event(ev_qu, &ev);
  if (ev.type == static_cast<int>(Shared::ro__my_events::CUSTOM_EVENT_LOG_STRING)){
    color_string str = *((color_string*)ev.user.data1);
    // usa str de alguma maneira, e só gera evento se Logger tiver novas linhas
  }
}

Pode parecer complexo, mas o Logger é extremamente fácil se você não errar os L::SL/SLF e L::EL/ELF. Garanta o esquema e você não vai ter dor de cabeça.

Clone this wiki locally