001/* 002 * Copyright (C) 2019 Michael N. Lipp (http://www.mnl.de) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package de.mnl.osgi.lf4osgi.core; 018 019import java.security.AccessController; 020import java.security.PrivilegedAction; 021import java.util.Optional; 022import java.util.Queue; 023import java.util.concurrent.ConcurrentLinkedQueue; 024import org.osgi.framework.Bundle; 025import org.osgi.service.log.LogLevel; 026import org.osgi.service.log.Logger; 027import org.osgi.service.log.LoggerFactory; 028 029/** 030 * A factory for creating {@link BufferingLogger}s. 031 */ 032public class BufferingLoggerFactory implements LoggerFactory { 033 034 public static final String LOG_THRESHOLD_PROPERTY 035 = "de.mnl.osgi.lf4osgi.bufferThreshold"; 036 public static final String BUFFER_SIZE_PROPERTY 037 = "de.mnl.osgi.lf4osgi.bufferSize"; 038 @SuppressWarnings("PMD.LooseCoupling") 039 private final Queue<BufferedEvent> events; 040 private LogLevel threshold = LogLevel.DEBUG; 041 private int bufferSize = 100; 042 043 /** 044 * Instantiates a new buffering logger factory with an 045 * event buffer with given size, buffering only events with 046 * at least the given threshold. 047 */ 048 public BufferingLoggerFactory() { 049 super(); 050 this.events = new ConcurrentLinkedQueue<>(); 051 AccessController.doPrivileged(new PrivilegedAction<Void>() { 052 @Override 053 public Void run() { 054 threshold = Optional.ofNullable(System 055 .getProperty(LOG_THRESHOLD_PROPERTY)) 056 .map(LogLevel::valueOf).orElse(LogLevel.TRACE); 057 bufferSize = Optional.ofNullable(System 058 .getProperty(BUFFER_SIZE_PROPERTY)) 059 .map(Integer::parseInt).orElse(1000); 060 return null; 061 } 062 }); 063 } 064 065 /** 066 * Sets the buffer size. 067 * 068 * @param bufferSize the buffer size 069 * @return the buffering logger factory 070 */ 071 public BufferingLoggerFactory setBufferSize(int bufferSize) { 072 this.bufferSize = bufferSize; 073 while (events.size() > bufferSize) { 074 events.poll(); 075 } 076 return this; 077 } 078 079 /** 080 * Sets the threshold. 081 * 082 * @param threshold the threshold 083 * @return the buffering logger factory 084 */ 085 public BufferingLoggerFactory setThreshold(LogLevel threshold) { 086 this.threshold = threshold; 087 return this; 088 } 089 090 public LogLevel threshold() { 091 return threshold; 092 } 093 094 /** 095 * Adds the event, removing the oldest event if the buffer sise is reached. 096 * 097 * @param event the event 098 */ 099 public void addEvent(BufferedEvent event) { 100 if (events.size() == bufferSize) { 101 events.poll(); 102 } 103 events.add(event); 104 } 105 106 /** 107 * Forward all buffered events. 108 * 109 * @param factory the factory 110 */ 111 public void flush(LoggerFactory factory) { 112 while (true) { 113 BufferedEvent event = events.poll(); 114 if (event == null) { 115 break; 116 } 117 event.forward(factory); 118 } 119 } 120 121 @Override 122 public Logger getLogger(String name) { 123 throw new UnsupportedOperationException(); 124 } 125 126 @Override 127 public Logger getLogger(Class<?> clazz) { 128 throw new UnsupportedOperationException(); 129 } 130 131 @Override 132 public <L extends Logger> L getLogger(String name, Class<L> loggerType) { 133 throw new UnsupportedOperationException(); 134 } 135 136 @Override 137 public <L extends Logger> L getLogger(Class<?> clazz, Class<L> loggerType) { 138 throw new UnsupportedOperationException(); 139 } 140 141 @SuppressWarnings("unchecked") 142 @Override 143 public <L extends Logger> L getLogger(Bundle bundle, String name, 144 Class<L> loggerType) { 145 return (L) new BufferingLogger(this, bundle, name); 146 } 147 148}