{"id":22750108,"url":"https://github.com/pwall567/log-front-api","last_synced_at":"2026-02-17T06:32:21.098Z","repository":{"id":57737619,"uuid":"488885086","full_name":"pwall567/log-front-api","owner":"pwall567","description":"Logging Interface API","archived":false,"fork":false,"pushed_at":"2025-11-09T04:30:55.000Z","size":31,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-09T04:45:58.933Z","etag":null,"topics":["api","java","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":"2022-05-05T08:10:45.000Z","updated_at":"2025-11-09T04:30:41.000Z","dependencies_parsed_at":"2025-04-12T23:25:16.874Z","dependency_job_id":"05887c69-d410-4e1b-9205-f8751bd5960b","html_url":"https://github.com/pwall567/log-front-api","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/pwall567/log-front-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pwall567","download_url":"https://codeload.github.com/pwall567/log-front-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwall567%2Flog-front-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29535974,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T05:00:25.817Z","status":"ssl_error","status_checked_at":"2026-02-17T04:57:16.126Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["api","java","logging"],"created_at":"2024-12-11T04:12:25.120Z","updated_at":"2026-02-17T06:32:21.088Z","avatar_url":"https://github.com/pwall567.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# log-front-api\n\n[![Build Status](https://github.com/pwall567/log-front-api/actions/workflows/build.yml/badge.svg)](https://github.com/pwall567/log-front-api/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-api?label=Maven%20Central)](https://central.sonatype.com/artifact/io.jstuff/log-front-api)\n\nLogging Interface API\n\n## Background\n\nThe library is a further development (and simplification) of the library\n[`log-front`](https://github.com/pwall567/log-front).\nThat library was an attempt to solve a long-standing problem in the creation of utility libraries:\n- the library wishes to make use of logging\n- the library wishes to have its own logging integrated with the logging output by the overall project\n- the library will be only a part of any project that makes use of it, and cannot dictate the form of logging used in\n  the project as a whole\n- the library must not bring in transitive dependencies that may cause conflicts, or that may cause conditional loading\n  to make incorrect assumptions about the form of logging in use\n- the library must be simple to integrate, and must not require `\u003cexclusions\u003e` (Maven) or `exclude` (Gradle) to avoid\n  incorrect dependency usage\n\nThis library provides a minimum set of interfaces which do not include the underlying functionality, allowing utility\nlibraries to be created with no references to implementation classes.\n\nThe original [`log-front`](https://github.com/pwall567/log-front) library has been modified to be an implementation of\nthis API library; the library [`log-front-kotlin`](https://github.com/pwall567/log-front-kotlin) is a Kotlin\nimplementation of the API.\n\n## Quick Start\n\nAll logging is performed through an instance of the `Logger` interface, and such instances are obtained from an\nimplementation of the `LoggerFactory` interface.\nA library class that requires to use logging should be provided with a `LoggerFactory`, either as a constructor\nparameter or by dependency injection, and it can then use this to create `Logger` instances to perform the logging\noperations.\n\n```java\nimport io.jstuff.log.Logger;\nimport io.jstuff.log.LoggerFactory;\n\npublic class ClassThatLogs {\n    private final Logger log;\n    public ClassThatLogs(LoggerFactory\u003c?\u003e loggerFactory) {\n        log = loggerFactory.getLogger();\n    }\n    public void doSomething(String value) {\n        log.info(() -\u003e \"Doing something with \" + value);\n        // etc.\n    }\n}\n```\n\n## Logging Levels\n\nThe concept of a logging level appears in most logging libraries.\nIn `log-front-api` there are 5 levels, specified in the [`Level`](#level) enum.\n\nIt is possible (but not necessary) to specify the initial level for a `Logger` when requesting it from the\n`LoggerFactory`; not all implementing classes make use of an initial level specified in this way.\n\n## Time\n\nIt can be useful to be able to specify the time of a log entry, as opposed to letting the logging system apply the\ncurrent time (possibly using a supplied `Clock` \u0026ndash; see [below](#clock)).\nFor example, when creating a database record, it can be valuable to have the log entry show the same creation time as\nthat stored in the record.\nAlso, when log entries are written in a separate thread from the one creating them, it is clearly preferable for the log\nentries to be tagged with the time they were created, not when they are were later output.\n\nTo accommodate this requirement, all of the logging function have forms that take a time (as an `Instant`).\nIt should be noted that not all underlying log mechanisms allow the time to be specified, so in many cases this time\nparameter will be ignored (in particular, `slf4j` lacks the ability to specify the time of a log entry).\n\n## Clock\n\nFor testing purposes, a `java.time.Clock` object can be specified when requesting a `Logger`.\nIt can be useful in unit tests to provide a fixed `Clock` so that date- or time-sensitive operations can be tested\nreliably.\nAllowing the same `Clock` to be used for logging can assist in confirming that the log messages produced correspond with\nthe functions under test.\n\nFew `Logger` implementations currently make use of a `Clock` specified in this manner, and for those that don\u0026rsquo;t,\nthe functionality may safely be ignored.\nIf the `Clock` is not specified, the system clock will be used (unless the time is [specified explicitly](#time) on the\nlogging call).\n\n## Reference\n\n### LoggerFactory\n\n#### Interface\n\n`LoggerFactory` is a generic interface, parameterised by the type of `Logger` returned:\n```java\npublic interface LoggerFactory\u003cL extends Logger\u003e {\n    // contents...\n}\n```\n\n#### `getLogger()`\n\nThe interface specifies a number of variations of the `getLogger()` function (the actual return type is `L`, the\nparameterised type of the `LoggerFactory`):\n\n- `Logger getLogger()`\n- `Logger getLogger(Level level)`\n- `Logger getLogger(Clock clock)`\n- `Logger getLogger(Level level, Clock clock)`\n- `Logger getLogger(Class\u003c?\u003e javaClass)`\n- `Logger getLogger(Class\u003c?\u003e javaClass, Level level)`\n- `Logger getLogger(Class\u003c?\u003e javaClass, Clock clock)`\n- `Logger getLogger(Class\u003c?\u003e javaClass, Level level, Clock clock)`\n- `Logger getLogger(String name)`\n- `Logger getLogger(String name, Level level)`\n- `Logger getLogger(String name, Clock clock)`\n- `Logger getLogger(String name, Level level, Clock clock)`\n\nImplementing classes need only implement the last function; default implementations for the other functions delegate to\nthe last function, supplying default values for the parameters as follows:\n\n1. **Logger Name** \u0026ndash; if a `Class\u003c?\u003e` is specified, the qualified class name of the class is used; if no logger\n   name or class is provided, the qualified class name of the calling class is used.\n2. **Level** \u0026ndash; if no level is specified, the default level for the `LoggerFactory` is used (see\n   [`getDefaultLevel()`](#getdefaultlevel)).\n3. **Clock** \u0026ndash; if no clock is specified, the default clock for the `LoggerFactory` is used (see\n   [`getDefaultClock()`](#getdefaultclock)).\n\n#### `getDefaultLevel()`\n\nThe `getDefaultLevel()` function returns the default level for this `LoggerFactory`:\n\n- `Level getDefaultLevel()`\n\nThe default implementation of this function returns `Level.INFO`.\n\n#### `setDefaultLevel()`\n\nThe `setDefaultLevel()` function sets the default level for this `LoggerFactory`:\n\n- `void setDefaultLevel(Level level)`\n\nThe default implementation of this function stores the supplied value, to be returned by subsequent calls to\n`getDefaultLevel()`\n\n#### `getDefaultClock()`\n\nThe `getDefaultClock()` function returns the default clock for this `LoggerFactory`:\n\n- `Clock getDefaultClock()`\n\nThe default implementation of this function returns the system clock.\n\n#### `setDefaultClock()`\n\nThe `setDefaultClock()` function sets the default clock for this `LoggerFactory`:\n\n- `void setDefaultClock(Clock clock)`\n\nThe default implementation of this function stores the supplied value, to be returned by subsequent calls to\n`getDefaultClock()`\n\n### Logger\n\nThe `Logger` interface specifies a number of logging operations related to the different logging levels:\n\n- `void trace(Object message)`\n- `void debug(Object message)`\n- `void info(Object message)`\n- `void warn(Object message)`\n- `void error(Object message)`\n- `void error(Throwable throwable, Object message)`\n- `void log(Level level, Object message)`\n\nThe message is specified as being of type `Object`, and may be nullable \u0026ndash; in most cases it will be converted to\n`String` by `String.valueOf(message)` (or equivalent), but that is dependent on the `Logger` implementation.\nThe second `error` function takes a `Throwable` as well as the message; how the `Throwable` is handled also depends on\nthe implementation.\nThe last function in the list allows the level to be specified as a parameter.\n\nTo specify the time of a logging event explicitly, the followings forms are also available:\n\n- `void trace(Instant time, Object message)`\n- `void debug(Instant time, Object message)`\n- `void info(Instant time, Object message)`\n- `void warn(Instant time, Object message)`\n- `void error(Instant time, Object message)`\n- `void error(Instant time, Throwable throwable, Object message)`\n- `void log(Instant time, Level level, Object message)`\n\nAs noted above, many implementations will ignore the time supplied.\n\nThere are also tests for the logging level of the `Logger`:\n\n- `boolean isTraceEnabled()`\n- `boolean isDebugEnabled()`\n- `boolean isInfoEnabled()`\n- `boolean isWarnEnabled()`\n- `boolean isErrorEnabled()`\n- `boolean isEnabled(Level level)`\n\nThe default implementations of these functions use the level in the `Logger`, not in the underlying implementation, so\nunless the level is kept in sync with the implementation, the tests are not likely to be useful in that form, and must\nbe overridden.\n\nLastly, there are a set of logging functions that take a `Supplier\u003cObject\u003e` lambda parameter.\nThese all have default implementations that call the appropriate `isXxxxEnabled()` function, and only if true, invoke\nlambda to create the message object.\nThis is the recommended means of logging complex messages, avoiding the cost of creating the message if it is not going\nto be used.\n\n- `void trace(Supplier\u003cObject\u003e messageSupplier)`\n- `void debug(Supplier\u003cObject\u003e messageSupplier)`\n- `void info(Supplier\u003cObject\u003e messageSupplier)`\n- `void warn(Supplier\u003cObject\u003e messageSupplier)`\n- `void error(Supplier\u003cObject\u003e messageSupplier)`\n- `void error(Throwable throwable, Supplier\u003cObject\u003e messageSupplier)`\n- `void log(Level level, Supplier\u003cObject\u003e messageSupplier)`\n\n- `void trace(Instant time, Supplier\u003cObject\u003e messageSupplier)`\n- `void debug(Instant time, Supplier\u003cObject\u003e messageSupplier)`\n- `void info(Instant time, Supplier\u003cObject\u003e messageSupplier)`\n- `void warn(Instant time, Supplier\u003cObject\u003e messageSupplier)`\n- `void error(Instant time, Supplier\u003cObject\u003e messageSupplier)`\n- `void error(Instant time, Throwable throwable, Supplier\u003cObject\u003e messageSupplier)`\n- `void log(Instant time, Level level, Supplier\u003cObject\u003e messageSupplier)`\n\nAs with the other `error` functions, there are versions that take a `Throwable`.\n\n### Level\n\nThe `Level` enum specifies five logging levels.\nIn increasing order of severity, they are:\n\n- `TRACE`\n- `DEBUG`\n- `INFO`\n- `WARN`\n- `ERROR`\n\nThese will mostly correspond to the level mechanism of the underlying implementation, but the documentation for the\nimplementing class should be consulted for details.\n\nThe `Level` includes the function `isEnabled` to simplify testing whether the `Level` is enabled for a nominated level\nand all higher levels:\n\n- `boolean isEnabled(Level level)`\n\n### LoggerException\n\nAll exceptions thrown by the library are instances of `LoggerException`, which extends `RuntimeException` (and are\ntherefore not checked exceptions).\n\n### NullLoggerFactory\n\nThe `NullLoggerFactory` is an implementation of `LoggerFactory` that returns a `NullLogger`.\n\n### NullLogger\n\nA `NullLogger` is a `Logger` that outputs nothing \u0026ndash; it includes null implementations of all the logging functions,\nalong with implementations of the `isEnabled()` functions that always return `false`.\n\n## Dependency Specification\n\nThe latest version of the library is 3.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-api\u003c/artifactId\u003e\n      \u003cversion\u003e3.0\u003c/version\u003e\n    \u003c/dependency\u003e\n```\n### Gradle\n```groovy\n    implementation 'io.jstuff:log-front-api:3.0'\n```\n### Gradle (kts)\n```kotlin\n    implementation(\"io.jstuff:log-front-api:3.0\")\n```\n\nPeter Wall\n\n2025-11-09\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwall567%2Flog-front-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpwall567%2Flog-front-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwall567%2Flog-front-api/lists"}