quarkus-logging-manager icon indicating copy to clipboard operation
quarkus-logging-manager copied to clipboard

should be able to add logger level at runtime

Open survivant opened this issue 4 years ago • 2 comments

from the UI and REST API, we should be able to add logger at runtime.

ex : I could have : org.abc.database.level=ERROR but I want to add org.abc.label=debug

I didn't saw a ADD logger from the UI

survivant avatar Mar 08 '21 14:03 survivant

Yes this will have to be implemented. But that would be a good addition

phillip-kruger avatar Mar 08 '21 14:03 phillip-kruger

I created a custom implementation for this. We had at my job a implementation using SpringBoot and I had to do the same thing for quarkus.

I did a HACK. I didn't modify any of quarkus-logging-manager instead a use a RestClient to call logging-manager endpoint from within my application.

I also create a new controller that will handle to logic.

@Slf4j
@Path("/api/v1/loggers")
@Produces(MediaType.APPLICATION_JSON)
public class LoggingController {

    @Inject
    @RestClient
    LoggingServiceRestConnector loggingServiceRestConnector;

    @Inject
    ObjectMapper mapper;

    JsonPersistence persistenceOriginal;    

    @PostConstruct
    void init() throws Exception {
        // save original logger levels on disk
        persistence.save(getAvailableLoggers(), "original.json");
        
        // load overriden loggers
        applyPersistedLogLevels();
    }

    private void applyPersistedLogLevels() throws Exception {
        log.debug("Loading persisted log levels....");
        persistence.findAll()
                .forEach(loggerSetting -> loggingServiceRestConnector.updateLogger(loggerSetting.getLoggerName(), loggerSetting.getConfiguredLevel())
                );
        log.debug("....persisted log levels loaded");
    }

    @Path("/")
    @GET
    public LoggerSetting getLogger(@QueryParam("loggerName") String loggerName) throws JsonProcessingException {
        var logger = loggingServiceRestConnector.getLogger(loggerName);

        var jsonNode = mapper.readTree(logger);

        return createLoggerSetting(jsonNode);
    }

    @Path("/available")
    @GET
    public List<LoggerSetting> getAvailableLoggers() throws JsonProcessingException {
        var logger = loggingServiceRestConnector.getLoggers();

        var list = new ArrayList<LoggerSetting>();

        var jsonNode = mapper.readTree(logger);

        for (var node : jsonNode) {
            list.add(createLoggerSetting(node));
        }

        return list;
    }

    private static LoggerSetting createLoggerSetting(JsonNode jsonNode) {
        var loggerSetting = new LoggerSetting();

        var name = jsonNode.get("name");
        var effectiveLevel = jsonNode.get("effectiveLevel");
        var configuredLevel = jsonNode.get("configuredLevel");

        if (name != null) {
            loggerSetting.setLoggerName(name.asText());
        }

        if (effectiveLevel != null) {
            loggerSetting.setEffectiveLevel(effectiveLevel.asText());
        }

        if (configuredLevel != null) {
            loggerSetting.setConfiguredLevel(configuredLevel.asText());
        }

        return loggerSetting;
    }

    @Path("/overridden")
    @GET
    public Collection<LoggerSetting> getOverriddenLoggers() throws BeanPersistenceException {
        return loggingSettingsService.getOverriddenLoggers();
    }

    @Path("/overridden")
    @PUT
    public LoggerSetting updateLogger(LoggerSetting logger) throws BeanPersistenceException {
        loggingServiceRestConnector.updateLogger(logger.getUniqueKey(), logger.getConfiguredLevel());

        // must save override
       persistence.update(logger);

        return logger;
    }

    @Path("/overridden")
    @DELETE
    public LoggerSetting resetLogger(String loggerName) throws BeanPersistenceException, JsonProcessingException {
        if (loggerName == null) return null;

        var original = persistence.findOriginalById(loggerName);

        if (original != null) {
            if (original.getConfiguredLevel() != null) {
                loggingServiceRestConnector.updateLogger(loggerName, original.getConfiguredLevel());
            } else {
                loggingServiceRestConnector.updateLogger(loggerName, original.getEffectiveLevel());
            }
        }

        var loggerSetting = getLogger(loggerName);

        // must remove override
        persistence.remove(loggerSetting);

        return loggerSetting;
    }
}

I tweak a little bit my code to show what was done without been to explicit

at startup

  1. call logger-manager to get all the loggers
  2. save those loggers into original.json
  3. load the overriden.json that contains all the loggers config
  4. apply those configs to logger-manager.update(loggername, level)

at runtime

  1. when a level change, it need to save the new level into oerriden.json
  2. send the new level to logging-manager

to reset a logger level

  1. read the original value of the logger from original.json
  2. sent that lavel to logging-manager

with that.. each time that I kill my application, it will reload my previous loggers settings.

PS. the reason that I created a new controler, it's because I had to respect the same URL that we had for SpringBoot

survivant avatar Jun 09 '21 17:06 survivant