Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update README files #69

Merged
merged 19 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 3 additions & 187 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

118 changes: 77 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,79 +5,116 @@

# Spine Logging

Spine Logging is a versatile library designed for Kotlin and Java projects, with a potential
for multi-platform use. At present, we only provide a JVM implementation for Kotlin,
with a JavaScript implementation being our priority for future development.
Spine Logging is a versatile library designed for Kotlin and Java projects,
with a potential for multi-platform use.

This library draws inspiration from the logging API of [Google Flogger][flogger], and
the introduction of a fluent logging API in [SLF4J v2.0.0][fluent-slf4j].
As for now, only JVM target is supported, with a JavaScript implementation
being our priority for future development.

## Current status: Experimental

Please note that this library is still in the experimental phase of development and hence,
its API may undergo significant changes. As such, we advise using this library cautiously in
your projects until it has reached a stable release stage.

## Logging backends
API and implementation are largely inspired by [Google Flogger][flogger],
and the introduction of fluent logging API in [SLF4J in v2.0.0][fluent-slf4j].

Our JVM implementation currently employs Google Flogger.
Since Flogger is a logging facade, it requires a backend to perform the actual logging operations.
At the time of writing, the following Flogger backends are available:
## Current status: Experimental

* `com.google.flogger:flogger-system-backend:$floggerVersion` — utilizing `java.util.logging`.
* `com.google.flogger:flogger-log4j-backend:$floggerVersion` — utilizing Log4j.
* `com.google.flogger:flogger-log4j2-backend:$floggerVersion` — utilizing Log4j2.
* `com.google.flogger:flogger-slf4j-backend:$floggerVersion` — utilizing SLF4J (which is a facade itself!).
Please note that this library is still in the experimental phase of development,
and hence, its API may undergo significant changes. As such, we advise using
this library cautiously in your projects until it has reached a stable
release stage.

### How to Use `java.util.logging` as a backend
## Simple example

To use `java.util.logging` in your project, add the following dependency:
To start logging, at least the following dependencies are needed:

```kotlin
dependencies {
implementation("io.spine:spine-logging:$version")
runtimeOnly("io.spine:spine-logging-backend:$version")
}
```
The second dependency replaces the default Flogger backend with a backend that resolves issues
with using LogLevelMap in the project.

### Utilizing other backends
The default logging backend outputs all logged statements to the console.

All logging operations are done with an instance of `io.spine.logging.Logger`.
To get a logger, one can use the following:

If you prefer a backend other than java.util.logging, add dependencies that include a `runtimeOnly`
dependency for your chosen logging backend. For instance:
1. Make a logging class implement `WithLogging` interface.
2. Get a logger from `LoggingFactory`.

The interface provides a default method `logger()` that returns a logger
for the implementing class or object:

```kotlin
dependencies {
implementation("io.spine:spine-logging:$version")
runtimeOnly("com.google.flogger:flogger-log4j2-backend:$floggerVersion")
import io.spine.logging.WithLogging

class Example : WithLogging {
fun doSomething() {
logger() // Call to the default method of `WithLogging`.
.atWarning()
.log { "..." }
}
}
```

For SLF4J as a backend, your dependencies should also include a backend for SLF4J. For example:
`LoggingFactory` has two methods that return a logger for the enclosing class
and for the given `KClass`:

```kotlin
import io.spine.logging.LoggingFactory

class App {
private val logger1 = LoggingFactory.forEnclosingClass()
private val logger2 = LoggingFactory.loggerFor(this::class)

fun doSomething() {
check(logger1 === logger2) // There is always one logger per class.
logger1.atWarning()
.log { "..." }
}
}
```

## Logging backends

A logging backend handles an actual output of the logged statement.
`LogRecord` may be printed to the console, be written to a file or sent by
the network to some log-aggregating service. It all is up to a chosen backend
and its configuration.

The following backends are available:

* `io.spine:spine-logging-backend` – the default JUL-based backend.
* `io.spine:spine-logging-log4j2-backend` – Log4j2 backend.

Put a chosen backend to `runtimeOnly` configuration, and the logging library
will discover it in the runtime.

An example usage of Log4j2 backend:

```kotlin
dependencies {
implementation("io.spine:spine-logging:$version")
runtimeOnly("com.google.flogger:flogger-slf4j-backend:$floggerVersion")
runtimeOnly("org.slf4j:slf4j-reload4j:$slf4jVersion")
runtimeOnly("io.spine:spine-logging-log4j2-backend:$version")
}
```

## Logging context
Please note, only one backend implementation should be present in the runtime.
Two or more backends will cause an exception because the logging framework
will not be able to understand, which one should be used.

## Logging contexts

A logging context refers to a set of attributes that are attached to all log records while
a context is installed. For instance, you can attach a user ID to all log records for
the current request.
A logging context refers to a set of attributes that are attached to all log
records while a context is installed. For instance, you can attach a user ID
to all log records for the current request.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last sentence probably deserves a code snippet. But I don't insist at the moment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I've decided to add a snippet because it's unclear how to use custom contexts. There's no example anywhere.

BTW, I've not tried them before.

It works, but there are several suggestions: #70, #71, #72.


The default implementation provides a no-op context. To use a logging context, a `runtimeOnly`
dependency for a context implementation should be added along with the above dependencies.
The default implementation provides a no-op context. To use a logging context,
a `runtimeOnly` dependency for a context implementation should be added along
with the mentioned above dependencies.

If your project does not use gRPC, use the following dependency:

```kotlin
dependencies {
//...
rutimeOnly("io.spine:spine-logging-context:$version")
}
```
Expand All @@ -86,8 +123,7 @@ If your project does use gRPC, add the following dependency:

```kotlin
dependencies {
//...
rutimeOnly("com.google.flogger:flogger-grpc-context:$floggerVersion")
rutimeOnly("io.spine:spine-logging-grpc-context:$version")
}
```

Expand Down
Loading
Loading