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

ChillAdvanced team pr #3

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
165 changes: 165 additions & 0 deletions app/src/main/java/chilladvanced/Logger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package chilladvanced

import android.util.Log
import com.google.gson.Gson
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.io.IOException
import java.net.HttpURLConnection
import java.net.Proxy
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicLong

/**
* Defining variable types.
*
* @param url the type of a urls in logs.
* @param method the type of a metods in logs.
* @param userId the type of a user_id in logs.
* @param unixtime the type of a time logging.
* @param inputTraffic the type of a incoming traffic in logs.
* @param outputTraffic the type of a outgoing traffic in logs.
* @param duration the type of a url in logs.
*/

data class RequestLog(
val url: String,
val method: String,
val userId: String,
val unixtime: Long,
val inputTraffic: Long,
val outputTraffic: Long,
val duration: Long,
)

typealias Host = String

typealias Timestamp = Long

/**
* Object containing the main functions used
*/

object Logger {

@JvmStatic
val userId: UUID = UUID.randomUUID()

@JvmStatic
private val storage = mutableSetOf<RequestLog>()

@JvmStatic
val sendLogsLock = Mutex()

@JvmStatic
val gson = Gson()

@JvmStatic
val map: ConcurrentHashMap<Host, Pair<NETWORK_METHODS, Timestamp>> = ConcurrentHashMap()

@JvmStatic
var lastUpdate = AtomicLong()


/**
* Parameters accepted by the logger.
*
* @param host the name of request host
* @param method the name method that usnig for network request
* @param duration the time in millisecond that network connection spend to
* @param inputTraffic the traffic in bytest that connection sends to server
* @param outputTraffic the traffic in bytest that connection received from server
*/
@JvmStatic
fun log(
host: String,
method: NETWORK_METHODS,
duration: Long,
inputTraffic: Long,
outputTraffic: Long
) {
val methodWithFilter = map[host]?.first ?: method
val currentTimeMillis = System.currentTimeMillis()
if (currentTimeMillis - lastUpdate.get() > 10000) {
map.filterValues { (currentTimeMillis - it.second) > 10000 }.keys.forEach(map::remove)
lastUpdate.set(currentTimeMillis);
}
val l = RequestLog(
host, methodWithFilter.name, userId.toString(),
currentTimeMillis, inputTraffic, outputTraffic, duration
)
synchronized(storage) {
storage += l
}
}

/**
* Registers an expected call to the host from a supplied method.
*
* @param host the name of host that connection will be sent
* @param method the name of network method that will be invocated
*/
@JvmStatic
fun register(host: String, method: NETWORK_METHODS) {
map[host] = Pair(method, System.currentTimeMillis());
}

/**
* frequency of sending statistic to server
*/
val SEND_LOG_TIME_SECOND = 5

/**
* Run logger.
*/
@JvmStatic
fun runSending() {
Thread {
while (true) {
Thread.sleep(SEND_LOG_TIME_SECOND.toLong() * 1000)
sendLog()
}
}.start()
}

/**
* Getting logs to the server.
*
*/
@JvmStatic
private fun sendLog() {
val lgs = synchronized(storage) {
storage.toList()
}

if (lgs.isEmpty()) {
return
}

/**
* Connecting to the server and getting logs.
* @throws IOException if failed to log network request.
*/

try {
Log.i("Logger", "log object: $lgs")
val connection = java.net.URL("https://d.kbats.ru/util/user-add")
.openConnection(Proxy.NO_PROXY) as HttpURLConnection
connection.requestMethod = "POST"
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8")

val info = gson.toJson(lgs)
Log.i("Logger", "sending log info: $info")
connection.outputStream.write(info.toByteArray())

val text = connection.inputStream.bufferedReader().readText()

synchronized(storage) {
storage -= lgs.toSet()
}
} catch (e: IOException) {
Log.e("Logger", "failed to log network request, caused error $e")
}
}
}
11 changes: 11 additions & 0 deletions app/src/main/java/chilladvanced/NETWORK_METHODS.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package chilladvanced

enum class NETWORK_METHODS {
UNKNOWN,
EXO_PLAYER,
OK_HTTP_CLIENT,
URL_CONNECTION,
FRESCO,
NATIVE,

}
74 changes: 74 additions & 0 deletions app/src/main/java/chilladvanced/NativeLibraryTracker.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package chilladvanced

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.net.TrafficStats
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.PermissionChecker
import androidx.core.content.PermissionChecker.checkSelfPermission
import com.google.android.exoplayer2.util.Log


class NativeLibraryTracker() {
// val currentThread: Int
// val totalTxBytes = TrafficStats.getTotalTxBytes()
// init {
// currentThread = TrafficStats.getUidRxBytes()
// TrafficStats.getThreadStatsTag()
// val totalRxBytes = TrafficStats..getTotalRxBytes()
// }

var trafficStatsTx = 0L
var started: Boolean = false
var trafficStatsRx = 0L
var uid = -1;

fun start(context: Activity) {
// May be we got permission for another task
try {
if (checkSelfPermission(
context,
Manifest.permission.READ_PHONE_STATE
) == PermissionChecker.PERMISSION_GRANTED
) {


uid = context.applicationInfo.uid
TrafficStats.setThreadStatsTag(uid)
trafficStatsRx = TrafficStats.getTotalRxBytes()
trafficStatsTx = TrafficStats.getTotalTxBytes()

}
} catch (e: Exception) {
Log.w(
"NativeLibraryTracker",
"Something went wrong in NativeLibraryTracker: " + e.message
)
}
}

fun stop(context: Context) {
try {
if (started && checkSelfPermission(
context,
Manifest.permission.READ_PHONE_STATE
) == PermissionChecker.PERMISSION_GRANTED
) {
TrafficStats.setThreadStatsTag(uid)
Logger.log(
"", NETWORK_METHODS.NATIVE, 0,
TrafficStats.getTotalRxBytes() - trafficStatsRx,
TrafficStats.getTotalTxBytes() - trafficStatsTx
)
}
} catch (e: Exception) {
Log.w(
"NativeLibraryTracker",
"Something went wrong in NativeLibraryTracker: " + e.message
)
}
}
}
67 changes: 67 additions & 0 deletions app/src/main/java/chilladvanced/NetworkLogger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package chilladvanced

/**
* Network logging sdk main object
*
* @author chill advanced team
*/
object NetworkLogger {

/**
* Initialize and run network logger
*
* This method setups and starts network proxy for logging all traffic in android application
*/
fun initializeAndRunLogging(proxyPortHttp: Int = 3128, proxyPortAnother: Int = 3129) {
setProxyHostHttp("127.0.0.1")
setProxyHostAnother("127.0.0.1")
setProxyPortHttp("$proxyPortHttp")
setProxyPortAnother("$proxyPortAnother")

ProxyServer(
proxyPortHttp,
SocketConnectHttpChecker.Companion::connectAndCountTraffic
).startServer()
ProxyServer(
proxyPortAnother,
SocketConnect.Companion::connectAndCountTraffic
).startServer()

Logger.runSending()
}

private fun setProxyHostHttp(host: String) {
System.setProperty("http.proxyHost", host);
}

private fun setProxyPortHttp(host: String) {
System.setProperty("http.proxyPort", host);
}

private fun setProxyHostAnother(host: String) {
System.setProperty("https.proxyHost", host);
System.setProperty("ftp.proxyHost", host);
System.setProperty("socksProxyHost", host);
}

private fun setProxyPortAnother(port: String) {
System.setProperty("https.proxyPort", port);
System.setProperty("ftp.proxyPort", port);
System.setProperty("socksProxyPort", port);
}

private fun delayShutdownEvent(millis: Long) {
Thread.setDefaultUncaughtExceptionHandler { t, e -> // perform any necessary cleanup or shutdown tasks here
println("Uncaught exception occurred: " + e.message)
try {
// delay the shutdown for 2 seconds
Thread.sleep(millis)
} catch (ex: InterruptedException) {
// handle the InterruptedException if necessary
ex.printStackTrace()
}
// shut down the program
System.exit(1)
}
}
}
13 changes: 13 additions & 0 deletions app/src/main/java/chilladvanced/OkHttpClientWithStat.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package chilladvanced

import android.util.Log
import okhttp3.Call
import okhttp3.OkHttpClient
import okhttp3.Request

class OkHttpClientWithStat(val okHttpClient: OkHttpClient) {
fun newCall(request: Request): Call {
Logger.register(request.url.host, NETWORK_METHODS.OK_HTTP_CLIENT)
return okHttpClient.newCall(request)
}
}
Loading