Logging

Logging#

@startuml logger

title Abstract model of logger

package logging {
    enum log_level {
        {field} {abstract} (omitted here)
    }

    class log_tag {
        - name_ : string
        + log_tag(name: string)
        + name() : const string&
    }

    !startsub log_tag_view
    class log_tag_view {
        - name_ : string_view
        + log_tag(name: string_view)
        + name() : string_view
    }
    !endsub

    package formatters {
        interface log_formatter_base {
            {abstract} + format(fmt::memory_buffer& buffer,\n\ttime: time_point, tag: string_view, level: log_level,\n\tsource: source_info_view, body: string_view)
        }
        log_formatter_base ..> log_level

        class xxx_log_formatter
        log_formatter_base <|.. xxx_log_formatter
    }

    package sinks {
        !startsub log_sink
        class log_sink {
            + write(time: time_point, tag: string_view, level: log_level,\n\tsource: source_info_view, body: string_view)
        }
        !endsub
        log_sink ..> log_level

        !startsub xxx_log_sink
        class xxx_log_sink
        !endsub
        log_sink o-- xxx_log_sink
        xxx_log_sink o-- log_formatter_base
    }

    !startsub log_tag_config
    class log_tag_config {
        + sink() : shared_ptr<log_sink>
        + output_log_level() : log_level
        + output_log_level_in_child_iterations() : log_level
        + iteration_output_period() : index_type
        + iteration_label_period() : index_type
    }
    !endsub
    log_tag_config o-- log_sink
    log_tag_config o-- log_level

    !startsub log_config
    class log_config {
        {static} + instance() : log_config&
        + get_default_tag_config() : log_tag_config
        + set_default_tag_config(config: log_tag_config)
        + get_config_of(tag: log_tag_view) : log_tag_config
        + set_config_of(tag: log_tag_view, config: log_tag_config)
    }
    !endsub
    log_config o-- log_tag
    log_config o-- log_tag_config
    log_config ..> log_tag_view

    class logging_proxy {
        + operator()(body: string_view)
        + operator()(format: fmt::format_string, args...)
    }

    !startsub logger
    class logger {
        + logger(tag: log_tag_view)
        + logger(tag: log_tag_view, config: log_tag_config)
        + logger(tag: log_tag, config: log_tag_config)
        + tag() : const log_tag&
        + config() : const log_tag_config&
        + set_iterative()
        + initialize_child_algorithm_logger(child: logger&)
        + should_log(level: log_level) : bool
        + log(level: log_level, source: source_info_view = source_info_view()) : logging_proxy
        + trace(source: source_info_view = source_info_view()) : logging_proxy
        + debug(source: source_info_view = source_info_view()) : logging_proxy
        + iteration(source: source_info_view = source_info_view()) : logging_proxy
        + iteration_label(source: source_info_view = source_info_view()) : logging_proxy
        + summary(source: source_info_view = source_info_view()) : logging_proxy
        + info(source: source_info_view = source_info_view()) : logging_proxy
        + warning(source: source_info_view = source_info_view()) : logging_proxy
        + error(source: source_info_view = source_info_view()) : logging_proxy
        + critical(source: source_info_view = source_info_view()) : logging_proxy
    }
    !endsub
    logger o-- log_tag
    logger o-- log_tag_config
    logger ..> log_tag_view
    logger ..> logging_proxy
    logger ..> log_config
}

@enduml

@startuml config

title Abstract model of configurations of logging

package logging {
    package sinks {
        !includesub ./logger.puml!log_sink
        !includesub ./logger.puml!xxx_log_sink
        log_sink o-- xxx_log_sink
    }
    !includesub ./logger.puml!log_tag_config
    log_tag_config o-- log_sink
    !includesub ./logger.puml!log_config
    log_config o-- log_tag_config

    package config {
        interface log_sink_factory_base {
            {abstract} + create(sinks: log_sink_factory_table&) : log_sink
        }
        log_sink_factory_base ..> log_sink

        class log_sink_factory_table {
            + append(name: string,\n\tsink_factory: shared_ptr<log_sink_factory_base>)
            + get(name: string) : log_sink
        }
        log_sink_factory_table o-- log_sink_factory_base
        log_sink_factory_table o-- log_sink
        log_sink_factory_base .up.> log_sink_factory_table

        interface log_config_parser_base {
            {abstract} + parse_from_file(filepath: string_view)
            {abstract} + parse_from_text(filepath: string_view)
        }

        package toml {
            class toml_xxx_log_sink_factory {
                + toml_xxx_log_sink_factory(config)
            }
            log_sink_factory_base <|.. toml_xxx_log_sink_factory
            toml_xxx_log_sink_factory ..> xxx_log_sink

            interface toml_log_sink_config_parser_base {
                {abstract} + parse(table: toml::table) : shared_ptr<log_sink_factory_base>
            }
            toml_log_sink_config_parser_base ..> log_sink_factory_base

            class toml_xxx_log_sink_config_parser
            toml_log_sink_config_parser_base <|.. toml_xxx_log_sink_config_parser
            toml_xxx_log_sink_config_parser ..> toml_xxx_log_sink_factory

            class toml_log_config_parser {
                + parse_from_table(table: toml::table)
            }
            log_config_parser_base <|.. toml_log_config_parser
            toml_log_config_parser o-- toml_log_sink_config_parser_base
            toml_log_config_parser ..> log_sink_factory_table
            toml_log_config_parser ..> log_config
        }
    }
}

@enduml

@startuml iterations

title Abstract model of iteration logs

package logging {
    !includesub ./logger.puml!log_tag_view
    package sinks {
        !includesub ./logger.puml!log_sink
    }

    package iterations {
        class iteration_parameter_value<Value, ...> {
            + get() : Value
            + get(algorithm: Algorithm*) : Value
        }
        note bottom
            This will have some variations:
            * Function to get the current value.
            * Member function to get the current value.
            * Pointer to a variable.
            * Pointer to a member variable.
        endnote

        class iteration_parameter_formatter<Value> {
            + format(value: const Value&, buffer: fmt::memory_buffer&)
        }

        interface iteration_parameter_base {
            {abstract} + format_label_to(buffer: fmt::memory_buffer&)
            {abstract} + format_value_to(buffer: fmt::memory_buffer&)
            {abstract} + format_summary_to(buffer: fmt::memory_buffer&)
            {abstract} + label() : const string&
        }

        class iteration_parameter<Value>
        iteration_parameter_base <|.. iteration_parameter
        iteration_parameter o-- iteration_parameter_value
        iteration_parameter o-- iteration_parameter_formatter

        class iteration_logger<Algorithm> {
            + start(logger: logger)
            + append(parameter: shared_ptr<iteration_parameter_base>)
            + append(label: string, ...) : shared_ptr<...>
            + write_iteration()
            + write_iteration(algorithm: Algorithm*)
            + write_summary()
            + write_summary(algorithm: Algorithm*)
            - format_labels_to(buffer: fmt::memory_buffer&, algorithm: Algorithm*)
            - format_values_to(buffer: fmt::memory_buffer&, algorithm: Algorithm*)
            - format_summary_to(buffer: fmt::memory_buffer&, algorithm: Algorithm*)
        }
        iteration_logger o-- iteration_parameter_base
        iteration_logger o-- log_tag_view
        iteration_logger o-- log_sink
    }
}

@enduml