Вопросы, на которые я не нашёл ответ в книгах (Помогите, пожалуйста)
Модератор: Модераторы разделов
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Вопросы, на которые я не нашёл ответ в книгах
Здраствуйте. Хочу расширить свои знания С++ и лучше всего это делать на практике, поэтому я взялся за проект. При написании проекта возникают переодически вопросы, которые я самостоятельно решить не могу. Прошу вас мне в этом помочь.
Как только я начал делать проект у меня возник первый вопрос: а как в С++ осуществляется система логгирования. Например в питоне для этого есть специальный модуль logging, в который надо указать имя файла, куда записывать лог и в каком бы файле не был подключен модуль logging, лог для всех файлов общий. А что делать в С++ в таких случаях? Неужели вводить специальную переменную типа string и передавать её конструкторам классов?
Как только я начал делать проект у меня возник первый вопрос: а как в С++ осуществляется система логгирования. Например в питоне для этого есть специальный модуль logging, в который надо указать имя файла, куда записывать лог и в каком бы файле не был подключен модуль logging, лог для всех файлов общий. А что делать в С++ в таких случаях? Неужели вводить специальную переменную типа string и передавать её конструкторам классов?
-
Portnov
- Модератор
- Сообщения: 1786
- Статус: Матёрый линуксоид
- ОС: Debian testing/unstable
Re: Вопросы, на которые я не нашёл ответ в книгах
Ручками. Библиотеки, думаю, есть, и, возможно, щас тут даже подскажут названия, но ни одна из них стандартной не является, поэтому ничем не лучше самодельного велосипеда. Это вам не питон, тут батареек в комплект никто не озаботился дать 
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
-
deninok
- Сообщения: 585
- Статус: Программист С++
- ОС: Debian GNU/Linux
Re: Вопросы, на которые я не нашёл ответ в книгах
(-DooM-) писал(а):... как в С++ осуществляется система логгирования?
А не подскажете ли, что такое логирование? Если "лог" - это журнал (в общем смысле этого слова), то логирование - это что, запись в этот журнал? Я просто не слышал такого термина, потому и спрашиваю...
-
yaleks
- Сообщения: 2121
- Статус: вне статуса
- ОС: Gentoo ~
Re: Вопросы, на которые я не нашёл ответ в книгах
Посмотрите как это реализовано в одном из крупных проектов, например в Squid 3.
-
dey
- Сообщения: 335
- ОС: OpenSuse 11.1
Re: Вопросы, на которые я не нашёл ответ в книгах
В сознательных действиях должен присутствовать существенный неалгоритмический компонент.
Roger Penrose,The Emperor's New Mind
Roger Penrose,The Emperor's New Mind
-
un-defined
- Сообщения: 145
- ОС: Kubuntu, Gentoo
Re: Вопросы, на которые я не нашёл ответ в книгах
А syslog(3) чем не устраивает?
Don`t try - just do or do not ©Master Joda
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Re: Вопросы, на которые я не нашёл ответ в книгах
Ну я под этим подразумеваю систему, которая обеспечивает запись текста в определенный файл причём глобально по всем файлам программы. Текст является логом, чтобы пользователи в случае ошибки могли его присылать разработчику.
А можно поподробнее? Что это?
-
un-defined
- Сообщения: 145
- ОС: Kubuntu, Gentoo
Re: Вопросы, на которые я не нашёл ответ в книгах
А можно поподробнее? Что это?
man 3 syslog
Don`t try - just do or do not ©Master Joda
-
deninok
- Сообщения: 585
- Статус: Программист С++
- ОС: Debian GNU/Linux
Re: Вопросы, на которые я не нашёл ответ в книгах
(-DooM-) писал(а):Ну я под этим подразумеваю систему, которая обеспечивает запись текста в определенный файл причём глобально по всем файлам программы. Текст является логом, чтобы пользователи в случае ошибки могли его присылать разработчику.
Ясно. Подобного рода систему я буду реализовывать и в своем проекте. Но делать это буду сам, поскольку мой проект работает на особом оборудовании. Но это так, к слову.
Спасибо за пояснение.
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Re: Вопросы, на которые я не нашёл ответ в книгах
Спасибо большое, нашёл её даже в репозитах. Почитаю документацию.
Спасибо, сейчас почитаю.
Ясно. Подобного рода систему я буду реализовывать и в своем проекте. Но делать это буду сам, поскольку мой проект работает на особом оборудовании. Но это так, к слову.
Пожалуйста. Я бы тоже сам реализовал, но других идей, кроме той, что написана в первом посте у меня нет
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Вопросы, на которые я не нашёл ответ в книгах
Если речь об отладочном выводе для девелопера/админа/юзера, то имхо логичнее всего будет обращение к глобальному объекту/функции, которая м.б. сконфигурирована (из конф.h и-или опциями при запуске) и выводит сообщения на любое из или на несколько одновременно:
- cerr/clog
- в указанный в опции файл
- в syslog
Опцией задается уровень "болтливости" лога. Сообщения отправляются с параметром критичности - логить или игнорировать... ну и отдельными аргами можно передавать имя подсистемы или что-нибудь еще, по вкусу, чтобы с форматированием самого сообщения меньше набивать.
Поскольку (скорее всего) система требует инициализации, то или вы не пользуетесь ею в статическом коде, или оформляете фокус с инициализацией так же, как со стандартными потоками с библиотеке сделано...
- cerr/clog
- в указанный в опции файл
- в syslog
Опцией задается уровень "болтливости" лога. Сообщения отправляются с параметром критичности - логить или игнорировать... ну и отдельными аргами можно передавать имя подсистемы или что-нибудь еще, по вкусу, чтобы с форматированием самого сообщения меньше набивать.
Поскольку (скорее всего) система требует инициализации, то или вы не пользуетесь ею в статическом коде, или оформляете фокус с инициализацией так же, как со стандартными потоками с библиотеке сделано...
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Re: Вопросы, на которые я не нашёл ответ в книгах
sergio писал(а): ↑04.05.2008 13:56Если речь об отладочном выводе для девелопера/админа/юзера, то имхо логичнее всего будет обращение к глобальному объекту/функции, которая м.б. сконфигурирована (из конф.h и-или опциями при запуске) и выводит сообщения на любое из или на несколько одновременно:
- cerr/clog
- в указанный в опции файл
- в syslog
Опцией задается уровень "болтливости" лога. Сообщения отправляются с параметром критичности - логить или игнорировать... ну и отдельными аргами можно передавать имя подсистемы или что-нибудь еще, по вкусу, чтобы с форматированием самого сообщения меньше набивать.
Поскольку (скорее всего) система требует инициализации, то или вы не пользуетесь ею в статическом коде, или оформляете фокус с инициализацией так же, как со стандартными потоками с библиотеке сделано...
А если направлять все сообщения для логов в cerr, можно будет забрать всё оттуда при выходе из программы например?
Посмотрел про syslog и решил, что это слишком сложная система в моей ситуации.
то имхо логичнее всего будет обращение к глобальному объекту/функции,
А в С++ как это делается? С помощью extern переменных в каком-либо подключаемом файле?
-
deninok
- Сообщения: 585
- Статус: Программист С++
- ОС: Debian GNU/Linux
Re: Вопросы, на которые я не нашёл ответ в книгах
(-DooM-) писал(а):то имхо логичнее всего будет обращение к глобальному объекту/функции,
А в С++ как это делается? С помощью extern переменных в каком-либо подключаемом файле?
Можно и так. А можно обойтись без extern-переменных путем создания одного объекта с открытым (из всех единиц трансляции) доступом.
Причем этот объект разумнее всего сделать на основе проектного паттерна "Одиночка", известного также как "Singleton".
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Вопросы, на которые я не нашёл ответ в книгах
Для этого надо запустить программу с перенаправлением стдерр в файл.
Код: Выделить всё
progname 2>> progname.log(можно оформить как баш-скрипт через который и запускать программу...)
Потому и говорил, что удобнее всего использовать для вывода свою функцию, которая может быть в одном месте сконфигурирована куда (в т.ч. и не в одну точку - например на консоль через стдерр и в указанный файл) ей выводить, насколько болтливо выводить и проч.
Глобальные переменные - да. Для использования их в другом модуле они должны быть объявлены в подключаемом туда заголовке с extern. Функции видны так, но есессно тоже должны быть объявлены в заголовке, подключаемом туда где их вызывают...
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Re: Вопросы, на которые я не нашёл ответ в книгах
Несколько варинтов логгирования я для себя узнал. (Понравилось взаимодействие с потоком ошибок, но писать баш скрипт в случае с С++ мимо). А какой по вашему лучше всего использовать и "красивее"?
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Вопросы, на которые я не нашёл ответ в книгах
Так то смотря для чего.
Системные процессы пишут логи в /var/log/ или непосредственно, или посредством syslog.
Пользовательская программа пишет лог файл какой закажут. progname --logfile=progname.log если закажут. Или из окошек то же самое.
Если речь идет об отладке, то тут не "красивее" критерий, а "проще и удобнее". Проще всего использовать стдерр, удобнее всего его перенаправить (или сдублировать тем же башем) в файл, чтобы можно было разглядывать долгими зимними ночами.
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Re: Вопросы, на которые я не нашёл ответ в книгах
Ну я как-то не представляю С++ программу, в которой баш скрипт запускает какой-нибудь бинарник, лежащий в /usr/lib например.
Решил сделать так: у меня в ядре программы будет основной класс Kernel, в котором будет переменная logVar типа std::string. Так как объект ядра будет передавать почти во все остальные объекты, вместе с ним и лог передается. Я просто напишу две функции для класса ядра: std::string log() const, void addLogMessage(char* message); Как вам решение?
Кто-нибудь работал с библиотекой libhal,libhal-storage? Где можно хотя бы примеры или документацию по их использованию найти?
-
un-defined
- Сообщения: 145
- ОС: Kubuntu, Gentoo
Re: Вопросы, на которые я не нашёл ответ в книгах
Ну так, на минуточку, все стартовые скрипты, например, как раз и есть баш-скрипты, запускающие C или (иногда) C++
программы, лежащие в том числе и в /usr/lib
Don`t try - just do or do not ©Master Joda
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Re: Вопросы, на которые я не нашёл ответ в книгах
un-defined писал(а): ↑04.05.2008 18:25
Ну так, на минуточку, все стартовые скрипты, например, как раз и есть баш-скрипты, запускающие C или (иногда) C++
программы, лежащие в том числе и в /usr/lib
Всё-таки мне более симпотичен выбранный вариант.
-
un-defined
- Сообщения: 145
- ОС: Kubuntu, Gentoo
Re: Вопросы, на которые я не нашёл ответ в книгах
-DooM- писал(а): ↑04.05.2008 18:17Решил сделать так: у меня в ядре программы будет основной класс Kernel, в котором будет переменная logVar типа std::string. Так как объект ядра будет передавать почти во все остальные объекты, вместе с ним и лог передается. Я просто напишу две функции для класса ядра: std::string log() const, void addLogMessage(char* message); Как вам решение?
А как быть с теми объектами, которые про ядро ничего не знают?
Лучше завести статический класс, в котором и будет выполняться журналирование. Ну или просто написать свободные функции, если статический класс по каким-то причинам не понравится.
Вариант каждому симпатичен свой, но писать логи в stderr - стандартнейший способ вывода сообщений об ошибках, если мы говорим все еще про *nix.
Don`t try - just do or do not ©Master Joda
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Re: Вопросы, на которые я не нашёл ответ в книгах
un-defined писал(а): ↑04.05.2008 18:33А как быть с теми объектами, которые про ядро ничего не знают?
Лучше завести статический класс, в котором и будет выполняться журналирование. Ну или просто написать свободные функции, если статический класс по каким-то причинам не понравится.
А что такое "свободная функция" и "статический класс"? К сожалению, в первый раз слышу.
Вариант каждому симпатичен свой, но писать логи в stderr - стандартнейший способ вывода сообщений об ошибках, если мы говорим все еще про *nix.
Вы правы, но всё таки баш скрипт мне кажется костылем.
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Вопросы, на которые я не нашёл ответ в книгах
Функция, которая сама по себе а не функция-член ака метод.
Статический класс - вероятно имеется в виду статически размещенный (вне кода какой-либо функции) глобальный объект логирующего класса.
И таких костылей в этой системе...
Щас сюда придет кто-нибудь из любителей баш и скажет вам все, что думает по этому поводу.
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
Assuri
- Сообщения: 678
- Статус: #include <brain.h>
- ОС: Fedora 12
Re: Вопросы, на которые я не нашёл ответ в книгах
То-есть я просто подключаю либу с одной функцией, например, addLogMessage(str) и она открывает файл, добавляет в него запись и снова закрывает?
Статический класс менее подходит, чем свободная функция, если я правильно понял.
И таких костылей в этой системе...![]()
Щас сюда придет кто-нибудь из любителей баш и скажет вам все, что думает по этому поводу.
Нет, нет, Вы меня неправильно поняли
-
sergio
- Сообщения: 436
- Статус: Интересующийся новичок
- ОС: Debian GNU/Linux 4 & 5
Re: Вопросы, на которые я не нашёл ответ в книгах
Это непрактично и возможный тормоз. Файл лога вероятнее должен быть открыт с запуска программы либо с первого обращения, закрыт при завершении.
Статический класс менее подходит, чем свободная функция, если я правильно понял.
Да примерно одна фигня. ;)
Два варианта.
1) вы при входе в мэйн вызываете функцию инит логгерного же модуля чтобы она открыла файл (хэндл файла сохраняется как внутренняя переменная модуля...), заковырка тут такая:
а) надо не забыть вызывать инит (и финит в конце мэйн для закрытия лога, возможно)
б) вы не можете писать в лог из кторов/дторов статических объектов, если у вас таковые случатся.
При использовании статического глобального объекта для логоведения пункт а) решается без вас, ничего вызывать не нужно, открытие файла вы производите в кторе объекта. Пункт б) остается. Его можно решить фокусом, который используется для iostream, если надо.
2) при каждом вызове addLogMessage проверяет, что открытие файла уже производилось, если нет - то вызывает функцию своего модуля, которая его открывает, сохраняет хэндл внутри модуля, и при дальнейших операциях пользует. Файл мы НЕ закрываем, поскольку... закрыть его вовремя можно только используя фокусы помянутые выше, и то я не уверен, надо подумать; но поскольку при не-аварийном завершении программа флашит весь вывод, а addLogMessage может флашить каждое сообщение - то это и не обязательно. То же самое можно оформить вместо функции и переменных модуля (единицы компиляции), в виде статик-метода класса...
Второй метод в вариациях является дизайн-шаблоном "синглтон", про который кто-то тут уже поминал. Singleton.
Нет, нет, Вы меня неправильно понялиЯ знаю что такое баш в нихе. Я имею ввиду, что в моём случае, это лишнее.
DooM, боюсь не очень понятно, какой лог вы собрались писать. Если это рабочий лог сервера (или журнал аськи, или еще чего) - это одно. Тогда костыли. Да и стдерр для него не очень подходит, возможно. Если это дебаг-мессиджи на период отладки-тестирования - то не вижу, чем плоха работа с баш-оберткой.
Код: Выделить всё
#!/bin/sh
# если ~/.myproga/ не существует, то mkdir ее...
echo "==============$( date )=============" >> ~/.myproga/myproga.log
/usr/bin/myproga --debug 2>> ~/.myproga/myproga.logDebian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
-
un-defined
- Сообщения: 145
- ОС: Kubuntu, Gentoo
Re: Вопросы, на которые я не нашёл ответ в книгах
Вообще-то я про статические функции-члены, особенно если в классе нет нестатических. А если к тому же еще и конструктор сделать приватным, то может вообще синглтон получиться
но опять-таки, надо смотреть, для каких целей журналирование ведется - если для отладки, то это одно, а если для работы - то уже другое.
Don`t try - just do or do not ©Master Joda
-
deninok
- Сообщения: 585
- Статус: Программист С++
- ОС: Debian GNU/Linux
Re: Вопросы, на которые я не нашёл ответ в книгах
(un-defined) писал(а):А если к тому же еще и конструктор сделать приватным, то может вообще синглтон получиться
Ну, закрытого конструктора для синглтона маловато будет...
-
un-defined
- Сообщения: 145
- ОС: Kubuntu, Gentoo
Re: Вопросы, на которые я не нашёл ответ в книгах
Ну это понятно, я же не сказал, что сразу получится, я сказал, что может получиться, если еще кое-какие усилия приложить.
Don`t try - just do or do not ©Master Joda
-
GRS
- Сообщения: 236
- Статус: C++ Pro
- ОС: Suse10.2/XP
Re: Вопросы, на которые я не нашёл ответ в книгах
Стандартных средст, как уже и до меня отметили - нет.
Нужно реализовывать свои.
Я могу лишь посоветовать.
1) Это должен быть класс-синглтон, для того чтобы доступ был простым и в любой части программы.
2) Нужно использовать макросы для удобства.
Вот например :
Вот и используем в программе макрос, где угодно :
Ну естественно в качестве параметром можно передать все - главное чтобы для своих типов была реализован стандартный вывод, оператор "<<".
В качестве дополнений, можно ввести идентификатор лога, чтобы лог-файлов было несколько - и по идентификатору сообщение писалось в нужный log файл.
Нужно реализовывать свои.
Я могу лишь посоветовать.
1) Это должен быть класс-синглтон, для того чтобы доступ был простым и в любой части программы.
2) Нужно использовать макросы для удобства.
Вот например :
Код: Выделить всё
class MyLog : public singletone<MyLog>
{
MyLog() {}
public:
static MyLog * Make(const char * sFilename); // здесь создаем обьект Log, если не удалось открыть файл для записи - возвращаем 0, т.е.лог создать не удалось
void Write(std::stringstream & strm);
bool Open(const char * sFilename);
private:
std::ofstream m_Output;
};
MyLog * MyLog::Make(const char * sFilename)
{
MyLog * log = new MyLog;
if (log.Open(sFilename))
return log;
delete log;
return 0;
}
void MyLog::Write(std::stringstream & strm)
{
m_Output << strm << std::endl;
}
// самое главное
#define MY_LOG(args) \
{ \
std::stringstream strm; \
strm << args; \
MyLog::Instance().Write(strm); \
}Вот и используем в программе макрос, где угодно :
Код: Выделить всё
...
MY_LOG("Debug : count = "<< nCount<<", sum = "<<nSum)
...Ну естественно в качестве параметром можно передать все - главное чтобы для своих типов была реализован стандартный вывод, оператор "<<".
В качестве дополнений, можно ввести идентификатор лога, чтобы лог-файлов было несколько - и по идентификатору сообщение писалось в нужный log файл.
Код: Выделить всё
void Write(int nId, std::stringstream & strm);
#define MY_LOG(id, args) \
{ \
std::stringstream strm; \
strm << args; \
MyLog::Instance().Write(id, strm); \
}
#define DEBUG_LOG(args) \
MY_LOG(DEBUG_LOG_ID, args)
#define USER_LOG(args) \
MY_LOG(USER_LOG_ID, args)-
deninok
- Сообщения: 585
- Статус: Программист С++
- ОС: Debian GNU/Linux
Re: Вопросы, на которые я не нашёл ответ в книгах
(GRS) писал(а):2) Нужно использовать макросы для удобства.
А разве функцию использовать нельзя? В С++ использование препроцессора вообще должно быть сведено к минимуму (в идеале он должен применяться только для двух операций: включение файлов и защита заголовочника от повторного включения в единицу трансляции).
-
GRS
- Сообщения: 236
- Статус: C++ Pro
- ОС: Suse10.2/XP
Re: Вопросы, на которые я не нашёл ответ в книгах
2 deninok
ну попробуй с помощью функции сделать так чтобы можно было написать.
log("degub data"<<data<<", counter = "<<nCounter<<//и еще так далее нужные данные, которые потребуются в логе
ну попробуй с помощью функции сделать так чтобы можно было написать.
log("degub data"<<data<<", counter = "<<nCounter<<//и еще так далее нужные данные, которые потребуются в логе