PROJECT_NAME = "dlog"
PROJECT_BRIEF = "Logging framework"
OUTPUT_DIRECTORY = "documentation"
-INPUT = doc/ include/dlog.h
+INPUT = doc/dlog_doc.h include/dlog.h
RECURSIVE = YES
# Misc optimisation
src/shared/logcommon.c \
src/logsend/logsend.c
-bin_PROGRAMS += dlogctrl
-dlogctrl_CFLAGS = \
- $(AM_CFLAGS) \
- -fPIE
-
-dlogctrl_LDFLAGS = \
- $(AM_LDFLAGS) \
- -pie
-
-dlogctrl_SOURCES = \
- src/shared/logconfig.c \
- src/shared/logcommon.c \
- src/logctrl/logctrl.c
-
usrlibexeclibdlogdir = /usr/libexec/libdlog
usrlibexeclibdlog_PROGRAMS = test_libdlog
--- /dev/null
+/**
+ @defgroup CLI_DLOGCONF dlog config
+ @ingroup DLOG_COMMAND_LINE_UTILITIES
+ @brief DLog configuration
+ @details Configuration for various DLog components
+
+Important config entries:
+
+Key | Value | Meaning
+--------|-------|----
+plog | 0 or 1 | Enable platform logging. Else, only app logs are collected.
+limiter | 0 or 1 | Enable log limiting. See limiter rules for details.
+limiter\|\<TAG\>\|\<PRIORITY\> | "allow", "deny" or integers | A series of entries to control limiting of apps with given TAG and PRIORITY. "allow" and values < 0 mean no filtering, "deny" or values > 10000 mean no logging allowed, and values between 0 and 10000 mean this many logs per minute are allowed.
+util_sorting_time_window | >= 0 | Sorting time window (in ms) for dlogutil. dlogutil can achieve logs out of order so it waits a bit to make sure unsorted logs have had time to arrive and get sorted.
+dlog_logger_conf_# | dlogutil invocations | The keys should be consecutive numbers from 0. The logger daemon will behave as if dlogutil was invoked for each of these.
+\<BUFFER\> | path | Specifies the path to given buffer. Only for android-logger backend. Do not change because these are usually hardcoded in the kernel.
+\<BUFFER\>_{ctl,write}_sock | path | Pipe backend only. Specifies a path to the control/write socket for given buffer.
+\<BUFFER\>_{ctl,write}_sock_owner | username | Pipe backend only. Specifies the owner of the control/write socket for given buffer.
+\<BUFFER\>_{ctl,write}_sock_group | path | Pipe only. Specifies the group of the control/write socket for given buffer.
+\<BUFFER\>_{ctl,write}_sock_rights | file permissions | Pipe backend only. Specifies file permissions of the control/write socket for given buffer (in the usual octal format).
+\<BUFFER\>_size | > 0 | Size of given buffer
+debugmode | 0 or 1 | If 0, logs of DEBUG priority are dropped
+util_sorting_buffer_size | > 0 | How large of a buffer dlogutil keeps for sorting.
+
+*/
%manifest dlogutil.manifest
%license LICENSE.APACHE2.0
%attr(750,log,log) %{_bindir}/dlogutil
-%attr(755,log,log) %{_bindir}/dlogctrl
%attr(755,log,log) %{_bindir}/dlogsend
%files -n libdlog
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <logconfig.h>
-#include "logctrl_doc.h"
-
-/**
- * @addtogroup DLOG_IMPLEMENTATION
- * @{
- * @defgroup DLOG_CTRL Control
- * @brief The config controller
- * @details The controller responsible for manipulation of the configuration.
- * @{
- */
-
-struct options {
- int print_all;
- int has_key;
- int help;
- int should_get;
- int should_set;
- int should_clear;
-};
-
-/**
- * @brief Validate options
- * @details Checks whether options are valid
- * @param[in] o Options to validate
- * @return Validity of options: 1 if valid, 0 if invalid
- */
-int validate(struct options o)
-{
- int valid = 1;
-
- if (!o.has_key && !o.print_all && !o.help) {
- printf("Having either -i, -p, or -k is mandatory!\n");
- valid = 0;
- }
- if (o.has_key && !(o.should_get || o.should_set || o.should_clear)) {
- printf("-k requires either -c, -g, or -s!\n");
- valid = 0;
- }
- if ((o.has_key + o.print_all + o.help) > 1) {
- printf("-i, -p and -k preclude each other!\n");
- valid = 0;
- }
- if (o.should_set + o.should_get + o.should_clear > 1) {
- printf("-c, -g and -s preclude each other!\n");
- valid = 0;
- }
- if (!o.has_key && (o.should_set || o.should_get || o.should_clear)) {
- printf("-c, -g and -s require -k!\n");
- valid = 0;
- }
-
- return valid;
-}
-
-int main(int argc, char ** argv)
-{
- struct log_config conf_etc, conf_run;
- struct log_config *conf;
- char key[MAX_CONF_KEY_LEN];
- char val[MAX_CONF_VAL_LEN];
- struct options opt = {0, 0, 0, 0, 0, 0};
- const char *filename = getenv("DLOG_CONFIG_PATH") ? : DEFAULT_CONFIG_PATH;
- const char *backend = NULL;
-
- if (argc == 1) {
- print_help(argv[0]);
- return 0;
- }
-
- for (;;) {
- int ret = getopt(argc, argv, "pt:k:gs:ci");
-
- if (ret < 0)
- break;
-
- switch (ret) {
- case 'p':
- opt.print_all = 1;
- break;
- case 'k':
- snprintf(key, MAX_CONF_KEY_LEN, "%s", optarg);
- opt.has_key = 1;
- break;
- case 'g':
- opt.should_get = 1;
- break;
- case 'c':
- opt.should_clear = 1;
- break;
- case 's':
- opt.should_set = 1;
- snprintf(val, MAX_CONF_VAL_LEN, "%s", optarg);
- break;
- case 'i':
- opt.help = 1;
- break;
- }
- }
-
- if (!validate(opt)) {
- print_help(argv[0]);
- return 1;
- }
-
- conf_etc.begin = conf_etc.last = NULL;
- conf_run.begin = conf_run.last = NULL;
- if (log_config_read_file(&conf_etc, filename) < 0) {
- printf("Error: cannot open the config file!\n");
- return 1;
- }
- backend = log_config_get(&conf_etc, "backend");
- if (!backend) {
- printf("Error: there is no backend information\n");
- goto cleanup;
- }
-
- if (opt.help) {
- print_extended_help(backend);
- goto cleanup;
- }
-
- conf = &conf_etc;
-
- if (opt.print_all) {
- log_config_print_out(&conf_etc);
- log_config_print_out(&conf_run);
- } else if (opt.should_get) {
- if (!log_config_print_key(conf, key))
- goto err_entry;
- } else if (opt.should_clear) {
- if (!log_config_remove(conf, key))
- goto err_entry;
- if (log_config_write(conf, filename) < 0)
- goto err_save;
- } else if (opt.should_set) {
- log_config_set(conf, key, val);
- if (log_config_write(conf, filename) < 0)
- goto err_save;
- } else {
- printf("Error: invalid options\n");
- goto cleanup;
- }
-
- log_config_free(&conf_run);
- log_config_free(&conf_etc);
- return 0;
-
-err_save:
- printf("Cannot save file\n");
- goto cleanup;
-
-err_entry:
- printf("Entry not found\n");
-
-cleanup:
- log_config_free(&conf_run);
- log_config_free(&conf_etc);
- return 1;
-}
-
-/**
- * @}
- * @}
- */
+++ /dev/null
-/**
- @defgroup CLI_DLOGCTRL dlogctrl usage
- @ingroup DLOG_COMMAND_LINE_UTILITIES
- @brief Configuration manipulation application
- @details dlogctrl is an application that helps configure the logging framework.
-
-The program accepts the following arguments:
-
-Argument | Requirements | Meaning
----------|-------------------------------------------|-------------
--p | conflicts with -ki | Print all config values.
--i | conflicts with -pk | Show extended information.
--k key | conflicts with -ip, requires one of -gsc | Choose a key for -gsc
--c | conflicts with -gs, requires -k | Clear the value associated with the key
--g | conflicts with -sc, requires -k | Print the value associated with the key
--s value | conflicts with -gc, requires - k | Set the value associated with the key
-
-Important config entries:
-
-Key | Value | Meaning
---------|-------|----
-plog | 0 or 1 | Enable platform logging. Else, only app logs are collected.
-limiter | 0 or 1 | Enable log limiting. See limiter rules for details.
-limiter\|\<TAG\>\|\<PRIORITY\> | "allow", "deny" or integers | A series of entries to control limiting of apps with given TAG and PRIORITY. "allow" and values < 0 mean no filtering, "deny" or values > 10000 mean no logging allowed, and values between 0 and 10000 mean this many logs per minute are allowed.
-util_sorting_time_window | >= 0 | Sorting time window (in ms) for dlogutil. dlogutil can achieve logs out of order so it waits a bit to make sure unsorted logs have had time to arrive and get sorted.
-dlog_logger_conf_# | dlogutil invocations | The keys should be consecutive numbers from 0. The logger daemon will behave as if dlogutil was invoked for each of these.
-\<BUFFER\> | path | Specifies the path to given buffer. Only for android-logger backend. Do not change because these are usually hardcoded in the kernel.
-\<BUFFER\>_{ctl,write}_sock | path | Pipe backend only. Specifies a path to the control/write socket for given buffer.
-\<BUFFER\>_{ctl,write}_sock_owner | username | Pipe backend only. Specifies the owner of the control/write socket for given buffer.
-\<BUFFER\>_{ctl,write}_sock_group | path | Pipe only. Specifies the group of the control/write socket for given buffer.
-\<BUFFER\>_{ctl,write}_sock_rights | file permissions | Pipe backend only. Specifies file permissions of the control/write socket for given buffer (in the usual octal format).
-\<BUFFER\>_size | > 0 | Size of given buffer
-debugmode | 0 or 1 | If 0, logs of DEBUG priority are dropped
-util_sorting_buffer_size | > 0 | How large of a buffer dlogutil keeps for sorting.
-
-*/
-
-
-
-void print_help()
-{
- printf("dlogctrl - provides control over dlog configuration. Options:\n"
- "\t-p Precludes -ki. Prints all entries in the config.\n"
- "\t-k key Precludes -pi and requires one of -gs. Specifies a config key.\n"
- "\t-g Requires -k, precludes -cs. Gets and prints the value of the entry assigned to the key.\n"
- "\t-s value Requires -k, precludes -cg. Sets the value of the entry associated with the key.\n"
- "\t-c Requires -k, precludes -gs. Clears the entry.\n"
- "\t-i Precludes -pk. Shows information for important config values.\n"
- "Having either -i, -p or -k is mandatory.\n"
- );
-}
-
-void print_extended_help(const char *backend)
-{
- printf("Important entries:\n"
- "\tplog: enable platform logging, ie. whether any logging happens at all. Values are 0 or 1.\n"
- "\tlimiter: enable log limiting. Values are 0 or 1.\n\n"
- "Limiter rules:\n"
- "\tlimiter entry keys are of the form \"limiter|TAG|LEVEL\",\n"
- "\twhere TAG is the arbitrary string which defines the user application,\n"
- "\tand LEVEL is logging level which is one of:\n"
- "\t\tV or 1: verbose\n"
- "\t\tD or 2: debug\n"
- "\t\tI or 3: info\n"
- "\t\tW or 4: warning\n"
- "\t\tE or 5: error\n"
- "\t\tF or 6: fatal\n"
- "\tA rule fits messages of given tag and level. Alternatively,\n"
- "\tan asterisk (*) can also be used in place of either, as a wild card.\n"
- "\tExplicit rules have priority over wild-card ones.\n"
- "\tTwo asterisks can be used to signify a backup rule for those messages\n"
- "\twhich did not fit any other rule. Some example rule keys:\n"
- "\tExample rules:\n"
- "\t\tlimiter|SOME_APP|W\n"
- "\t\tlimiter|SOME_APP|* (affects all SOME_APP logs except warnings, which already have an explicit rule)\n"
- "\t\tlimiter|*|W (affects all warnings except the ones from SOME_APP)\n"
- "\t\tlimiter|*|* (affects everything else)\n"
- "\tLimiter entries can have one of three value types:\n"
- "\t\tstring \"allow\" or integers < 0: lets all logs of given type through.\n"
- "\t\tstring \"deny\" or integers > 10000: blocks all logs of given type.\n"
- "\t\tintegers from the <1, 10000> range: let through that many logs per minute.\n\n"
- "Buffer size entries:\n"
- "\tkeys are of the form <BUFFER>_size, for example main_size;\n"
- "\tvalues are size in bytes, for example 1048576.\n"
- "\tThese entries control the size of the logging buffers.\n\n"
- "Passive logging to file (dlog_logger):\n"
- "\tkeys are of the format dlog_logger_conf_#\n"
- "\twhere # are consecutive integers from 0.\n"
- "\tValues are the same as when calling dlogutil (including \"dlogutil\" at start), for example\n"
- "\t\tdlogutil -b system -r 5120 -n 1 -f /var/log/dlog/system.raw *:I\n\n");
-
- if (!strncmp(backend, "pipe", sizeof("pipe") + 1))
- printf("DLogUtil sorting:\n"
- "\tkey is util_sorting_time_window;\n"
- "\tvalue is an integer representing the size\n"
- "\tof the sorting window in milliseconds. This\n"
- "\taffects quality of the sort, but also delay.\n\n"
- "Socket control entries:\n"
- "\tkeys are of the form <BUFFER>_{ctl,write}_sock_{path,rights,group,owner}\n"
- "\tFor example: system_write_sock_group, radio_ctl_sock_path\n"
- "\tCTL sockets are for administrative purposes, WRITE are for programs making logs.\n"
- "\tFor PATH, values signify the path to the appropriate socket.\n"
- "\tFor RIGHTS, the value is file permissions in octal (for example 0664).\n"
- "\tFor GROUP and OWNER the values are group/owner of the file (for example root).\n\n");
- else
- printf("Buffer device names:\n"
- "\tkeys are simply buffer names, for example main;\n"
- "\tvalues are paths to the devices.\n"
- "\tNote: these values are read-only!\n"
- "\tChanging them does nothing and can potentially break things.\n\n");
-}
mkdir /tmp/dlog_tests
-# dlogctrl (tests 1-10)
-dlogctrl &> /dev/null && ok || fail # no args (display help)
-dlogctrl -g &> /dev/null && fail || ok # no -pk
-dlogctrl -p &> /dev/null && ok || fail # valid -p
-dlogctrl -k &> /dev/null && fail || ok # invalid -k
-dlogctrl -p -k some_test_key &> /dev/null && fail || ok # both -pk
-dlogctrl -k some_test_key &> /dev/null && fail || ok # no -gs with -k
-dlogctrl -k some_test_key -g &> /dev/null && fail || ok # non-existent key
-dlogctrl -k some_test_key -s &> /dev/null && fail || ok # no value
-dlogctrl -k some_test_key -s some_value &> /dev/null && ok || fail # valid -s
-dlogctrl -k some_test_key -g &> /dev/null && ok || fail # valid -g
-
-# tests 11-18
-dlogctrl -k some_test_key -g -s some_other_value &> /dev/null && fail || ok # both -gs
-dlogctrl -k some_test_key -g -c &> /dev/null && fail || ok # both -gc
-dlogctrl -k some_test_key -c -s some_other_value &> /dev/null && fail || ok # both -cs
-dlogctrl -k some_test_key -g | grep some_value &> /dev/null && ok || fail # checks whether the value is what we passed
-dlogctrl -k some_test_key -g | grep some_other_value &> /dev/null && fail || ok # ditto
-dlogctrl -k some_test_key -c &> /dev/null && ok || fail # clear the test key
-dlogctrl -k some_test_key -c &> /dev/null && fail || ok # clear the now non-existent key
-dlogctrl -k some_test_key -g &> /dev/null && fail || ok # get the now non-existent key
-
# Start the daemon, add some logs
dlog_logger -b 99 -t 0 &
LOGGER=$!
test_libdlog 100
sleep 1
-# 19-22: test -d and -t
+# 1-4: test -d and -t
dlogutil -d &> /dev/null && ok || fail
if [ $(dlogutil -t 20 | wc -l) -eq 20 ]; then ok; else fail; fi # less logs than currently in buffer
if [ $(dlogutil -t 200 | wc -l) -eq 100 ]; then ok; else fail; fi # more
if [ $(dlogutil -d | wc -l) -eq 100 ]; then ok; else fail; fi # exactly
-# 23-24: test -b
+# 5-6: test -b
dlogutil -b nonexistent_buffer &> /dev/null && fail || ok
if [ $(dlogutil -d -b apps | wc -l) -eq 0 ]; then ok; else fail; fi # the logs should be in another buffer
-# 25-26: test -c
+# 7-8: test -c
dlogutil -c && ok || fail
test_libdlog 10
if [ $(dlogutil -d | wc -l) -eq 10 ]; then ok; else fail; fi # should be 10, not 110
-# 27: test filters
+# 9: test filters
if [ $(dlogutil -d *:E | wc -l) -eq 5 ]; then ok; else fail; fi # half of current logs (test_libdlog alternates between error and info log levels)
-# 28: test -s
+# 10: test -s
if [ $(dlogutil -s -d | wc -l) -eq 0 ]; then ok; else fail; fi
-# 29: test -g
+# 11: test -g
dlogutil -g &> /dev/null && ok || fail
-# 30-37: test -f, -r and -n
+# 12-19: test -f, -r and -n
dlogutil -f /tmp/dlog_tests/dlog_test_file -d &> /dev/null && ok || fail
dlogutil -f /tmp/dlog_tests/dlog_rotating_file -r 12 -n 3 & # 3 files at 12 KB each
UTIL_PID=$!
# Test -v
# TODO
-# 38: test library
+# 20: test library
dlogutil -f /tmp/dlog_tests/dlog_mt_test &
MT_TEST=$!
test_libdlog && ok || fail