Skip to content

Commit

Permalink
merge branch 'release/0.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
wookietreiber committed May 28, 2017
2 parents 96ce668 + 8a6802b commit 69fbfe6
Show file tree
Hide file tree
Showing 9 changed files with 1,359 additions and 39 deletions.
1,230 changes: 1,228 additions & 2 deletions NOTICE.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Analyzes [strace][] output. Currently, the following analysis commands are provi
- **read** per file read summary
- **write** per file write summary
- **io** does both **read** and **write**
- **io-profile** per file **read** and **write** profile, outputs a chart (png) per file and per op

File descriptors are associated with file names. The association is made when syscalls like
**open**, **creat**, **dup** or **pipe** are read from the log and the association gets terminated
Expand Down
2 changes: 1 addition & 1 deletion bash-completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ _strace-analyzer()
COMPREPLY=( $( compgen -W '-? -h -help -version --help --version' -- $cur ) )
;;
*)
COMPREPLY=( $( compgen -W 'summary read write io' -- $cur ) )
COMPREPLY=( $( compgen -W 'summary read write io io-profile' -- $cur ) )
;;
esac

Expand Down
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ lazy val root = (project in file(".")).
enablePlugins(BuildInfoPlugin).
settings (
name := "strace-analyzer",
libraryDependencies += "com.github.wookietreiber" %% "scala-chart" % "0.5.0",
buildInfoKeys := Seq[BuildInfoKey](name, version),
buildInfoPackage := "strace.analyze",
mappings in Universal <++= name in Universal map { name =>
Expand Down
49 changes: 16 additions & 33 deletions src/main/scala/analyzer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,41 +33,20 @@ object Analyzer extends App {
// help / usage / version
// -----------------------------------------------------------------------------------------------

if (List("-version", "--version") exists args.contains) {
Console.println(s"""${BuildInfo.name} ${BuildInfo.version}""")
def help() = {
import sys.process._
"man strace-analyzer".!
sys exit 0
}

if (List("-?", "-h", "-help", "--help") exists args.contains) {
Console.println(s"""
|${BuildInfo.name} ${BuildInfo.version}
|
|Usage: strace-analyzer [io|read|summary|write] [<log1> <log2> ...]
|
|Generate logs like this:
|
| strace -ff -T -ttt -o app-strace.log app
|
|Other formats are not supported.
|
| -? | -h | -help | --help print this help
| -version | --version print version
|
|Command: io
| The io command compiles a read/write operation summary.
|
|Command: read
| The read command compiles a read operation summary.
|
|Command: summary
| The summary command compiles a short per operation summary.
|
|Command: write
| The write command compiles a write operation summary.
|""".stripMargin)
if (List("-version", "--version") exists args.contains) {
Console.println(s"""${BuildInfo.name} ${BuildInfo.version}""")
sys exit 0
}

if (List("-?", "-h", "-help", "--help") exists args.contains)
help()

// -----------------------------------------------------------------------------------------------
// parse cli args
// -----------------------------------------------------------------------------------------------
Expand All @@ -77,10 +56,14 @@ object Analyzer extends App {
Console.err.println("error: need command")
sys exit 1

case Some("io") => IO
case Some("read") => Read
case Some("summary") => Summary
case Some("write") => Write
case Some("io") => IO
case Some("io-profile") => IOProfile
case Some("read") => Read
case Some("summary") => Summary
case Some("write") => Write

case Some("help") =>
help()

case Some(other) =>
Console.err.println(s"""error: don't know the command "$other"""")
Expand Down
90 changes: 90 additions & 0 deletions src/main/scala/io-profile.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015-2016 Christian Krause *
* *
* Christian Krause <kizkizzbangbang@gmail.com> *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of strace-analyzer. *
* *
* strace-analyzer is free software: you can redistribute it and/or modify it under the terms *
* of the GNU General Public License as published by the Free Software Foundation, either *
* version 3 of the License, or any later version. *
* *
* strace-analyzer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; *
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* strace-analyzer. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


package strace
package analyze

import scalax.chart.api._

object IOProfile extends Analysis {
def analyze(implicit config: Config): Unit =
for ((log,entries) <- parseLogs) {
saveChart(log, entries, op = "read") {
case entry: LogEntry.Read => entry
}

saveChart(log, entries, op = "write") {
case entry: LogEntry.Write => entry
}
}

def saveChart(log: String, entries: List[LogEntry], op: String)
(pf: PartialFunction[LogEntry,LogEntry with HasBytes with HasFD]): Unit = {
val filtered = entries.collect(pf)

for ((file,entries) <- filtered.groupBy(_.fd)) {
val filename = new java.io.File(file).getName
val logname = new java.io.File(log).getName

val chart = genChart(entries)

chart.saveAsPNG (
file = s"""strace-analyzer-profile-$op-$logname-$filename.png""",
resolution = (1920,1080)
)
}
}

def genChart[A <: LogEntry with HasBytes](entries: List[A]) = {
import java.text._
import java.util.Date
import org.jfree.chart.axis.NumberAxis
import org.jfree.data.time.Second

val raw = for {
entry <- entries
time = new Second(new Date(entry.jepoch))
value = entry.bytes
} yield (time,value)

val data = raw.groupBy(_._1).mapValues(_.foldLeft(0L)(_ + _._2))

val chart = XYBarChart(data.toTimeSeries(""), legend = false)
chart.plot.range.axis.label.text = "bytes"
chart.plot.range.axis.peer match {
case axis: NumberAxis =>
axis setNumberFormatOverride new NumberFormat {
def format(value: Long, buf: StringBuffer, fp: FieldPosition): StringBuffer =
buf append Memory.humanize(value)
def format(value: Double, buf: StringBuffer, fp: FieldPosition): StringBuffer =
format(value.round, buf, fp)
def parse(value: String, pp: ParsePosition): Number = ???
}

case _ =>
}

chart
}
}
13 changes: 12 additions & 1 deletion strace-analyzer.1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 1.17.0.3
.\"
.TH "STRACE\-ANALYZER" "1" "March 2016" "Version 0.1.1" "strace\-analyzer manual"
.TH "STRACE\-ANALYZER" "1" "March 2016" "Version 0.2.0" "strace\-analyzer manual"
.hy
.SH NAME
.PP
Expand Down Expand Up @@ -40,6 +40,11 @@ Thus, the resulting \f[B]strace(1)\f[] invocation to create the logs
should look as in the \f[B]EXAMPLES\f[] section.
.SS Analysis Commands
.TP
.B help
Prints usage information.
.RS
.RE
.TP
.B summary
Prints a summary for the syscalls \f[B]read(2)\f[] and
\f[B]write(2)\f[].
Expand All @@ -60,6 +65,12 @@ Prints a \f[B]write(2)\f[] summary for each file.
Does both the \f[B]read\f[] and \f[B]write\f[] commands for each file.
.RS
.RE
.TP
.B io\-profile
Per file \f[B]read\f[] and \f[B]write\f[] profile.
Outputs a chart (png) per file and per operation.
.RS
.RE
.SH OPTIONS
.TP
.B \-?, \-h, \-help, \-\-help
Expand Down
10 changes: 9 additions & 1 deletion strace-analyzer.1.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
% STRACE-ANALYZER(1) Version 0.1.1 | strace-analyzer manual
% STRACE-ANALYZER(1) Version 0.2.0 | strace-analyzer manual
%
% March 2016

Expand Down Expand Up @@ -32,6 +32,10 @@ resulting **strace(1)** invocation to create the logs should look as in the **EX

## Analysis Commands

help

: Prints usage information.

summary

: Prints a summary for the syscalls **read(2)** and **write(2)**.
Expand All @@ -48,6 +52,10 @@ io

: Does both the **read** and **write** commands for each file.

io-profile

: Per file **read** and **write** profile. Outputs a chart (png) per file and per operation.

# OPTIONS

-?, -h, -help, --help
Expand Down
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
git.baseVersion in ThisBuild := "0.1.1"
git.baseVersion in ThisBuild := "0.2.0"

0 comments on commit 69fbfe6

Please sign in to comment.