All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.reactor.logger.ReactiveLogger Maven / Gradle / Ivy

The newest version!
package org.zodiac.reactor.logger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Signal;
import reactor.core.publisher.SignalType;
import reactor.core.publisher.SynchronousSink;
import reactor.util.context.Context;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public abstract class ReactiveLogger {

    private ReactiveLogger() {
        super();
    }

    private static Logger log = LoggerFactory.getLogger(ReactiveLogger.class);

    private static final String CONTEXT_KEY = ReactiveLogger.class.getName();

    public static Function start(String key, String value) {
        return start(Collections.singletonMap(key, value));
    }

    public static Function start(String... keyAndValue) {
        Map map = new HashMap<>();
        for (int i = 0, len = keyAndValue.length / 2; i < len; i++) {
            map.put(keyAndValue[i * 2], keyAndValue[i * 2 + 1]);
        }
        return start(map);
    }

    public static Mono mdc(String key, String value) {
        return Mono
                .empty()
                .subscriberContext(start(key, value));
    }

    public static Mono mdc(String... keyAndValue) {
        return Mono
                .empty()
                .subscriberContext(start(keyAndValue));
    }

    public static Function start(Map context) {
        return ctx -> {
            Optional> maybeContextMap = ctx.getOrEmpty(CONTEXT_KEY);
            if (maybeContextMap.isPresent()) {
                maybeContextMap.get().putAll(context);
                return ctx;
            } else {
                return ctx.put(CONTEXT_KEY, new LinkedHashMap<>(context));
            }
        };
    }

    public static  void log(Context context, Consumer> logger) {
        Optional> maybeContextMap = context.getOrEmpty(CONTEXT_KEY);
        if (!maybeContextMap.isPresent()) {
            logger.accept(new HashMap<>());
        } else {
            Map ctx = maybeContextMap.get();
            MDC.setContextMap(ctx);
            try {
                logger.accept(ctx);
            } finally {
                MDC.clear();
            }
        }
    }

    public static  Consumer> on(SignalType type, BiConsumer, Signal> logger) {
        return signal -> {
            if (signal.getType() != type) {
                return;
            }
            Optional> maybeContextMap
                    = signal.getContext().getOrEmpty(CONTEXT_KEY);
            if (!maybeContextMap.isPresent()) {
                logger.accept(new HashMap<>(), signal);
            } else {
                Map ctx = maybeContextMap.get();
                MDC.setContextMap(ctx);
                try {
                    logger.accept(ctx, signal);
                } finally {
                    MDC.clear();
                }
            }
        };
    }

    public static Mono mdc(Consumer> consumer) {
        return Mono
                .subscriberContext()
                .doOnNext(ctx -> {
                    Optional> maybeContextMap = ctx.getOrEmpty(CONTEXT_KEY);
                    if (maybeContextMap.isPresent()) {
                        consumer.accept(maybeContextMap.get());
                    } else {
                        consumer.accept(Collections.emptyMap());
                        log.warn("logger context is empty,please call publisher.subscriberContext(ReactiveLogger.mdc()) first!");
                    }
                })
                .then();
    }

    public static  BiConsumer> handle(BiConsumer> logger) {
        return (t, rFluxSink) -> {
            log(rFluxSink.currentContext(), context -> {
                logger.accept(t, rFluxSink);
            });
        };
    }

    public static  Consumer> onNext(Consumer logger) {
        return on(SignalType.ON_NEXT, (ctx, signal) -> {
            logger.accept(signal.get());
        });
    }

    public static  Consumer> onComplete(Runnable logger) {
        return on(SignalType.ON_COMPLETE, (ctx, signal) -> {
            logger.run();
        });
    }

    public static  Consumer> onError(Consumer logger) {
        return on(SignalType.ON_ERROR, (ctx, signal) -> {
            logger.accept(signal.getThrowable());
        });
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy