Skip to content
This repository was archived by the owner on Mar 11, 2019. It is now read-only.

Commit d85e870

Browse files
huertasmcolmant
authored andcommitted
feature(rest): implement the REST reporter
1 parent d310804 commit d85e870

File tree

9 files changed

+463
-8
lines changed

9 files changed

+463
-8
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ We all stand on the shoulders of giants and get by with a little help from our f
5555
* [Scala IO](http://jesseeichar.github.io/scala-io-doc/0.4.3/index.html#!/overview) (version 0.4.3 under [3-clause BSD license](http://www.scala-lang.org/license.html)), for an extensions of IO.
5656
* [Saddle](http://saddle.github.io/) (version 1.3.3 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for data manipulation.
5757
* [Sigar](https://support.hyperic.com/display/SIGAR/Home) (version 1.6.5 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for providing a portable interface for gathering system information.
58+
* [spray-can](http://spray.io/) (version 1.3.3 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for providing a low-level, low-overhead, high-performance HTTP server and client.
59+
* [spray-client](http://spray.io/) (version 1.3.3 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for providing high-level HTTP client.
60+
* [spray-routing](http://spray.io/) (version 1.3.3 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for providing a high-level, very flexible routing DSL for elegantly defining RESTful web services.
61+
* [spray-json](http://spray.io/) (version 1.2.2 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for (de)serializing JSON.
62+
* [nscala-time](https://github.com/nscala-time/nscala-time) (version 2.0.0 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for using a scala wrapper for Joda Time (quality replacement for the Java date and time classes).
5863

5964
# License
6065
This software is licensed under the *GNU Affero General Public License*, quoted below.

powerapi-core/build.sbt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,20 @@ libraryDependencies ++= Seq(
1616
"com.github.scala-incubator.io" %% "scala-io-file" % "0.4.3",
1717
"org.jfree" % "jfreechart" % "1.0.19",
1818
"org.scala-saddle" %% "saddle-core" % "1.3.3",
19-
"org.hyperic" % "sigar" % "1.6.5.132"
19+
"org.hyperic" % "sigar" % "1.6.5.132",
20+
"io.spray" %% "spray-can" % "1.3.3",
21+
"io.spray" %% "spray-client" % "1.3.3",
22+
"io.spray" %% "spray-routing" % "1.3.3",
23+
"io.spray" %% "spray-json" % "1.3.2",
24+
"com.github.nscala-time" %% "nscala-time" % "2.0.0"
2025
)
2126

2227
// Tests
2328
libraryDependencies ++= Seq(
2429
"com.typesafe.akka" %% "akka-testkit" % "2.3.11" % "test",
2530
"org.scalatest" %% "scalatest" % "2.2.5" % "test",
26-
"org.scalamock" %% "scalamock-scalatest-support" % "3.2.2" % "test"
31+
"org.scalamock" %% "scalamock-scalatest-support" % "3.2.2" % "test",
32+
"io.spray" %% "spray-testkit" % "1.3.3" % "test"
2733
)
2834

2935
startYear := Some(2014)

powerapi-core/src/main/scala/org/powerapi/PowerMeter.scala

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ import akka.util.Timeout
3131
import java.util.concurrent.TimeUnit
3232
import org.powerapi.PowerMeterMessages.StopAll
3333
import org.powerapi.core.{ActorComponent, Clocks, ConfigValue, Configuration, APIComponent, Monitor, Monitors, MessageBus}
34-
import org.powerapi.core.MonitorChannel.MonitorStart
34+
import org.powerapi.core.MonitorChannel.{ GetMonitoredProcesses, MonitorStart }
35+
import org.powerapi.core.MonitorChannel.stopMonitor
3536
import org.powerapi.core.target.Target
3637
import org.powerapi.core.power._
3738
import scala.concurrent.{ Await, Future }
@@ -80,6 +81,12 @@ class PowerMeterActor(eventBus: MessageBus, modules: Seq[PowerModule], timeout:
8081
case _ => log.error("The monitor supervisor is not created")
8182
}
8283
}
84+
case GetMonitoredProcesses => {
85+
monitorSupervisor match {
86+
case Some(actorRef) => sender ! Await.result(actorRef.ask(GetMonitoredProcesses)(timeout), timeout.duration)
87+
case _ => log.error("The monitor supervisor is not created")
88+
}
89+
}
8390
case StopAll => stopAll()
8491
} orElse default
8592

@@ -122,6 +129,17 @@ class PowerMeter(system: ActorSystem, modules: Seq[PowerModule]) extends PowerMe
122129
Await.result(powerMeterActor.ask(MonitorStart("", monitor.muid, frequency, targets.toList))(timeout), timeout.duration)
123130
monitor
124131
}
132+
133+
/**
134+
* Allows to get the processes which are monitored by a power meter.
135+
*/
136+
def getMonitoredProcesses: Iterable[Set[Target]] = {
137+
Await.result(
138+
Await.result(
139+
powerMeterActor.ask(GetMonitoredProcesses)(timeout), timeout.duration
140+
).asInstanceOf[Future[Iterable[Set[Target]]]], timeout.duration
141+
).asInstanceOf[Iterable[Set[Target]]]
142+
}
125143

126144
/**
127145
* Blocks and actively waits for a specific duration before returning.
@@ -136,6 +154,13 @@ class PowerMeter(system: ActorSystem, modules: Seq[PowerModule]) extends PowerMe
136154

137155
this
138156
}
157+
158+
/**
159+
* Cancel a subscription and stops the associated monitoring.
160+
*/
161+
def stopMonitor(muid: UUID): Unit = {
162+
org.powerapi.core.MonitorChannel.stopMonitor(muid)(eventBus)
163+
}
139164

140165
/**
141166
* Shuts down the current instance of power meter.
@@ -243,3 +268,4 @@ trait PowerDisplay {
243268
*/
244269
def display(muid: UUID, timestamp: Long, targets: Set[Target], devices: Set[String], power: Power)
245270
}
271+

powerapi-core/src/main/scala/org/powerapi/core/MonitorActors.scala

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,37 @@
2222
*/
2323
package org.powerapi.core
2424

25+
import akka.util.Timeout
2526
import akka.actor.SupervisorStrategy.{Directive, Resume}
2627
import akka.actor.{Actor, ActorRef, ActorSystem, PoisonPill, Props}
2728
import akka.event.LoggingReceive
29+
import akka.pattern.ask
2830
import java.util.UUID
31+
import java.util.concurrent.TimeUnit
2932
import org.powerapi.core.ClockChannel.ClockTick
3033
import org.powerapi.core.power._
3134
import org.powerapi.core.target.Target
3235
import org.powerapi.{PowerDisplay, PowerMonitoring}
3336
import org.powerapi.core.ClockChannel.{startClock, stopClock, subscribeClockTick, unsubscribeClockTick}
34-
import org.powerapi.core.MonitorChannel.{MonitorAggFunction, MonitorStart, MonitorStarted, MonitorStop, MonitorStopAll, formatMonitorChildName, subscribeMonitorsChannel}
37+
import org.powerapi.core.MonitorChannel.{GetMonitoredProcesses, MonitorAggFunction, MonitorStart, MonitorStarted, MonitorStop, MonitorStopAll, formatMonitorChildName, subscribeMonitorsChannel}
3538
import org.powerapi.core.MonitorChannel.{publishMonitorTick, setAggFunction, stopMonitor}
3639
import org.powerapi.module.PowerChannel.{AggregatePowerReport, RawPowerReport, render, subscribeRawPowerReport, unsubscribeRawPowerReport, subscribeAggPowerReport}
3740
import org.powerapi.module.SensorChannel.{monitorAllStopped, monitorStopped}
3841
import org.powerapi.reporter.ReporterComponent
39-
import scala.concurrent.duration.FiniteDuration
42+
import scala.concurrent.duration.{ DurationLong, FiniteDuration }
43+
import scala.concurrent.{ Await, Future }
44+
import scala.concurrent.ExecutionContext.Implicits.global
45+
import scala.util.{ Failure, Success }
46+
47+
/**
48+
* Main Configuration
49+
*/
50+
trait MonitorConfiguration extends Configuration {
51+
lazy val timeout: Timeout = load { _.getDuration("powerapi.actors.timeout", TimeUnit.MILLISECONDS) } match {
52+
case ConfigValue(value) => Timeout(value.milliseconds)
53+
case _ => Timeout(15l.seconds)
54+
}
55+
}
4056

4157
/**
4258
* One child represents one monitor.
@@ -61,6 +77,7 @@ class MonitorChild(eventBus: MessageBus,
6177
case tick: ClockTick => produceMessages(tick)
6278
case MonitorAggFunction(_, id, aggF) if muid == id => setAggregatingFunction(aggR, aggF)
6379
case powerReport: RawPowerReport => aggregate(aggR, powerReport, aggFunction)
80+
case GetMonitoredProcesses => sender ! targets
6481
case MonitorStop(_, id) if muid == id => stop()
6582
case _: MonitorStopAll => stop()
6683
} orElse default
@@ -125,7 +142,7 @@ class MonitorChild(eventBus: MessageBus,
125142
*
126143
* @author Maxime Colmant <maxime.colmant@gmail.com>
127144
*/
128-
class Monitors(eventBus: MessageBus) extends Supervisor {
145+
class Monitors(eventBus: MessageBus) extends MonitorConfiguration with Supervisor {
129146

130147
override def preStart(): Unit = {
131148
subscribeMonitorsChannel(eventBus)(self)
@@ -144,6 +161,7 @@ class Monitors(eventBus: MessageBus) extends Supervisor {
144161
case msg: MonitorAggFunction => setAggregatingFunction(msg)
145162
case msg: MonitorStop => stop(msg)
146163
case msg: MonitorStopAll => stopAll(msg)
164+
case GetMonitoredProcesses => getMonitoredProcesses
147165
} orElse default
148166

149167
/**
@@ -189,6 +207,20 @@ class Monitors(eventBus: MessageBus) extends Supervisor {
189207
monitorAllStopped()(eventBus)
190208
context.become(receive)
191209
}
210+
211+
/**
212+
* Allows to get the processes which are monitored by a power meter.
213+
*/
214+
def getMonitoredProcesses: Unit = {
215+
val monitoredProcesses = Future.sequence(for (child <- context.children) yield {
216+
child.ask(GetMonitoredProcesses)(timeout).map(Success(_)).recover({
217+
case e => Failure(e)
218+
})
219+
}).map(_.collect {
220+
case Success(list) => list.asInstanceOf[List[Target]].toSet
221+
})
222+
sender ! monitoredProcesses
223+
}
192224
}
193225

194226
/**
@@ -226,3 +258,4 @@ class Monitor(eventBus: MessageBus, system: ActorSystem) extends PowerMonitoring
226258
reporters = Array()
227259
}
228260
}
261+

powerapi-core/src/main/scala/org/powerapi/core/MonitorChannel.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ object MonitorChannel extends Channel {
8484
*/
8585
object MonitorStarted
8686

87+
/**
88+
* Dedicated type of message to get the processes which are monitored
89+
* by a power meter.
90+
*/
91+
object GetMonitoredProcesses
92+
8793
/**
8894
* MonitorStop is represented as a dedicated type of message.
8995
*
@@ -156,3 +162,4 @@ object MonitorChannel extends Channel {
156162
s"monitor-$muid"
157163
}
158164
}
165+

0 commit comments

Comments
 (0)