generated from JetBrains/intellij-platform-plugin-template
-
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
202 additions
and
305 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
src/main/kotlin/com/dsoftware/ghmanager/api/GetJobLogRequest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package com.dsoftware.ghmanager.api | ||
|
||
import com.dsoftware.ghmanager.api.model.Job | ||
import com.dsoftware.ghmanager.api.model.JobStep | ||
import com.intellij.openapi.diagnostic.logger | ||
import org.jetbrains.plugins.github.api.GithubApiRequest | ||
import org.jetbrains.plugins.github.api.GithubApiResponse | ||
import java.io.BufferedReader | ||
import java.io.IOException | ||
import java.io.InputStream | ||
import java.io.InputStreamReader | ||
import java.text.SimpleDateFormat | ||
import java.util.Date | ||
import java.util.TimeZone | ||
|
||
typealias JobLog = Map<Int, StringBuilder> | ||
|
||
class GetJobLogRequest(private val job: Job) : GithubApiRequest.Get<String>(job.url + "/logs") { | ||
private val stepsPeriodMap = job.steps?.associate { step -> | ||
step.number to (step.startedAt to step.completedAt) | ||
} ?: emptyMap() | ||
private val lastStepNumber: Int = stepsPeriodMap.keys.maxOrNull() ?: 0 | ||
|
||
override fun extractResult(response: GithubApiResponse): String { | ||
LOG.debug("extracting result for $url") | ||
return response.handleBody { | ||
extractJobLogFromStream(it) | ||
} | ||
} | ||
|
||
fun extractJobLogFromStream(inputStream: InputStream): String { | ||
val stepLogs = extractLogByStep(inputStream) | ||
return stepsAsLog(stepLogs) | ||
} | ||
|
||
fun extractLogByStep(inputStream: InputStream): Map<Int, StringBuilder> { | ||
val dateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.SSS" | ||
val formatter = SimpleDateFormat(dateTimePattern) | ||
|
||
val contentBuilders = HashMap<Int, StringBuilder>() | ||
|
||
formatter.timeZone = TimeZone.getTimeZone("UTC") | ||
var lineNum = 0 | ||
var currStep = 1 | ||
try { | ||
val reader = BufferedReader(InputStreamReader(inputStream)) | ||
val lines = reader.readLines() | ||
for (line in lines) { | ||
++lineNum | ||
if (line.length < 29) { | ||
contentBuilders.getOrDefault(currStep, StringBuilder()).append(line + "\n") | ||
continue | ||
} | ||
val datetimeStr = line.substring(0, 23) | ||
val time = formatter.parse(datetimeStr) | ||
currStep = findStep(currStep, time) | ||
|
||
contentBuilders.getOrPut(currStep) { StringBuilder(400_000) }.append(line + "\n") | ||
} | ||
} catch (e: IOException) { | ||
LOG.warn(e.message) | ||
throw e | ||
} | ||
return contentBuilders | ||
} | ||
|
||
private fun findStep(initialStep: Int, time: Date): Int { | ||
var currStep = initialStep | ||
while (currStep < lastStepNumber) { | ||
if (!stepsPeriodMap.containsKey(currStep)) { | ||
currStep += 1 | ||
continue | ||
} | ||
val currStart = stepsPeriodMap[currStep]?.first | ||
val currEnd = stepsPeriodMap[currStep]?.second | ||
if (currStart != null && currStart.after(time)) { | ||
return currStep | ||
} | ||
if ((currStart == null || currStart.before(time) || currStart == time) | ||
&& (currEnd == null || currEnd.after(time) || currEnd == time) | ||
) { | ||
return currStep | ||
} | ||
currStep += 1 | ||
} | ||
return currStep | ||
} | ||
|
||
private fun stepsAsLog(stepLogs: JobLog): String { | ||
val stepsResult: Map<Int, JobStep> = if (job.steps == null) { | ||
emptyMap() | ||
} else { | ||
job.steps.associateBy { it.number } | ||
} | ||
val stepNumbers = stepsResult.keys.sorted() | ||
if (!stepNumbers.containsAll(stepLogs.keys)) { | ||
LOG.warn( | ||
"Some logs do not have a step-result associated " + | ||
"[steps in results=$stepNumbers, step with logs=${stepLogs.keys}] " | ||
) | ||
} | ||
val res = StringBuilder(1_000_000) | ||
for (index in stepNumbers) { | ||
val stepInfo = stepsResult[index]!! | ||
val indexStr = "%3d".format(index) | ||
res.append( | ||
when (stepInfo.conclusion) { | ||
"skipped" -> "\u001B[0m\u001B[37m---- Step ${indexStr}: ${stepInfo.name} (skipped) ----\u001b[0m\n" | ||
"failure" -> "\u001B[0m\u001B[31m---- Step ${indexStr}: ${stepInfo.name} (failed) ----\u001b[0m\n" | ||
else -> "\u001B[0m\u001B[32m---- Step ${indexStr}: ${stepInfo.name} ----\u001b[0m\n" | ||
} | ||
) | ||
if (stepInfo.conclusion != "skipped" && stepLogs.containsKey(index) && (res.length < 950_000)) { | ||
if (res.length + (stepLogs[index]?.length ?: 0) < 990_000) { | ||
res.append(stepLogs[index]) | ||
} else { | ||
res.append("Log is too big to display, showing only first 1mb") | ||
} | ||
} | ||
} | ||
return res.toString() | ||
} | ||
|
||
companion object { | ||
private val LOG = logger<GetJobLogRequest>() | ||
} | ||
} |
80 changes: 0 additions & 80 deletions
80
src/main/kotlin/com/dsoftware/ghmanager/api/GetRunLogRequest.kt
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 22 additions & 6 deletions
28
src/test/kotlin/com/dsoftware/ghmanager/TestGetJobLogRequest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,33 @@ | ||
package com.dsoftware.ghmanager | ||
|
||
import com.dsoftware.ghmanager.api.model.Job | ||
import com.dsoftware.ghmanager.api.GetJobLogRequest | ||
import com.dsoftware.ghmanager.api.model.WorkflowRunJobs | ||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import com.fasterxml.jackson.databind.PropertyNamingStrategies | ||
import com.fasterxml.jackson.module.kotlin.readValue | ||
import com.fasterxml.jackson.module.kotlin.registerKotlinModule | ||
import com.intellij.testFramework.fixtures.BasePlatformTestCase | ||
import junit.framework.TestCase | ||
|
||
class TestGetJobLogRequest : BasePlatformTestCase() { | ||
class TestGetJobLogRequest : TestCase() { | ||
private val mapper = ObjectMapper().registerKotlinModule() | ||
|
||
override fun setUp() { | ||
super.setUp() | ||
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); | ||
} | ||
|
||
fun testGetJobLogRequest() { | ||
val logContent = TestGetJobLogRequest::class.java.getResource("wf-run-single-job.log")?.readText() | ||
val jobJson = TestGetJobLogRequest::class.java.getResource("wf-run-single-job.json")?.readText() | ||
val obj: List<Job> = mapper.readValue(json) | ||
// arrange | ||
val logContent = TestGetJobLogRequest::class.java.getResource("/wf-run-single-job.log")!!.readText() | ||
val wfJobsJson = TestGetJobLogRequest::class.java.getResource("/wf-run-jobs.json")!!.readText() | ||
val wfJobs: WorkflowRunJobs = mapper.readValue(wfJobsJson) | ||
val job = wfJobs.jobs.first() | ||
|
||
//act | ||
val jobLog = GetJobLogRequest(job).extractLogByStep(logContent.byteInputStream()) | ||
|
||
//assert | ||
val jobLogLinesCount = jobLog.map { it.key to it.value.split("\n").size }.toMap() | ||
assertTrue(jobLogLinesCount == mapOf((1 to 33), (2 to 21), (3 to 834), (4 to 813), (6 to 5), (8 to 15))) | ||
} | ||
} |
Oops, something went wrong.