{"id":22750078,"url":"https://github.com/pwall567/log-front","last_synced_at":"2026-02-14T23:02:54.451Z","repository":{"id":57737617,"uuid":"301260898","full_name":"pwall567/log-front","owner":"pwall567","description":"Logging interface","archived":false,"fork":false,"pushed_at":"2025-03-13T13:04:45.000Z","size":126,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-21T08:56:24.986Z","etag":null,"topics":["java","library","logging"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pwall567.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-10-05T01:05:25.000Z","updated_at":"2025-03-13T13:04:28.000Z","dependencies_parsed_at":"2024-02-25T12:24:25.922Z","dependency_job_id":"0df8ba61-1526-4bdc-8d9a-25c40ac2b320","html_url":"https://github.com/pwall567/log-front","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/pwall567/log-front","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pwall567","download_url":"https://codeload.github.com/pwall567/log-front/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front/sbom","scorecard":{"id":750706,"data":{"date":"2025-08-11","repo":{"name":"github.com/pwall567/log-front","commit":"76fc2068ec25a8f489d9a012055a57efefba4fb9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/deploy.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/pwall567/log-front/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/pwall567/log-front/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/deploy.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/pwall567/log-front/deploy.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/deploy.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/pwall567/log-front/deploy.yml/main?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/deploy.yml:7"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T20:16:34.686Z","repository_id":57737617,"created_at":"2025-08-22T20:16:34.686Z","updated_at":"2025-08-22T20:16:34.686Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278302774,"owners_count":25964572,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","library","logging"],"created_at":"2024-12-11T04:12:16.688Z","updated_at":"2026-02-14T23:02:54.445Z","avatar_url":"https://github.com/pwall567.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# log-front\n\n[![Build Status](https://github.com/pwall567/log-front/actions/workflows/build.yml/badge.svg)](https://github.com/pwall567/log-front/actions/workflows/build.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Maven Central](https://img.shields.io/maven-central/v/io.jstuff/log-front?label=Maven%20Central)](https://central.sonatype.com/artifact/io.jstuff/log-front)\n\nSimple logging interface and basic implementation.\n\n## Important\n\nStarting from version 5.0, this is a significant reworking of the `log-front` library.\nThe interfaces that make up the principal API for the library have been moved to a new library\n[`log-front-api`](https://github.com/pwall567/log-front-api), with the `log-front` library retaining the original\nimplementation classes, along with new implementations that make use of an extensible appender and formatter structure.\n\nThese changes have been motivated by two factors:\n1. A desire to have a simple cut-down API that would not require implementation code to be included with all uses of the\n   library, and\n2. A realisation that the commonly-used logging implementations like `log4j` were overly complex, with that excessive\n   complexity being a potential source of dangerous vulnerabilities such as the one reported in late 2021.\n\nThe original `log-front` implementation was written in the expectation that users would employ it as a fa\u0026ccedil;ade to\nan `slf4j`-based library or to Java Logging, and the console logger implementation included was somewhat rudimentary.\nThe new version includes a more full-featured log appender and formatter mechanism, allowing it to be used as a complete\nreplacement for those libraries.\n\nOnly a single implementation of the `LogAppender` interface (`PrintStreamAppender`) and the `LogFormatter` interface\n(`BasicFormatter`) are currently provided, but the interfaces are straightforward, and users should be able to provide\ncustom implementations without too much difficulty.\nAdditional appenders (such as a rolling file appender or a syslog appender) and formatters may be added in due course.\n\n## Background\n\nThis is a simple implementation of the [`log-front-api`](https://github.com/pwall567/log-front-api) (see that library\nfor a description of the motivation behind its creation).\n\nThe default behaviour is to use reflection to find the `slf4j` classes in the classpath \u0026ndash; if they are found, all\nlogging calls will be redirected to that mechanism.\nThe second choice is to use Apache Commons Logging, if those classes are found in the classpath.\nThe third choice is to use the Java Logging framework if indicated by the presence of a system property or\nconfiguration associated with that framework;\notherwise log messages will be output using a logger that writes to a `PrintStream` (default `stdout`).\n\nIf it is necessary to fit in with an existing logging framework other than `slf4j`, Apache Commons Logging or Java\nLogging, the API is designed to be simple to implement so that a thin interfacing layer can be created, accepting this\nAPI and invoking the required target logging mechanism.\n\nNew from version 4.0 onward is multi-line logging.\nThis is a security measure \u0026ndash; if an attacker is aware that input text is included in a log message, they may try to\ncreate fake log events by including a newline followed by what looks like a log message prefix in their text.\nThe library now splits messages containing line terminators into separate invocations of the underlying log output\nfunction, so each line of the log has the correct prefix.\n\n(The name `log-front` is a play on the name of the popular [Logback](https://logback.qos.ch/) project;\nalso on the fact that it is a front-end \u0026ndash; a fa\u0026ccedil;ade \u0026ndash; to an underlying logging system.)\n\n## Quick Start\n\nTo get an instance of `Logger`:\n```java\n    Logger log = Log.getLogger(\"name\");\n```\n\nThis will return one of the following:\n1. If the Gradle Logging classes are found in the classpath, a `ProxyLogger` which uses the `GradleProxy` will be\n   returned.\n2. If Gradle Logging is not found, but the `slf4j` classes are found in the classpath, a `ProxyLogger` which uses the\n   `Slf4jProxy` will be returned.\n3. If neither Gradle Logging nor `slf4j` is found, but the Apache Commons Logging classes are found in the classpath, a\n   `ProxyLogger` which uses the `ACLProxy` will be returned.\n4. If none of the first three options is found, but either the \"`java.util.logging.config.file`\" system property is\n   present or a file named \"`logging.properties`\" is present as a resource, then a `JavaLogger` will be returned.\n5. Otherwise, a `FormattingLogger` will be returned.\n\nThe name used in the `getLogger()` call may be a `String`, a `Class`, or it may be omitted, in which case the class of\nthe calling function will be used.\n\nThen, to use the `Logger`:\n```java\n    log.info(\"Message\"); // etc.\n```\n\nThe message may be any form of `Object`, and the `toString()` of the object will be invoked only if logging for the\nlevel implied by the function name is enabled for this `Logger`.\nWhen the message is a `String` (as in the above example), the `toString()` function will of course return the string\nitself.\nAlternative forms of the `info()` (_etc._) functions take a lambda returning the message object; this is the preferred\nmeans of specifying a complex message that is to be created only when needed.\n```java\n    log.info(() -\u003e \"Total records: \" + totalRecords);\n```\n\nYour IDE will show the functions available on the `Logger` object.\n\n## Reference Guide\n\nLogging requests are made via the `Logger` interface, and instances of classes implementing this interface are obtained\nfrom a `LoggerFactory` (or from the static method `Log.getLogger()`).\nThe API employs a `Level` enum, which corresponds with the logging level mechanism used in other libraries.\n\nThese interfaces and enum are documented in the [`log-front-api`](https://github.com/pwall567/log-front-api) project.\n\n### `Log`\n\nThe `Log` class contains a number of static functions.\nTo get a default `Logger` for a specified name or class:\n\n- `Log.getLogger(String name)`\n- `Log.getLogger(Class\u003c?\u003e javaClass)`\n- `Log.getLogger()`\n\nTo get the default `LoggerFactory`:\n- `Log.getDefaultLoggerFactory()`\n\nIt is also possible to set the default `LoggerFactory` to be used by subsequent calls to `getLogger()`:\n- `Log.setDefaultLoggerFactory(loggerFactory)`\n\nThe default `LoggerFactory` is initialised to a [`DynamicLoggerfactory`](#dynamicloggerfactory), but this may be\noverridden by the use of the `io.jstuff.log.defaultLoggerFactory` system property, which supplies the name of the\n`LoggerFactory` class to be used as default.\n\n### `LogAppender`\n\nThe `LogAppender` interface allows for the use of different output mechanisms for the log.\nIt specifies a single function:\n```java\n    void output(long millis, Logger logger, Level level, Object message, Throwable throwable);\n```\nIt also derives from `AutoCloseable`; it provides a default implementation of `close()` which does nothing.\n\nCurrently only a single implementation is provided, `PrintStreamAppender`, which outputs (unsurprisingly) to a\n`PrintStream`.\n\n### `LogFormatter`\n\nThe `LogFormatter` interface allows log output to be formatted as desired by the user.\nThe sole function required to be implemented is:\n```java\n    void format(long millis, Logger logger, Level level, Object message, Throwable throwable, IntConsumer outFunction);\n```\nThere is also an `AbstractFormatter` class which includes static functions to help with formatting the time, level and\nother text.\n\nThe only implementation currently provided, `BasicFormatter`, formats the log item with the time (using the time zone of\nthe `Clock`, formatted as hh:mm:ss.nnn), the level (right-padded to 5 characters), the logger name (left-truncated to 40\ncharacters) and the message.\nAnyone wishing to use a different format should consult the code of this class for guidance on how to format the log\nevent as required.\n\n### `LogListener`\n\nThe library provides a built-in mechanism for testing whether log items are output as expected.\nIf an object extending the `LogListener` abstract base class is created, it will be added to a list of listeners and\nwill be called for every log event\nCalling `close()` on the listener will remove it from the list, and because the `LogListener` class implements the\n`AutoCloseable` interface, a natural way of using it is within a try-with-resources block \u0026ndash; that way the listener\nwill be removed automatically when the block of code ends, normally or otherwise.\n\nThe `LogListener` implementation must provide the following function:\n```java\n    public abstract void receive(long time, Logger logger, Level level, Object message, Throwable throwable);\n```\nNote that the `Thread` (or any similar information) is not included in the listener arguments.\nThe function will be invoked in the same execution environment as the logging call, so any such information may be\nobtained from the environment if required.\n\nThe mechanism is intended to be completely non-intrusive \u0026ndash; it should be possible to write code that outputs log\nmessages using `Logger` objects obtained from the default `LoggerFactory`, and then to create tests that intercept the\nlog messages and check for correctness.\nWhen the code is run in a production situation with no listeners, the overhead of checking for them will be minuscule.\n\n**Note that the listener mechanism is global (and simplistic) \u0026ndash; it is intended solely for unit testing purposes.**\nOnly log messages output via this library will be presented to the listener; messages output to the underlying logging\nsystem by other means will not be visible.\nAnd because logging systems create their own timestamps, the times on messages captured by this mechanism may differ\nvery slightly from the times generated by the underlying system.\n\nNote also that any use of logging within a `LogListener` runs the risk of recursion; this must be avoided by (for\nexample) checking the identity of the `Logger` in the `receive()` function.\n\nThe [`log-front-test`](https://github.com/pwall567/log-front-test) library makes use of the `LogListener` mechanism to\nprovide a simple but effective testng mechanism.\n\n### `AbstractLoggerFactory`\n\nThe `AbstractLoggerFactory` is the abstract base class of all the `LoggerFactory` implementations described here.\nIt provides the following functions, which are available in all of the derived classes.\n\n- `Level getDefaultLevel()`\n- `void setDefaultLevel(Level)`\n- `Clock getDefaultClock()`\n- `void setDefaultClock(Clock defaultClock)`\n\nThe default level will initially be set to `INFO`, and the default clock will be set to the system clock.\n\n### `DynamicLoggerFactory`\n\nThe `DynamicLoggerFactory` is the default `LoggerFactory` used by the `Log.getLogger()` functions, unless overridden.\nIt is this class that checks for the presence of `slf4j` or Java Logging, as described earlier:\n\n1. If the `slf4j` classes are found in the classpath, an `Slf4jLogger` will be returned.\n2. If `slf4j` is not found, but either the \"`java.util.logging.config.file`\" system property is present or a file named\n   \"`logging.properties`\" is present as a resource, then a `JavaLogger` will be returned.\n3. Otherwise, a `FormattingLogger` with a `PrintStreamAppender` and a `BasicFormatter` will be returned.\n\nThe class derives from [`AbstractLoggerFactory`](#abstractloggerfactory), and therefore the functions of that class\nrelating to default level and clock are available on this one.\n\n### `FormattingLoggerFactory`\n\nThe `FormattingLoggerFactory` creates a `FormattingLogger`, which uses a `LogAppender` and a `LogFormatter` to output\nlog messages that follow a simple standardised format.\nThis is the main fallback `LoggerFactory` used if neither `slf4j` nor Java Logging is found in the run-time environment.\n\nThis class also derives from [`AbstractLoggerFactory`](#abstractloggerfactory), and therefore the functions of that\nclass relating to default level and clock are available on this one.\n\n### `FormattingLogger`\n\nThe `FormattingLogger` is implemented with a specific `LogAppender`, and it delegates all functionality to that object.\n\n### `LogAppender`\n\nObjects implementing the `LogAppender` interface are expected to output the formatted message to a specific output\nmechanism.\nOnly a single `LogAppender` \u0026ndash; `PrintStreamAppender` \u0026ndash; is currently available.\n\n### `PrintStreamAppender`\n\nThe `PrintStreamAppender` is an implementation that outputs to a `PrintStream` (default `System.out`).\n\n### `LogFormatter`\n\nObjects implementing the `LogFormatter` interface must format the message for output by the `LogAppender`.\nOnly a single `LogFormatter` \u0026ndash; `BasicFormatter` \u0026ndash; is currently available.\n\n### `BasicFormatter`\n\nThe `BasicFormatter` will format a message similar to the following:\n```text\n11:34:55.766 INFO  com.example.LoggingTest: Logging test line\n```\nThe date will be formatted using the system clock.\nA maximum of 40 characters will be output for the logger name; if the name is longer it will be truncated to 37\ncharacters preceded by three dots.\n\n### `JavaLoggerFactory`\n\nThe `JavaLoggerFactory` creates a `JavaLogger`, which uses the Java Logging functionality (often referred to by the\npackage name `java.util.logging`).\n\nThis class also derives from [`AbstractLoggerFactory`](#abstractloggerfactory), and therefore the functions of that\nclass relating to default level and clock are available on this one.\n\n### `JavaLogger`\n\nA `JavaLogger` outputs log messages using the Java Logging mechanism.\nThe configuration options of that mechanism may be used to format the log messages, or to enable or disable logging for\nspecific logger names.\n\n### `ProxyLogger`\n\nInstances of this `Logger` are created by `DynamicLoggerFactory` to handle logging via Gradle Logging, `slf4j` or Apache\nCommons Logging.\nIt has no publicly-accessible constructors.\n\n### `ConsoleLoggerFactory`\n\nThis was previously used to provide simple fallback logging functionality for cases where neither `slf4j` nor Java\nLogging was provided.\nIt has been superseded by `FormattingLoggerFactory` and will probably be removed in the near future.\n\n### `ConsoleLogger`\n\nSee [`ConsoleLoggerFactory`](#consoleloggerfactory) above.\n\n## Environment Variables\n\nThe following environment variables may be set to modify defaults used by the library:\n\n- `io.jstuff.log.defaultLoggerFactory`: the default `LoggerFactory` class name (must be an implementation of\n  `LoggerFactory\u003cL extends Logger\u003e`); if omitted, `DynamicLoggerFactory` is used.\n- `io.jstuff.log.defaultLevel`: the default `Level` to be used (must be `TRACE`, `DEBUG`, `INFO`, `WARN` or `ERROR`); if\n  omitted, `INFO` is used.\n\n## Gradle Logging\n\nGradle has its own logging mechanism and its own set of log levels.\nWhen used in a Gradle script or plugin, the automated logging mechanism determination described under\n[`DynamicLoggerFactory`](#dynamicloggerfactory) will detect the presence of the Gradle logging classes and use them in\npreference to any other logging framework.\n\nThe `log-front` logging levels are mapped to the Gradle levels as follows:\n\n| `log-front` | Gradle      |\n|-------------|-------------|\n| `ERROR`     | `ERROR`     |\n| `WARN`      | `WARN`      |\n| `INFO`      | `LIFECYCLE` |\n| `DEBUG`     | `INFO`      |\n| `TRACE`     | `DEBUG`     |\n\n## `slf4j`\n\nThe `slf4j` library, if used, is accessed entirely through reflection.\nThis is not as inefficient as it sounds \u0026ndash; the lookup process to find the method references is performed once only,\nand the method invocation through these references is the least costly aspect of reflection.\n\nThe reason for this design decision (as opposed to making the `slf4j` library an optional dependency) is to avoid any\npotential problems with vulnerabilities resulting from the use of a specific version of `slf4j`.\nWhilst there would be no actual vulnerability from using `slf4j` in this way, some vulnerability scanners might detect\nthe library reference and report an issue.\n\nIt should be noted that `slf4j` does not provide a mechanism for setting the logging level of an `org.slf4j.Logger`\nprogrammatically.\nWhen this library creates a `Logger` backed by an `slf4j` implementation, the setting of the logging level (whether by\nconstructor parameter or by `setLevel()`) is managed internally, and the testing of levels to determine whether a log\nmessage is to be output uses **BOTH** mechanisms \u0026ndash; that is, logging must be enabled in the `Logger` **AND** in the\nconfiguration of the `slf4j` implementation.\n\nTo route logging from this library to `slf4j`, the simplest method is to add `logback` to your build (check\n[Maven Central](https://mvnrepository.com/artifact/ch.qos.logback/logback-classic) for the latest version, but bear in\nmind that versions 1.4.x and later require the use of Java 11 or above):\n\n### Maven\n```xml\n    \u003cdependency\u003e\n      \u003cgroupId\u003ech.qos.logback\u003c/groupId\u003e\n      \u003cartifactId\u003elogback-classic\u003c/artifactId\u003e\n      \u003cversion\u003e1.3.15\u003c/version\u003e\n      \u003cscope\u003eruntime\u003c/scope\u003e\n    \u003c/dependency\u003e\n```\n### Gradle\n```groovy\n    runtimeOnly 'ch.qos.logback:logback-classic:1.3.15'\n```\n### Gradle (kts)\n```kotlin\n    runtimeOnly(\"ch.qos.logback:logback-classic:1.3.15\")\n```\n\n## Apache Commons Logging\n\nFrom version 7.0, the library also includes support for Apache Commons Logging.\nAs with `slf4j`, the underlying library is accessed through reflection.\n\n## Dependency Specification\n\nThe latest version of the library is 7.0, and it may be obtained from the Maven Central repository.\n\n### Maven\n```xml\n    \u003cdependency\u003e\n      \u003cgroupId\u003eio.jstuff\u003c/groupId\u003e\n      \u003cartifactId\u003elog-front\u003c/artifactId\u003e\n      \u003cversion\u003e7.0\u003c/version\u003e\n    \u003c/dependency\u003e\n```\n### Gradle\n```groovy\n    implementation 'io.jstuff:log-front:7.0'\n```\n### Gradle (kts)\n```kotlin\n    implementation(\"io.jstuff:log-front:7.0\")\n```\n\nPeter Wall\n\n2025-11-09\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwall567%2Flog-front","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpwall567%2Flog-front","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwall567%2Flog-front/lists"}