herlanS_ преди 4 години
родител
ревизия
fc4c90b5b2

+ 1 - 0
.gitignore

@@ -24,6 +24,7 @@ target/
 /nbbuild/
 /dist/
 /web/**
+/log/**
 /nbdist/
 /.nb-gradle/
 build/

+ 21 - 1
pom.xml

@@ -20,14 +20,34 @@
 	</properties>
 
 	<dependencies>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter</artifactId>
+			<exclusions>
+				<exclusion>
+					<groupId>org.springframework.boot</groupId>
+					<artifactId>spring-boot-starter-logging</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-web</artifactId>
+			<artifactId>spring-boot-starter-log4j2</artifactId>
 		</dependency>
+
+		<dependency>
+			<groupId>org.apache.logging.log4j</groupId>
+			<artifactId>log4j-web</artifactId>
+			<version>2.13.3</version>
+		</dependency>
+
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-websocket</artifactId>
 		</dependency>
+
 		<dependency>
 			<groupId>com.fasterxml.jackson.module</groupId>
 			<artifactId>jackson-module-kotlin</artifactId>

+ 25 - 10
src/main/kotlin/co/id/datacomsolusindo/ipphonebridge/BridgeFIlter.kt

@@ -3,6 +3,7 @@ package co.id.datacomsolusindo.ipphonebridge
 import com.fasterxml.jackson.core.type.TypeReference
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.apache.commons.io.IOUtils
+import org.apache.logging.log4j.LogManager
 import org.springframework.context.annotation.Configuration
 import org.springframework.core.Ordered
 import org.springframework.core.annotation.Order
@@ -61,9 +62,12 @@ class SimpleCORSFilter : Filter {
 }
 
 @Component
-@Order(2)
+@Order(1)
 class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoader: ResourceLoader) : Filter {
     override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
+        val startTime = System.nanoTime()
+
+
         val req = request as HttpServletRequest
         val res = response as HttpServletResponse
         val splitPath = req.requestURI.split("/")
@@ -89,6 +93,8 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad
                     rb.queryString = req.parameterMap
                     Singletons.requestInstance[reqId] = RequestQue(reqId, rb, null)
 
+
+
                     template.convertAndSend("/topic/$client", RequestTrigger(reqId))
 
 
@@ -102,6 +108,9 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad
                             res.writer.write("{\"message\":\"Request timeout. Client not responding\"}")
                             res.flushBuffer()
                             Singletons.requestInstance.remove(reqId)
+                            val endTime = System.nanoTime()
+                            val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
+                            LogManager.getLogger("client.$client").info("Request failed, No Response. Time: $duration  UA: " + req.getHeader("User-Agent") + " From: " + InetAddress.getLocalHost().hostAddress + " To: " + req.requestURL.toString() + "?" + req.queryString)
                             return
                         }
                     }
@@ -124,6 +133,11 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad
                     res.flushBuffer()
 
                     Singletons.requestInstance.remove(reqId)
+                    val endTime = System.nanoTime()
+
+                    val duration = (endTime - startTime).toDouble() / 1000000 //divide by 1000000 to get milliseconds.
+                    LogManager.getLogger("client.$client").info("Request Success. Time: $duration  UA: " + req.getHeader("User-Agent") + " From: " + InetAddress.getLocalHost().hostAddress + " To: " + req.requestURL.toString() + "?" + req.queryString)
+
                     return
                 } else {
 
@@ -150,15 +164,16 @@ class BridgeFilter(private val template: SimpMessagingTemplate, val resourceLoad
     }
 }
 
-@Component
-@Order(1)
-class RequestFilter : Filter {
-    override fun doFilter(sreq: ServletRequest?, sres: ServletResponse?, fc: FilterChain?) {
-        val req = sreq as HttpServletRequest
-        println("Request With " + req.getHeader("User-Agent") + " Address " + InetAddress.getLocalHost().hostAddress + " To " + req.requestURL.toString() + "?" + req.queryString)
-        fc!!.doFilter(sreq, sres)
-    }
-}
+//@Component
+//@Order(1)
+//class RequestFilter : Filter {
+//    override fun doFilter(sreq: ServletRequest?, sres: ServletResponse?, fc: FilterChain?) {
+//        val req = sreq as HttpServletRequest
+////        AppLog.write(this.javaClass).info("Request With " + req.getHeader("User-Agent") + " Address " + InetAddress.getLocalHost().hostAddress + " To " + req.requestURL.toString() + "?" + req.queryString)
+//        //println("Request With " + req.getHeader("User-Agent") + " Address " + InetAddress.getLocalHost().hostAddress + " To " + req.requestURL.toString() + "?" + req.queryString)
+//        fc!!.doFilter(sreq, sres)
+//    }
+//}
 
 class RequestQue(val id: String, val requestBuilder: RequestBuilder, var responseObj: Resp?)
 

+ 142 - 7
src/main/kotlin/co/id/datacomsolusindo/ipphonebridge/IpPhoneBridgeApplication.kt

@@ -1,13 +1,25 @@
 package co.id.datacomsolusindo.ipphonebridge
 
+import org.apache.logging.log4j.Level
+import org.apache.logging.log4j.LogManager
+import org.apache.logging.log4j.Logger
+import org.apache.logging.log4j.core.Filter
+import org.apache.logging.log4j.core.config.Configurator
+import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory
+import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder
+import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder
+import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder
 import org.ini4j.Wini
 import org.springframework.boot.SpringApplication
 import org.springframework.boot.autoconfigure.SpringBootApplication
-import org.springframework.messaging.simp.SimpMessagingTemplate
+import org.springframework.context.event.EventListener
+import org.springframework.messaging.support.GenericMessage
 import org.springframework.scheduling.annotation.EnableScheduling
-import org.springframework.scheduling.annotation.Scheduled
 import org.springframework.stereotype.Component
+import org.springframework.web.socket.messaging.SessionSubscribeEvent
 import java.io.File
+import java.io.Serializable
+import java.time.LocalDateTime
 import java.util.*
 
 
@@ -20,19 +32,142 @@ fun main(args: Array<String>) {
     val ini = Wini(File("conf/general.ini"))
     properties["server.port"] = ini.get("server", "port")
     val sApp = SpringApplication(IpPhoneBridgeApplication::class.java)
+
     sApp.setDefaultProperties(properties)
     sApp.run(*args)
+
+    val builder = ConfigurationBuilderFactory.newConfigurationBuilder()
+    val console = builder.newAppender("stdout", "Console")
+
+    val appLog = builder.newAppender("appLog", "RollingFile")
+    appLog.addAttribute("fileName", "log/app/app.log")
+    appLog.addAttribute("filePattern", "log/app/\$\${date:yyyy - MM}/app-%d{yyyy-MM-dd}-%i.log.zip")
+
+    val flow: FilterComponentBuilder = builder.newFilter(
+            "MarkerFilter",
+            Filter.Result.ACCEPT,
+            Filter.Result.DENY)
+    flow.addAttribute("marker", "FLOW")
+
+    console.add(flow)
+
+    val standard = builder.newLayout("PatternLayout")
+    standard.addAttribute("pattern", "%d %p [%c{1}] %m%n")
+
+    val policies = builder.newLayout("Policies")
+    val timeBasedTriggeringPolicy = builder.newLayout("TimeBasedTriggeringPolicy")
+    val sizeBasedTriggeringPolicy = builder.newLayout("SizeBasedTriggeringPolicy")
+    sizeBasedTriggeringPolicy.addAttribute("size", "10 MB")
+    policies.addComponent(timeBasedTriggeringPolicy)
+    policies.addComponent(sizeBasedTriggeringPolicy)
+    appLog.addComponent(policies)
+    console.add(standard)
+    appLog.add(standard)
+    builder.add(console)
+    builder.add(appLog)
+    val rootLogger: RootLoggerComponentBuilder = builder.newRootLogger(Level.ERROR)
+    rootLogger.add(builder.newAppenderRef("stdout"))
+    builder.add(rootLogger)
+    val logger: LoggerComponentBuilder = builder.newLogger("co.id.datacomsolusindo.ipphonebridge", Level.DEBUG)
+    logger.add(builder.newAppenderRef("appLog"))
+    logger.addAttribute("additivity", false)
+    builder.add(logger)
+    Configurator.reconfigure(builder.build())
+    LogManager.getLogger("co.id.datacomsolusindo.ipphonebridge.IpPhoneBridgeApplication").info("Bridge Start")
+}
+
+class Client(
+        val number: String,
+        val lastRequest: LocalDateTime
+        //,val logger: Logger
+) : Serializable
+
+object ClientHolder {
+    private val clientMap: MutableMap<String, Client> = mutableMapOf()
+    fun load() = clientMap.toMap()
+    fun add(vararg pairs: Pair<String, Client>): Map<String, Client> {
+        clientMap.putAll(pairs)
+        return clientMap.toMap()
+    }
 }
 
 @Component
-class ScheduledMessage(val template: SimpMessagingTemplate) {
-    @Scheduled(fixedDelay = 1000)
-    fun sendMessageToGreetings() {
-        //template.convertAndSend("/topic/greetings", Greeting("Fire"))
-        //val headers = HttpHeaders()
+class WebSocketEventListener {
+    @EventListener(SessionSubscribeEvent::class)
+    fun handleSessionSubscribeEvent(event: SessionSubscribeEvent) {
+        val message = event.message as GenericMessage<*>
+        val simDestination = message.headers["simpDestination"] as String?
+        if (!simDestination!!.startsWith("/topic/healthCheck")) {
+            // do stuff
+            val clNum = simDestination.split("/")[2]
+            ClientHolder.add(Pair(clNum, Client(clNum, LocalDateTime.now())))
+
+            LogManager.getLogger(this.javaClass).info("clientConnected $simDestination")
+
+            val builder = ConfigurationBuilderFactory.newConfigurationBuilder()
+            val console = builder.newAppender("stdout", "Console")
 
+            val appLog = builder.newAppender("appLog", "RollingFile")
+            appLog.addAttribute("fileName", "log/app/app.log")
+            appLog.addAttribute("filePattern", "log/app/\$\${date:yyyy - MM}/app-%d{yyyy-MM-dd}-%i.log.zip")
+
+            val flow: FilterComponentBuilder = builder.newFilter(
+                    "MarkerFilter",
+                    Filter.Result.ACCEPT,
+                    Filter.Result.DENY)
+            flow.addAttribute("marker", "FLOW")
+
+            console.add(flow)
+
+            val standard = builder.newLayout("PatternLayout")
+            standard.addAttribute("pattern", "%d %p [%c{1}] %m%n")
+            val policies = builder.newLayout("Policies")
+            val timeBasedTriggeringPolicy = builder.newLayout("TimeBasedTriggeringPolicy")
+            val sizeBasedTriggeringPolicy = builder.newLayout("SizeBasedTriggeringPolicy")
+
+            sizeBasedTriggeringPolicy.addAttribute("size", "10 MB")
+            policies.addComponent(timeBasedTriggeringPolicy)
+            policies.addComponent(sizeBasedTriggeringPolicy)
+            console.add(standard)
+            builder.add(console)
+
+            appLog.add(standard)
+            appLog.addComponent(policies)
+            builder.add(appLog)
+
+            val rootLogger: RootLoggerComponentBuilder = builder.newRootLogger(Level.ERROR)
+            rootLogger.add(builder.newAppenderRef("stdout"))
+            builder.add(rootLogger)
+
+            val logger: LoggerComponentBuilder = builder.newLogger("co.id.datacomsolusindo.ipphonebridge", Level.DEBUG)
+            logger.add(builder.newAppenderRef("appLog"))
+            logger.addAttribute("additivity", false)
+            builder.add(logger)
+
+            ClientHolder.load().entries.forEach {
+                val clientLog = builder.newAppender("client-${it.key}", "RollingFile")
+                clientLog.addAttribute("fileName", "log/${it.key}/client-${it.key}.log")
+                clientLog.addAttribute("filePattern", "log/${it.key}/\$\${date:yyyy - MM}/app-%d{yyyy-MM-dd}-%i.client-${it.key}.zip")
+                clientLog.add(standard)
+                clientLog.addComponent(policies)
+                builder.add(clientLog)
+
+                val loggerClient: LoggerComponentBuilder = builder.newLogger("client.${it.key}", Level.DEBUG)
+                loggerClient.add(builder.newAppenderRef("client-${it.key}"))
+                loggerClient.addAttribute("additivity", false)
+                builder.add(loggerClient)
+            }
+
+            Configurator.reconfigure(builder.build())
+            LogManager.getLogger("client.$clNum").info("Client $clNum Connected")
+        }
     }
+}
 
+object AppLog {
+    fun write(cls: Class<*>): Logger {
+        return LogManager.getLogger(cls)
+    }
 }
 
 

+ 19 - 0
src/main/resources/log4j2.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="INFO" name="MyApp" packages="">
+    <Properties>
+        <Property name="LOG_PATTERN">%d %p [%c{1}] %m%n</Property>
+        <Property name="APP_LOG_ROOT">log</Property>
+    </Properties>
+
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT" follow="true">
+            <PatternLayout pattern="${LOG_PATTERN}"/>
+        </Console>
+
+    </Appenders>
+    <Loggers>
+        <Root level="INFO">
+            <AppenderRef ref="Console"/>
+        </Root>
+    </Loggers>
+</Configuration>