Elektron Logging library (#16)
switch to logrus for logging. replaced old logging library with a wrapper around logrus. We now just need to use the exported Log(...) and Logf(...) from the logging/ package that wraps around a set of loggers constituting a chain (following COR). Loggers are configured using a YAML file that specifies the following. 1. enabled/disabled 2. whether the message should be logged on console. 3. filename extension. 4. minimum log level. Retrofitted source code to now use the updated logging library. Updated the documentation with information regarding the specification of the log config file. Currently, the log format in the config file is not adhered to. This is going to be addressed in a future commit.
This commit is contained in:
parent
9977251c14
commit
3543960689
61 changed files with 1510 additions and 1067 deletions
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
// TODO: Clean this up and use Mesos Attributes instead.
|
||||
package constants
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package def
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package def
|
||||
|
||||
|
|
10
def/task.go
10
def/task.go
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package def
|
||||
|
||||
|
|
|
@ -1,31 +1,33 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package def
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"github.com/mash/gokmeans"
|
||||
"github.com/montanaflynn/stats"
|
||||
log "github.com/sirupsen/logrus"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
)
|
||||
|
||||
// Information about a cluster of tasks.
|
||||
|
@ -50,7 +52,7 @@ func (tc TasksToClassify) taskObservationCalculator(task Task) []float64 {
|
|||
} else if task.Watts != 0.0 {
|
||||
return []float64{task.Watts}
|
||||
} else {
|
||||
log.Fatal("Unable to classify tasks. Missing Watts or ClassToWatts attribute in workload.")
|
||||
elekLog.Log(CONSOLE, log.FatalLevel, "Unable to classify tasks. Missing Watts or ClassToWatts attribute in workload")
|
||||
return []float64{0.0} // Won't reach here.
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +107,7 @@ func clusterSizeAvgMMMPU(tasks []Task, taskObservation func(task Task) []float64
|
|||
} else {
|
||||
// skip this value
|
||||
// there is an error in the task config.
|
||||
log.Println(err)
|
||||
elekLog.Log(CONSOLE, log.ErrorLevel, err.Error())
|
||||
}
|
||||
} else {
|
||||
// There is only one observation for the task.
|
||||
|
|
|
@ -20,11 +20,12 @@ package def
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
"github.com/spdfg/elektron/constants"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTasksFromJSON(t *testing.T) {
|
||||
|
|
16
docs/Logs.md
16
docs/Logs.md
|
@ -11,4 +11,18 @@ _Elektron_ logs can be categorized into the following.
|
|||
* _**Scheduling Policy Switching Logs**_ - When scheduling policy switching is enabled (`-switchSchedPol` is used when launching _Elektron_), the following information is logged.
|
||||
* [**Scheduling Policy Switch trace (SPS)**](data/withSpsEnabled/SchedulingPolicySwitchTrace.md) - Every time _Elektron_ switches to a different scheduling policy, the _name_ of the scheduling policy and the corresponding _time stamp_ is logged.<br>
|
||||
* [**SCHED_WINDOW**](data/withSpsEnabled/SchedulingWindow.md) - For every switch, the size of the scheduling window and the name of the scheduling policy is logged.
|
||||
* [**CLSFN_TASKDIST_OVERHEAD**](data/withSpsEnabled/TaskClassificationOverhead.md) - If the switching criteria is task distribution based, then the time taken to classify the tasks into low power consuming and high power consuming, and then to determine the task distribution is logged.
|
||||
* [**CLSFN_TASKDISTR_OVERHEAD**](data/withSpsEnabled/TaskClassificationOverhead.md) - If the switching criteria is task distribution based, then the time taken to classify the tasks into low power consuming and high power consuming, and then to determine the task distribution is logged.
|
||||
|
||||
_Elektron_ logs can be configured through [Log config file](../logConfig.yaml). The following is the format for configuration.
|
||||
```
|
||||
<logtype>:
|
||||
enabled: <true/false>
|
||||
filenameExtension: <filename extension>
|
||||
minLogLevel: <minimum log level>
|
||||
allowOnConsole: <true/false>
|
||||
```
|
||||
The file has default configurations set. One can also configure the above fields for every log type.
|
||||
* `enabled` - Enable or disable a specific log type.
|
||||
* `filenameExtension` - Provide the file extension for specific log type.
|
||||
* `minLogLevel` - Provide a minimum log level above which all logs should be logged. This is available only for Console log type. The default value is debug).
|
||||
* `allowOnConsole` - Allow or Disallow a specific log type on the console.
|
||||
|
|
|
@ -25,12 +25,12 @@ myhost:kernel.all.cpu.sys
|
|||
|
||||
When we run the `pmdumptext` command mentioned above for 5 seconds, the PCP log from _Elektron_ would be as shown below.
|
||||
```
|
||||
<yyyy/mm/dd> <hh:mm:ss> myhost:kernel.all.cpu.user,myhost:kernel.all.cpu.sys
|
||||
<yyyy/mm/dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
<yyyy/mm/dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
<yyyy/mm/dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
<yyyy/mm/dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
<yyyy/mm/dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> myhost:kernel.all.cpu.user,myhost:kernel.all.cpu.sys
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> <myhost user cpu time>,<myhost system cpu time>
|
||||
```
|
||||
|
||||
## Power Measurements
|
||||
|
|
|
@ -9,6 +9,6 @@ The scheduled trace logs are written to a file named _\<logFilePrefix\>\_\<times
|
|||
|
||||
The format of the data logged is as shown below.
|
||||
```
|
||||
<yyyy/mm/dd> <hh:mm:ss> <hostname>:<task ID>
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> <hostname>=<task ID>
|
||||
```
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ The logs are written to a file named _\<logFilePrefix\>\_\<timestamp\>\_schedPol
|
|||
|
||||
The format of the data logged is as shown below.
|
||||
```
|
||||
<yyyy/mm/dd> <hh:mm:ss> <sched policy name>
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> Name=<sched policy name>
|
||||
```
|
||||
|
||||
_Note: The names of the scheduling policies can be found [here](https://gitlab.com/spdf/elektron/blob/master/schedulers/store.go#L14)_
|
||||
|
|
|
@ -8,5 +8,5 @@ The logs are written to a file named _\<logFilePrefix\>\_\<timestamp\>\_schedWin
|
|||
|
||||
The format of the data logged is as shown below.
|
||||
```
|
||||
<yyyy/mm/dd> <hh:mm:ss> <sched window size> <sched policy name>
|
||||
```
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> Window size=<sched window size>, Name=<sched policy name>
|
||||
```
|
||||
|
|
|
@ -8,7 +8,7 @@ The logs are written to a file named _\<logFilePrefix\>\_\<timestamp\>\_classifi
|
|||
|
||||
The format of the data logged is as shown below.
|
||||
```
|
||||
<yyyy/mm/dd> <hh:mm:ss> <overhead>
|
||||
[<loglevel>]: <yyyy-mm-dd> <hh:mm:ss> Overhead in microseconds=<overhead>
|
||||
```
|
||||
|
||||
_Note: The classification overhead is logged in **microseconds**._
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package environment
|
||||
|
||||
|
|
29
go.mod
29
go.mod
|
@ -4,20 +4,23 @@ go 1.12
|
|||
|
||||
require (
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/gogo/protobuf v1.1.1
|
||||
github.com/gogo/protobuf v1.3.0
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
|
||||
github.com/golang/protobuf v1.2.0
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/google/uuid v1.0.0
|
||||
github.com/mash/gokmeans v0.0.0-20140614041449-8bbf08905a7e
|
||||
github.com/mattn/go-colorable v0.0.9
|
||||
github.com/mattn/go-isatty v0.0.4
|
||||
github.com/mesos/mesos-go v0.0.8
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe
|
||||
github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec
|
||||
github.com/mash/gokmeans v0.0.0-20170215130432-ea22cff45f59
|
||||
github.com/mattn/go-colorable v0.1.2
|
||||
github.com/mattn/go-isatty v0.0.9
|
||||
github.com/mesos/mesos-go v0.0.10
|
||||
github.com/montanaflynn/stats v0.5.0
|
||||
github.com/pborman/uuid v1.2.0
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/stretchr/testify v1.4.0
|
||||
golang.org/x/crypto v0.0.0-20180927165925-5295e8364332
|
||||
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3
|
||||
golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611
|
||||
gitlab.com/spdf/elektron v0.0.0-20191024200717-26f96f361f10
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
)
|
||||
|
|
44
go.sum
44
go.sum
|
@ -1,41 +1,85 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
|
||||
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/mash/gokmeans v0.0.0-20140614041449-8bbf08905a7e h1:KrPVKjYg/ocMUbv39AQoIINny7acoDE0jghg+vTvTY4=
|
||||
github.com/mash/gokmeans v0.0.0-20140614041449-8bbf08905a7e/go.mod h1:nxv+mR7KuDZRAmEjsCFBQNtWcIty99qUn2Ycbgcns5c=
|
||||
github.com/mash/gokmeans v0.0.0-20170215130432-ea22cff45f59 h1:C7rqeTVPDC/0QZFxfsMvS2y66WjMxQogK8/PTy9Jo0A=
|
||||
github.com/mash/gokmeans v0.0.0-20170215130432-ea22cff45f59/go.mod h1:nxv+mR7KuDZRAmEjsCFBQNtWcIty99qUn2Ycbgcns5c=
|
||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mesos/mesos-go v0.0.8 h1:hiAUHba+ycyZLxDiBUqKs91a0LbHZaAca988LzN19xM=
|
||||
github.com/mesos/mesos-go v0.0.8/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4=
|
||||
github.com/mesos/mesos-go v0.0.10 h1:+M/7Zlkvw4MolkLvXHfj6hkDsLLHOOU54CmOkOUaNBc=
|
||||
github.com/mesos/mesos-go v0.0.10/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/montanaflynn/stats v0.5.0 h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk=
|
||||
github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709 h1:zNBQb37RGLmJybyMcs983HfUfpkw9OTFD9tbBfAViHE=
|
||||
github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
|
||||
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
gitlab.com/spdf/elektron v0.0.0-20191024200717-26f96f361f10 h1:8ySmVAfFtX2mY2o7vbJauJBflwlDk1+XA6Xlp2K6bRg=
|
||||
gitlab.com/spdf/elektron v0.0.0-20191024200717-26f96f361f10/go.mod h1:F6knSIgL9ajNjb0oNAjzV0vpJ51FtNs1UHxw86QQAQ0=
|
||||
golang.org/x/crypto v0.0.0-20180927165925-5295e8364332 h1:hvQVdF6P9DX4OiKA5tpehlG6JsgzmyQiThG7q5Bn3UQ=
|
||||
golang.org/x/crypto v0.0.0-20180927165925-5295e8364332/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ=
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3 h1:dgd4x4kJt7G4k4m93AYLzM8Ni6h2qLTfh9n9vXJT3/0=
|
||||
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
26
logConfig.yaml
Normal file
26
logConfig.yaml
Normal file
|
@ -0,0 +1,26 @@
|
|||
schedTrace:
|
||||
enabled: true
|
||||
filenameExtension: _schedTrace.log
|
||||
allowOnConsole: true
|
||||
sps:
|
||||
enabled: false
|
||||
filenameExtension: _schedPolicySwitch.log
|
||||
allowOnConsole: true
|
||||
console:
|
||||
enabled: true
|
||||
filenameExtension: _console.log
|
||||
minLogLevel: debug
|
||||
allowOnConsole: true
|
||||
pcp:
|
||||
enabled: true
|
||||
filenameExtension: .pcplog
|
||||
allowOnConsole: false
|
||||
schedWindow:
|
||||
enabled: false
|
||||
filenameExtension: _schedWindow.log
|
||||
allowOnConsole: true
|
||||
clsfnTaskDistrOverhead:
|
||||
enabled: false
|
||||
filenameExtension: _classificationOverhead.log
|
||||
allowOnConsole: true
|
||||
|
117
logging/clsfnTaskDistrOverheadLogger.go
Normal file
117
logging/clsfnTaskDistrOverheadLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type clsfnTaskDistrOverheadLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newClsfnTaskDistrOverheadLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *clsfnTaskDistrOverheadLogger {
|
||||
|
||||
cLog := &clsfnTaskDistrOverheadLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.TaskDistrConfig.Enabled,
|
||||
FilenameExtension: config.TaskDistrConfig.FilenameExtension,
|
||||
AllowOnConsole: config.TaskDistrConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
cLog.createLogFile(prefix)
|
||||
return cLog
|
||||
}
|
||||
func (cLog clsfnTaskDistrOverheadLogger) Log(logType int, level log.Level, message string) {
|
||||
if cLog.logType == logType {
|
||||
if cLog.isEnabled() {
|
||||
if cLog.isAllowedOnConsole() {
|
||||
cLog.logger.SetOutput(os.Stdout)
|
||||
cLog.logger.WithFields(cLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
cLog.logger.SetOutput(cLog.logFile)
|
||||
cLog.logger.WithFields(cLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if cLog.next != nil {
|
||||
cLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
cLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (cLog clsfnTaskDistrOverheadLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if cLog.logType == logType {
|
||||
if cLog.isEnabled() {
|
||||
if cLog.isAllowedOnConsole() {
|
||||
cLog.logger.SetOutput(os.Stdout)
|
||||
cLog.logger.WithFields(cLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
cLog.logger.SetOutput(cLog.logFile)
|
||||
cLog.logger.WithFields(cLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
if cLog.next != nil {
|
||||
cLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
cLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (cLog *clsfnTaskDistrOverheadLogger) createLogFile(prefix string) {
|
||||
|
||||
if cLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, cLog.getFilenameExtension()}, "")
|
||||
dirName := cLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
cLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
logging/consoleLogger.go
Normal file
117
logging/consoleLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type consoleLogger struct {
|
||||
baseElektronLogger
|
||||
MinLogLevel string
|
||||
}
|
||||
|
||||
func newConsoleLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *consoleLogger {
|
||||
|
||||
cLog := &consoleLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.ConsoleConfig.Enabled,
|
||||
FilenameExtension: config.ConsoleConfig.FilenameExtension,
|
||||
AllowOnConsole: config.ConsoleConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
|
||||
MinLogLevel: config.ConsoleConfig.MinLogLevel,
|
||||
}
|
||||
|
||||
cLog.createLogFile(prefix)
|
||||
return cLog
|
||||
}
|
||||
|
||||
func (cLog consoleLogger) Log(logType int, level log.Level, message string) {
|
||||
if logType <= cLog.logType {
|
||||
if cLog.isEnabled() {
|
||||
cLog.logger.SetOutput(os.Stdout)
|
||||
cLog.logger.WithFields(cLog.data).Log(level, message)
|
||||
|
||||
cLog.logger.SetOutput(cLog.logFile)
|
||||
cLog.logger.WithFields(cLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger.
|
||||
if cLog.next != nil {
|
||||
cLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
cLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (cLog consoleLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if logType <= cLog.logType {
|
||||
if cLog.isEnabled() {
|
||||
cLog.logger.SetOutput(os.Stdout)
|
||||
cLog.logger.WithFields(cLog.data).Logf(level, msgFmtString, args...)
|
||||
|
||||
cLog.logger.SetOutput(cLog.logFile)
|
||||
cLog.logger.WithFields(cLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
if cLog.next != nil {
|
||||
cLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
cLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (cLog *consoleLogger) createLogFile(prefix string) {
|
||||
// Create log file for the type if it is enabled.
|
||||
if cLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, cLog.getFilenameExtension()}, "")
|
||||
dirName := cLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
cLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
logging/createLogDir.go
Normal file
57
logging/createLogDir.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type logDirectory struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (logD *logDirectory) getDirName() string {
|
||||
return logD.name
|
||||
}
|
||||
|
||||
func (logD *logDirectory) createLogDir(prefix string, startTime time.Time) {
|
||||
|
||||
if logD.name == "" {
|
||||
// Creating directory to store all logs for this run. Directory name format : _2019-November-21_14-33-0.
|
||||
prefix = prefix + "_"
|
||||
logDirName := strings.Join([]string{"./", prefix, strconv.Itoa(startTime.Year())}, "")
|
||||
logDirName = strings.Join([]string{logDirName, startTime.Month().String(), strconv.Itoa(startTime.Day())}, "-")
|
||||
logDirName = strings.Join([]string{logDirName, strconv.Itoa(startTime.Hour())}, "_")
|
||||
logDirName = strings.Join([]string{logDirName, strconv.Itoa(startTime.Minute()), strconv.Itoa(startTime.Second())}, "-")
|
||||
|
||||
if _, err := os.Stat(logDirName); os.IsNotExist(err) {
|
||||
os.Mkdir(logDirName, 0755)
|
||||
} else {
|
||||
log.Println("Unable to create log directory: ", err)
|
||||
logDirName = ""
|
||||
}
|
||||
|
||||
logD.name = logDirName
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type ClsfnTaskDistOverheadLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (col ClsfnTaskDistOverheadLogger) Log(message string) {
|
||||
// Logging the overhead of classifying tasks in the scheduling window and determining the distribution
|
||||
// of light power consuming and heavy power consuming tasks.
|
||||
col.logObserverSpecifics[clsfnTaskDistOverheadLogger].logFile.Println(message)
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
type ConsoleLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (cl ConsoleLogger) Log(message string) {
|
||||
// We need to log to console only if the message is not empty
|
||||
if message != "" {
|
||||
log.Println(message)
|
||||
// Also logging the message to the console log file
|
||||
cl.logObserverSpecifics[conLogger].logFile.Println(message)
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import "github.com/fatih/color"
|
||||
|
||||
// Defining enums of log message types
|
||||
var logMessageNames []string
|
||||
|
||||
// Possible log message types
|
||||
var (
|
||||
ERROR = messageNametoMessageType("ERROR")
|
||||
WARNING = messageNametoMessageType("WARNING")
|
||||
GENERAL = messageNametoMessageType("GENERAL")
|
||||
SUCCESS = messageNametoMessageType("SUCCESS")
|
||||
SCHED_TRACE = messageNametoMessageType("SCHED_TRACE")
|
||||
PCP = messageNametoMessageType("PCP")
|
||||
SPS = messageNametoMessageType("SPS")
|
||||
CLSFN_TASKDIST_OVERHEAD = messageNametoMessageType("CLSFN_TASKDIST_OVERHEAD")
|
||||
SCHED_WINDOW = messageNametoMessageType("SCHED_WINDOW")
|
||||
)
|
||||
|
||||
// Text colors for the different types of log messages.
|
||||
var LogMessageColors map[LogMessageType]*color.Color = map[LogMessageType]*color.Color{
|
||||
ERROR: color.New(color.FgRed, color.Bold),
|
||||
WARNING: color.New(color.FgYellow, color.Bold),
|
||||
GENERAL: color.New(color.FgWhite, color.Bold),
|
||||
SUCCESS: color.New(color.FgGreen, color.Bold),
|
||||
}
|
||||
|
||||
type LogMessageType int
|
||||
|
||||
func (lmt LogMessageType) String() string {
|
||||
return logMessageNames[lmt]
|
||||
}
|
||||
|
||||
func GetLogMessageTypes() []string {
|
||||
return logMessageNames
|
||||
}
|
||||
|
||||
func messageNametoMessageType(messageName string) LogMessageType {
|
||||
// Appending messageName to LogMessageNames
|
||||
logMessageNames = append(logMessageNames, messageName)
|
||||
// Mapping messageName to int
|
||||
return LogMessageType(len(logMessageNames) - 1)
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type LoggerDriver struct {
|
||||
loggerSubject
|
||||
allowedMessageTypes map[LogMessageType]bool
|
||||
}
|
||||
|
||||
func newLogger() *LoggerDriver {
|
||||
logger := &LoggerDriver{
|
||||
allowedMessageTypes: map[LogMessageType]bool{
|
||||
ERROR: true,
|
||||
GENERAL: true,
|
||||
WARNING: true,
|
||||
SCHED_TRACE: true,
|
||||
SUCCESS: true,
|
||||
PCP: true,
|
||||
SPS: true,
|
||||
CLSFN_TASKDIST_OVERHEAD: true,
|
||||
SCHED_WINDOW: true,
|
||||
},
|
||||
}
|
||||
return logger
|
||||
}
|
||||
|
||||
func BuildLogger(startTime time.Time, prefix string) *LoggerDriver {
|
||||
// building logger
|
||||
l := newLogger()
|
||||
attachAllLoggers(l, startTime, prefix)
|
||||
return l
|
||||
}
|
||||
|
||||
func (log *LoggerDriver) EnabledLogging(messageType LogMessageType) {
|
||||
log.allowedMessageTypes[messageType] = true
|
||||
}
|
||||
|
||||
func (log *LoggerDriver) DisableLogging(messageType LogMessageType) {
|
||||
log.allowedMessageTypes[messageType] = false
|
||||
}
|
||||
|
||||
func (log *LoggerDriver) WriteLog(messageType LogMessageType, message string) {
|
||||
// checking to see if logging for given messageType is disabled
|
||||
if log.allowedMessageTypes[messageType] {
|
||||
log.setMessage(message)
|
||||
// notify registered loggers to log
|
||||
log.notify(messageType)
|
||||
}
|
||||
}
|
||||
|
||||
func (log *LoggerDriver) Listen(logMType <-chan LogMessageType, logMsg <-chan string) {
|
||||
for {
|
||||
mType := <-logMType
|
||||
msg := <-logMsg
|
||||
log.WriteLog(mType, msg)
|
||||
}
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
logUtils "github.com/spdfg/elektron/logging/utils"
|
||||
)
|
||||
|
||||
// Names of different loggers
|
||||
const (
|
||||
conLogger = "console-logger"
|
||||
schedTraceLogger = "schedTrace-logger"
|
||||
pcpLogger = "pcp-logger"
|
||||
spsLogger = "schedPolicySwitch-logger"
|
||||
clsfnTaskDistOverheadLogger = "classificationOverhead-logger"
|
||||
schedWindowLogger = "schedWindow-logger"
|
||||
)
|
||||
|
||||
// Logger class factory
|
||||
var Loggers map[string]loggerObserver = map[string]loggerObserver{
|
||||
conLogger: nil,
|
||||
schedTraceLogger: nil,
|
||||
pcpLogger: nil,
|
||||
spsLogger: nil,
|
||||
clsfnTaskDistOverheadLogger: nil,
|
||||
schedWindowLogger: nil,
|
||||
}
|
||||
|
||||
// Logger options to help initialize loggers
|
||||
type loggerOption func(l loggerObserver) error
|
||||
|
||||
func withLogDirectory(startTime time.Time, prefix string) loggerOption {
|
||||
return func(l loggerObserver) error {
|
||||
l.(*loggerObserverImpl).setLogDirectory(logUtils.GetLogDir(startTime, prefix))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// This loggerOption initializes the specifics for each loggerObserver
|
||||
func withLoggerSpecifics(prefix string) loggerOption {
|
||||
return func(l loggerObserver) error {
|
||||
l.(*loggerObserverImpl).logObserverSpecifics = map[string]*specifics{
|
||||
conLogger: &specifics{},
|
||||
schedTraceLogger: &specifics{},
|
||||
pcpLogger: &specifics{},
|
||||
spsLogger: &specifics{},
|
||||
clsfnTaskDistOverheadLogger: &specifics{},
|
||||
schedWindowLogger: &specifics{},
|
||||
}
|
||||
l.(*loggerObserverImpl).setLogFilePrefix(prefix)
|
||||
l.(*loggerObserverImpl).setLogFile()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Build and assign all loggers
|
||||
func attachAllLoggers(lg *LoggerDriver, startTime time.Time, prefix string) {
|
||||
loi := &loggerObserverImpl{}
|
||||
loi.init(withLogDirectory(startTime, strings.Split(prefix, startTime.Format("20060102150405"))[0]),
|
||||
withLoggerSpecifics(prefix))
|
||||
Loggers[conLogger] = &ConsoleLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[schedTraceLogger] = &SchedTraceLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[pcpLogger] = &PCPLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[spsLogger] = &SchedPolicySwitchLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[clsfnTaskDistOverheadLogger] = &ClsfnTaskDistOverheadLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
Loggers[schedWindowLogger] = &SchedWindowLogger{
|
||||
loggerObserverImpl: *loi,
|
||||
}
|
||||
|
||||
for _, lmt := range GetLogMessageTypes() {
|
||||
switch lmt {
|
||||
case SCHED_TRACE.String():
|
||||
lg.attach(SCHED_TRACE, Loggers[schedTraceLogger])
|
||||
case GENERAL.String():
|
||||
lg.attach(GENERAL, Loggers[conLogger])
|
||||
case WARNING.String():
|
||||
lg.attach(WARNING, Loggers[conLogger])
|
||||
case ERROR.String():
|
||||
lg.attach(ERROR, Loggers[conLogger])
|
||||
case SUCCESS.String():
|
||||
lg.attach(SUCCESS, Loggers[conLogger])
|
||||
case PCP.String():
|
||||
lg.attach(PCP, Loggers[pcpLogger])
|
||||
case SPS.String():
|
||||
lg.attach(SPS, Loggers[spsLogger])
|
||||
case CLSFN_TASKDIST_OVERHEAD.String():
|
||||
lg.attach(CLSFN_TASKDIST_OVERHEAD, Loggers[clsfnTaskDistOverheadLogger])
|
||||
case SCHED_WINDOW.String():
|
||||
lg.attach(SCHED_WINDOW, Loggers[schedWindowLogger])
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Logging platform
|
||||
type loggerObserver interface {
|
||||
Log(message string)
|
||||
setLogFile()
|
||||
setLogFilePrefix(prefix string)
|
||||
setLogDirectory(dirName string)
|
||||
init(opts ...loggerOption)
|
||||
}
|
||||
|
||||
type specifics struct {
|
||||
logFilePrefix string
|
||||
logFile *log.Logger
|
||||
}
|
||||
|
||||
type loggerObserverImpl struct {
|
||||
logFile *log.Logger
|
||||
logObserverSpecifics map[string]*specifics
|
||||
logDirectory string
|
||||
}
|
||||
|
||||
func (loi *loggerObserverImpl) init(opts ...loggerOption) {
|
||||
for _, opt := range opts {
|
||||
// applying logger options
|
||||
if err := opt(loi); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (loi loggerObserverImpl) Log(message string) {}
|
||||
|
||||
// Requires logFilePrefix to have already been set
|
||||
func (loi *loggerObserverImpl) setLogFile() {
|
||||
for prefix, ls := range loi.logObserverSpecifics {
|
||||
if logFile, err := os.Create(ls.logFilePrefix); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
fmt.Printf("Creating logFile with pathname: %s, and prefix: %s\n", ls.logFilePrefix, prefix)
|
||||
ls.logFile = log.New(logFile, "", log.LstdFlags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (loi *loggerObserverImpl) setLogFilePrefix(prefix string) {
|
||||
// Setting logFilePrefix for pcp logger
|
||||
pcpLogFilePrefix := prefix + ".pcplog"
|
||||
if loi.logDirectory != "" {
|
||||
pcpLogFilePrefix = loi.logDirectory + "/" + pcpLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[pcpLogger].logFilePrefix = pcpLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for console logger
|
||||
consoleLogFilePrefix := prefix + "_console.log"
|
||||
if loi.logDirectory != "" {
|
||||
consoleLogFilePrefix = loi.logDirectory + "/" + consoleLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[conLogger].logFilePrefix = consoleLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for schedTrace logger
|
||||
schedTraceLogFilePrefix := prefix + "_schedTrace.log"
|
||||
if loi.logDirectory != "" {
|
||||
schedTraceLogFilePrefix = loi.logDirectory + "/" + schedTraceLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[schedTraceLogger].logFilePrefix = schedTraceLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for schedulingPolicySwitch logger
|
||||
schedPolicySwitchLogFilePrefix := prefix + "_schedPolicySwitch.log"
|
||||
if loi.logDirectory != "" {
|
||||
schedPolicySwitchLogFilePrefix = loi.logDirectory + "/" + schedPolicySwitchLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[spsLogger].logFilePrefix = schedPolicySwitchLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for clsfnTaskDist logger.
|
||||
// Execution time of every call to def.GetTaskDistribution(...) would be recorded and logged in this file.
|
||||
// The overhead would be logged in microseconds.
|
||||
clsfnTaskDistOverheadLogFilePrefix := prefix + "_classificationOverhead.log"
|
||||
if loi.logDirectory != "" {
|
||||
clsfnTaskDistOverheadLogFilePrefix = loi.logDirectory + "/" + clsfnTaskDistOverheadLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[clsfnTaskDistOverheadLogger].logFilePrefix = clsfnTaskDistOverheadLogFilePrefix
|
||||
|
||||
// Setting logFilePrefix for schedWindow logger.
|
||||
// Going to log the time stamp when the scheduling window was determined
|
||||
// and the size of the scheduling window.
|
||||
schedWindowLogFilePrefix := prefix + "_schedWindow.log"
|
||||
if loi.logDirectory != "" {
|
||||
schedWindowLogFilePrefix = loi.logDirectory + "/" + schedWindowLogFilePrefix
|
||||
}
|
||||
loi.logObserverSpecifics[schedWindowLogger].logFilePrefix = schedWindowLogFilePrefix
|
||||
}
|
||||
|
||||
func (loi *loggerObserverImpl) setLogDirectory(dirName string) {
|
||||
loi.logDirectory = dirName
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type loggerSubject struct {
|
||||
Registry map[LogMessageType][]loggerObserver
|
||||
message string
|
||||
}
|
||||
|
||||
func (ls *loggerSubject) setMessage(message string) {
|
||||
ls.message = message
|
||||
}
|
||||
|
||||
func (ls *loggerSubject) attach(messageType LogMessageType, lo loggerObserver) {
|
||||
if ls.Registry == nil {
|
||||
ls.Registry = make(map[LogMessageType][]loggerObserver)
|
||||
}
|
||||
ls.Registry[messageType] = append(ls.Registry[messageType], lo)
|
||||
}
|
||||
|
||||
func (ls *loggerSubject) notify(messageType LogMessageType) {
|
||||
for _, logObserver := range ls.Registry[messageType] {
|
||||
logObserver.Log(ls.message)
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type SchedPolicySwitchLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (pl *SchedPolicySwitchLogger) Log(message string) {
|
||||
pl.logObserverSpecifics[spsLogger].logFile.Println(message)
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type SchedTraceLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (stl SchedTraceLogger) Log(message string) {
|
||||
// Logging schedule trace to mentioned file
|
||||
stl.logObserverSpecifics[schedTraceLogger].logFile.Println(message)
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
type SchedWindowLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (swl SchedWindowLogger) Log(message string) {
|
||||
// Logging schedule trace to mentioned file
|
||||
swl.logObserverSpecifics[schedWindowLogger].logFile.Println(message)
|
||||
}
|
54
logging/elektronFormatter.go
Normal file
54
logging/elektronFormatter.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type elektronFormatter struct {
|
||||
TimestampFormat string
|
||||
}
|
||||
|
||||
func (f elektronFormatter) Format(entry *log.Entry) ([]byte, error) {
|
||||
var b *bytes.Buffer
|
||||
|
||||
if entry.Buffer != nil {
|
||||
b = entry.Buffer
|
||||
} else {
|
||||
b = &bytes.Buffer{}
|
||||
}
|
||||
|
||||
level := fmt.Sprintf("[%s]:", strings.ToUpper(entry.Level.String()))
|
||||
message := strings.Join([]string{level, entry.Time.Format(f.TimestampFormat), entry.Message, " "}, " ")
|
||||
|
||||
var formattedFields []string
|
||||
for key, value := range entry.Data {
|
||||
formattedFields = append(formattedFields, strings.Join([]string{key, value.(string)}, "="))
|
||||
}
|
||||
|
||||
b.WriteString(message)
|
||||
b.WriteString(strings.Join(formattedFields, ", "))
|
||||
b.WriteByte('\n')
|
||||
return b.Bytes(), nil
|
||||
}
|
165
logging/logger.go
Normal file
165
logging/logger.go
Normal file
|
@ -0,0 +1,165 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
)
|
||||
|
||||
// var config loggerConfig
|
||||
var formatter elektronFormatter
|
||||
var elektronLoggerInstance elektronLogger
|
||||
|
||||
type elektronLogger interface {
|
||||
setNext(next elektronLogger)
|
||||
Log(logType int, level log.Level, message string)
|
||||
Logf(logType int, level log.Level, msgFmtString string, args ...interface{})
|
||||
WithFields(logData log.Fields) elektronLogger
|
||||
WithField(key string, value string) elektronLogger
|
||||
}
|
||||
|
||||
type baseLogData struct {
|
||||
data log.Fields
|
||||
}
|
||||
|
||||
type baseElektronLogger struct {
|
||||
*baseLogData
|
||||
|
||||
config struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}
|
||||
|
||||
logType int
|
||||
logFile *os.File
|
||||
next elektronLogger
|
||||
logger *log.Logger
|
||||
logDir *logDirectory
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) isEnabled() bool {
|
||||
return l.config.Enabled
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) isAllowedOnConsole() bool {
|
||||
return l.config.AllowOnConsole
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) getFilenameExtension() string {
|
||||
return l.config.FilenameExtension
|
||||
}
|
||||
|
||||
func (l *baseElektronLogger) WithFields(logData log.Fields) elektronLogger {
|
||||
l.data = logData
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *baseElektronLogger) WithField(key string, value string) elektronLogger {
|
||||
l.data[key] = value
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *baseElektronLogger) setNext(next elektronLogger) {
|
||||
l.next = next
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) Log(logType int, level log.Level, message string) {
|
||||
if l.next != nil {
|
||||
l.next.Log(logType, level, message)
|
||||
}
|
||||
}
|
||||
|
||||
func (l baseElektronLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if l.next != nil {
|
||||
l.next.Logf(logType, level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *baseElektronLogger) resetFields() {
|
||||
l.data = nil
|
||||
l.data = log.Fields{}
|
||||
}
|
||||
|
||||
func BuildLogger(prefix string, logConfigFilename string) error {
|
||||
|
||||
// Create the log directory.
|
||||
startTime := time.Now()
|
||||
formatter.TimestampFormat = "2006-01-02 15:04:05"
|
||||
formattedStartTime := startTime.Format("20060102150405")
|
||||
logDir := &logDirectory{}
|
||||
logDir.createLogDir(prefix, startTime)
|
||||
|
||||
// Instantiate the logrus instance.
|
||||
prefix = strings.Join([]string{prefix, formattedStartTime}, "_")
|
||||
logger := &log.Logger{
|
||||
Out: os.Stderr,
|
||||
Level: log.DebugLevel,
|
||||
Formatter: &formatter,
|
||||
}
|
||||
|
||||
// Create a chain of loggers.
|
||||
b := &baseLogData{data: log.Fields{}}
|
||||
head := &baseElektronLogger{baseLogData: b}
|
||||
|
||||
// Read configuration from yaml.
|
||||
if config, err := getConfig(logConfigFilename); err != nil {
|
||||
return errors.Wrap(err, "Failed to build logger")
|
||||
} else {
|
||||
cLog := newConsoleLogger(config, b, CONSOLE, prefix, logger, logDir)
|
||||
pLog := newPCPLogger(config, b, PCP, prefix, logger, logDir)
|
||||
schedTraceLog := newSchedTraceLogger(config, b, SCHED_TRACE, prefix, logger, logDir)
|
||||
spsLog := newSchedPolicySwitchLogger(config, b, SPS, prefix, logger, logDir)
|
||||
schedWindowLog := newSchedWindowLogger(config, b, SCHED_WINDOW, prefix, logger, logDir)
|
||||
tskDistLog := newClsfnTaskDistrOverheadLogger(config, b, CLSFN_TASKDISTR_OVERHEAD, prefix, logger, logDir)
|
||||
|
||||
head.setNext(cLog)
|
||||
cLog.setNext(pLog)
|
||||
pLog.setNext(schedTraceLog)
|
||||
schedTraceLog.setNext(spsLog)
|
||||
spsLog.setNext(schedWindowLog)
|
||||
schedWindowLog.setNext(tskDistLog)
|
||||
|
||||
}
|
||||
|
||||
elektronLoggerInstance = head
|
||||
return nil
|
||||
}
|
||||
|
||||
func Log(logType int, level log.Level, message string) {
|
||||
elektronLoggerInstance.Log(logType, level, message)
|
||||
}
|
||||
|
||||
func Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
elektronLoggerInstance.Logf(logType, level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
func WithFields(logData log.Fields) elektronLogger {
|
||||
return elektronLoggerInstance.WithFields(logData)
|
||||
}
|
||||
|
||||
func WithField(key string, value string) elektronLogger {
|
||||
return elektronLoggerInstance.WithField(key, value)
|
||||
}
|
83
logging/loggerConfig.go
Normal file
83
logging/loggerConfig.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type loggerConfig struct {
|
||||
SchedTraceConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"schedTrace"`
|
||||
|
||||
PCPConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"pcp"`
|
||||
|
||||
ConsoleConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
MinLogLevel string `yaml:"minLogLevel"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"console"`
|
||||
|
||||
SPSConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"sps"`
|
||||
|
||||
TaskDistrConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"clsfnTaskDistrOverhead"`
|
||||
|
||||
SchedWindowConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
FilenameExtension string `yaml:"filenameExtension"`
|
||||
AllowOnConsole bool `yaml:"allowOnConsole"`
|
||||
} `yaml:"schedWindow"`
|
||||
|
||||
Format []string `yaml:"format"`
|
||||
}
|
||||
|
||||
func getConfig(logConfigFilename string) (*loggerConfig, error) {
|
||||
|
||||
yamlFile, err := ioutil.ReadFile(logConfigFilename)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to read log config file")
|
||||
}
|
||||
|
||||
c := &loggerConfig{}
|
||||
err = yaml.Unmarshal(yamlFile, c)
|
||||
if err != nil {
|
||||
log.Fatalf("Error in unmarshalling yaml: %v", err)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
117
logging/pcpLogger.go
Normal file
117
logging/pcpLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type pcpLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newPCPLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *pcpLogger {
|
||||
|
||||
pLog := &pcpLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.PCPConfig.Enabled,
|
||||
FilenameExtension: config.PCPConfig.FilenameExtension,
|
||||
AllowOnConsole: config.PCPConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
pLog.createLogFile(prefix)
|
||||
return pLog
|
||||
}
|
||||
|
||||
func (pLog pcpLogger) Log(logType int, level log.Level, message string) {
|
||||
if pLog.logType == logType {
|
||||
if pLog.isEnabled() {
|
||||
if pLog.isAllowedOnConsole() {
|
||||
pLog.logger.SetOutput(os.Stdout)
|
||||
pLog.logger.WithFields(pLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
pLog.logger.SetOutput(pLog.logFile)
|
||||
pLog.logger.WithFields(pLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
if pLog.next != nil {
|
||||
pLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
pLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (pLog pcpLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if pLog.logType == logType {
|
||||
if pLog.isEnabled() {
|
||||
if pLog.isAllowedOnConsole() {
|
||||
pLog.logger.SetOutput(os.Stdout)
|
||||
pLog.logger.WithFields(pLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
pLog.logger.SetOutput(pLog.logFile)
|
||||
pLog.logger.WithFields(pLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if pLog.next != nil {
|
||||
pLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
pLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (pLog *pcpLogger) createLogFile(prefix string) {
|
||||
if pLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, pLog.getFilenameExtension()}, "")
|
||||
dirName := pLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
pLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
logging/schedPolicySwitchLogger.go
Normal file
117
logging/schedPolicySwitchLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type schedPolicySwitchLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newSchedPolicySwitchLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *schedPolicySwitchLogger {
|
||||
|
||||
sLog := &schedPolicySwitchLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.SPSConfig.Enabled,
|
||||
FilenameExtension: config.SPSConfig.FilenameExtension,
|
||||
AllowOnConsole: config.SPSConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
sLog.createLogFile(prefix)
|
||||
return sLog
|
||||
}
|
||||
|
||||
func (sLog schedPolicySwitchLogger) Log(logType int, level log.Level, message string) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
if sLog.next != nil {
|
||||
sLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog schedPolicySwitchLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if sLog.next != nil {
|
||||
sLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog *schedPolicySwitchLogger) createLogFile(prefix string) {
|
||||
if sLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, sLog.getFilenameExtension()}, "")
|
||||
dirName := sLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
sLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
logging/schedTraceLogger.go
Normal file
117
logging/schedTraceLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type schedTraceLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newSchedTraceLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *schedTraceLogger {
|
||||
|
||||
sLog := &schedTraceLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.SchedTraceConfig.Enabled,
|
||||
FilenameExtension: config.SchedTraceConfig.FilenameExtension,
|
||||
AllowOnConsole: config.SchedTraceConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
sLog.createLogFile(prefix)
|
||||
return sLog
|
||||
}
|
||||
|
||||
func (sLog schedTraceLogger) Log(logType int, level log.Level, message string) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
if sLog.next != nil {
|
||||
sLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog schedTraceLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if sLog.next != nil {
|
||||
sLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog *schedTraceLogger) createLogFile(prefix string) {
|
||||
if sLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, sLog.getFilenameExtension()}, "")
|
||||
dirName := sLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
sLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
logging/schedWindowLogger.go
Normal file
117
logging/schedWindowLogger.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type schedWindowLogger struct {
|
||||
baseElektronLogger
|
||||
}
|
||||
|
||||
func newSchedWindowLogger(
|
||||
config *loggerConfig,
|
||||
b *baseLogData,
|
||||
logType int,
|
||||
prefix string,
|
||||
logger *log.Logger,
|
||||
logDir *logDirectory) *schedWindowLogger {
|
||||
|
||||
sLog := &schedWindowLogger{
|
||||
baseElektronLogger: baseElektronLogger{
|
||||
baseLogData: b,
|
||||
config: struct {
|
||||
Enabled bool
|
||||
FilenameExtension string
|
||||
AllowOnConsole bool
|
||||
}{
|
||||
Enabled: config.SchedWindowConfig.Enabled,
|
||||
FilenameExtension: config.SchedWindowConfig.FilenameExtension,
|
||||
AllowOnConsole: config.SchedWindowConfig.AllowOnConsole,
|
||||
},
|
||||
logType: logType,
|
||||
next: nil,
|
||||
logger: logger,
|
||||
logDir: logDir,
|
||||
},
|
||||
}
|
||||
|
||||
sLog.createLogFile(prefix)
|
||||
return sLog
|
||||
}
|
||||
|
||||
func (sLog schedWindowLogger) Log(logType int, level log.Level, message string) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Log(level, message)
|
||||
}
|
||||
}
|
||||
// Forwarding to next logger
|
||||
if sLog.next != nil {
|
||||
sLog.next.Log(logType, level, message)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog schedWindowLogger) Logf(logType int, level log.Level, msgFmtString string, args ...interface{}) {
|
||||
if sLog.logType == logType {
|
||||
if sLog.isEnabled() {
|
||||
if sLog.isAllowedOnConsole() {
|
||||
sLog.logger.SetOutput(os.Stdout)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
|
||||
sLog.logger.SetOutput(sLog.logFile)
|
||||
sLog.logger.WithFields(sLog.data).Logf(level, msgFmtString, args...)
|
||||
}
|
||||
}
|
||||
if sLog.next != nil {
|
||||
sLog.next.Logf(logType, level, msgFmtString, args...)
|
||||
} else {
|
||||
// Clearing the fields.
|
||||
sLog.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
func (sLog *schedWindowLogger) createLogFile(prefix string) {
|
||||
if sLog.isEnabled() {
|
||||
filename := strings.Join([]string{prefix, sLog.getFilenameExtension()}, "")
|
||||
dirName := sLog.logDir.getDirName()
|
||||
if dirName != "" {
|
||||
if logFile, err := os.Create(filepath.Join(dirName, filename)); err != nil {
|
||||
log.Fatal("Unable to create logFile: ", err)
|
||||
} else {
|
||||
sLog.logFile = logFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +1,28 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package logging
|
||||
package types
|
||||
|
||||
type PCPLogger struct {
|
||||
loggerObserverImpl
|
||||
}
|
||||
|
||||
func (pl *PCPLogger) Log(message string) {
|
||||
pl.logObserverSpecifics[pcpLogger].logFile.Println(message)
|
||||
}
|
||||
const (
|
||||
CONSOLE = iota
|
||||
PCP
|
||||
SCHED_TRACE
|
||||
SPS
|
||||
SCHED_WINDOW
|
||||
CLSFN_TASKDISTR_OVERHEAD
|
||||
)
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package logging
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var LogDir string
|
||||
|
||||
func GetLogDir(startTime time.Time, prefix string) string {
|
||||
if LogDir == "" {
|
||||
LogDir = createLogDir(prefix, startTime)
|
||||
}
|
||||
return LogDir
|
||||
}
|
||||
|
||||
func createLogDir(prefix string, startTime time.Time) string {
|
||||
// Creating directory to store all logs for this run
|
||||
logDirName := "./" + prefix + strconv.Itoa(startTime.Year())
|
||||
logDirName += "-"
|
||||
logDirName += startTime.Month().String()
|
||||
logDirName += "-"
|
||||
logDirName += strconv.Itoa(startTime.Day())
|
||||
logDirName += "_"
|
||||
logDirName += strconv.Itoa(startTime.Hour())
|
||||
logDirName += "-"
|
||||
logDirName += strconv.Itoa(startTime.Minute())
|
||||
logDirName += "-"
|
||||
logDirName += strconv.Itoa(startTime.Second())
|
||||
if _, err := os.Stat(logDirName); os.IsNotExist(err) {
|
||||
os.Mkdir(logDirName, 0755)
|
||||
} else {
|
||||
log.Println("Unable to create log directory: ", err)
|
||||
logDirName = ""
|
||||
}
|
||||
return logDirName
|
||||
}
|
30
pcp/pcp.go
30
pcp/pcp.go
|
@ -1,35 +1,35 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package pcp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"log"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
elekLogDef "github.com/spdfg/elektron/logging/def"
|
||||
log "github.com/sirupsen/logrus"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
)
|
||||
|
||||
func Start(quit chan struct{}, logging *bool, logMType chan elekLogDef.LogMessageType,
|
||||
logMsg chan string, pcpConfigFile string) {
|
||||
func Start(quit chan struct{}, logging *bool, pcpConfigFile string) {
|
||||
var pcpCommand string = "pmdumptext -m -l -f '' -t 1.0 -d , -c " + pcpConfigFile
|
||||
cmd := exec.Command("sh", "-c", pcpCommand)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||
|
@ -47,8 +47,7 @@ func Start(quit chan struct{}, logging *bool, logMType chan elekLogDef.LogMessag
|
|||
scanner.Scan()
|
||||
|
||||
// Write to logfile
|
||||
logMType <- elekLogDef.PCP
|
||||
logMsg <- scanner.Text()
|
||||
elekLog.Log(PCP, log.InfoLevel, scanner.Text())
|
||||
|
||||
// Throw away first set of results
|
||||
scanner.Scan()
|
||||
|
@ -59,16 +58,14 @@ func Start(quit chan struct{}, logging *bool, logMType chan elekLogDef.LogMessag
|
|||
text := scanner.Text()
|
||||
|
||||
if *logging {
|
||||
logMType <- elekLogDef.PCP
|
||||
logMsg <- text
|
||||
elekLog.Log(PCP, log.InfoLevel, text)
|
||||
}
|
||||
|
||||
seconds++
|
||||
}
|
||||
}(logging)
|
||||
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "PCP logging started"
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "PCP logging started")
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -78,8 +75,7 @@ func Start(quit chan struct{}, logging *bool, logMType chan elekLogDef.LogMessag
|
|||
|
||||
select {
|
||||
case <-quit:
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "Stopping PCP logging in 5 seconds"
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Stopping PCP logging in 5 seconds")
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// http://stackoverflow.com/questions/22470193/why-wont-go-kill-a-child-process-correctly
|
||||
|
|
10
pcp/utils.go
10
pcp/utils.go
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package pcp
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package pcp
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package powerCap
|
||||
|
||||
|
@ -22,7 +22,6 @@ import (
|
|||
"bufio"
|
||||
"container/ring"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
@ -30,20 +29,21 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
elekLogDef "github.com/spdfg/elektron/logging/def"
|
||||
log "github.com/sirupsen/logrus"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
"github.com/spdfg/elektron/pcp"
|
||||
"github.com/spdfg/elektron/rapl"
|
||||
)
|
||||
|
||||
func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThreshold, loThreshold float64,
|
||||
logMType chan elekLogDef.LogMessageType, logMsg chan string, pcpConfigFile string) {
|
||||
func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThreshold, loThreshold float64, pcpConfigFile string) {
|
||||
|
||||
var pcpCommand string = "pmdumptext -m -l -f '' -t 1.0 -d , -c " + pcpConfigFile
|
||||
cmd := exec.Command("sh", "-c", pcpCommand, pcpConfigFile)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||
|
||||
if hiThreshold < loThreshold {
|
||||
log.Println("High threshold is lower than low threshold!")
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "High threshold is lower than low threshold!")
|
||||
}
|
||||
|
||||
pipe, err := cmd.StdoutPipe()
|
||||
|
@ -59,8 +59,7 @@ func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThresh
|
|||
scanner.Scan()
|
||||
|
||||
// Write to logfile
|
||||
logMType <- elekLogDef.PCP
|
||||
logMsg <- scanner.Text()
|
||||
elekLog.Log(PCP, log.InfoLevel, scanner.Text())
|
||||
|
||||
headers := strings.Split(scanner.Text(), ",")
|
||||
|
||||
|
@ -95,12 +94,13 @@ func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThresh
|
|||
for scanner.Scan() {
|
||||
|
||||
if *logging {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "Logging PCP..."
|
||||
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Logging PCP...")
|
||||
|
||||
text := scanner.Text()
|
||||
split := strings.Split(text, ",")
|
||||
logMType <- elekLogDef.PCP
|
||||
logMsg <- text
|
||||
|
||||
elekLog.Log(PCP, log.InfoLevel, text)
|
||||
|
||||
totalPower := 0.0
|
||||
for _, powerIndex := range powerIndexes {
|
||||
|
@ -111,8 +111,10 @@ func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThresh
|
|||
powerHistories[host].Value = power
|
||||
powerHistories[host] = powerHistories[host].Next()
|
||||
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Host: %s, Power: %f", indexToHost[powerIndex], (power * pcp.RAPLUnits))
|
||||
elekLog.WithFields(log.Fields{
|
||||
"Host": indexToHost[powerIndex],
|
||||
"Power": fmt.Sprintf("%f", power*pcp.RAPLUnits),
|
||||
}).Log(CONSOLE, log.InfoLevel, "")
|
||||
|
||||
totalPower += power
|
||||
}
|
||||
|
@ -123,12 +125,13 @@ func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThresh
|
|||
|
||||
clusterMean := pcp.AverageClusterPowerHistory(clusterPowerHist)
|
||||
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Total power: %f, %d Sec Avg: %f", clusterPower, clusterPowerHist.Len(), clusterMean)
|
||||
elekLog.WithFields(log.Fields{
|
||||
"Total power": fmt.Sprintf("%f %d Sec", clusterPower, clusterPowerHist.Len()),
|
||||
"Avg": fmt.Sprintf("%f", clusterMean),
|
||||
}).Log(CONSOLE, log.InfoLevel, "")
|
||||
|
||||
if clusterMean > hiThreshold {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "Need to cap a node"
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Need to cap a node")
|
||||
// Create statics for all victims and choose one to cap
|
||||
victims := make([]pcp.Victim, 0, 8)
|
||||
|
||||
|
@ -149,11 +152,10 @@ func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThresh
|
|||
if !cappedHosts[victim.Host] {
|
||||
cappedHosts[victim.Host] = true
|
||||
orderCapped = append(orderCapped, victim.Host)
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Capping Victim %s Avg. Wattage: %f", victim.Host, victim.Watts*pcp.RAPLUnits)
|
||||
elekLog.WithField("Avg. Wattage",
|
||||
fmt.Sprintf("%f", victim.Watts*pcp.RAPLUnits)).Logf(CONSOLE, log.InfoLevel, "Capping Victim %s", victim.Host)
|
||||
if err := rapl.Cap(victim.Host, "rapl", 50); err != nil {
|
||||
logMType <- elekLogDef.ERROR
|
||||
logMsg <- "Error capping host"
|
||||
elekLog.Log(CONSOLE, log.ErrorLevel, "Error capping host")
|
||||
}
|
||||
break // Only cap one machine at at time.
|
||||
}
|
||||
|
@ -166,12 +168,9 @@ func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThresh
|
|||
orderCapped = orderCapped[:len(orderCapped)-1]
|
||||
cappedHosts[host] = false
|
||||
// User RAPL package to send uncap.
|
||||
log.Printf("Uncapping host %s", host)
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Uncapped host %s", host)
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Uncapping host %s", host)
|
||||
if err := rapl.Cap(host, "rapl", 100); err != nil {
|
||||
logMType <- elekLogDef.ERROR
|
||||
logMsg <- "Error capping host"
|
||||
elekLog.Log(CONSOLE, log.ErrorLevel, "Error capping host")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -181,8 +180,7 @@ func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThresh
|
|||
}
|
||||
}(logging, hiThreshold, loThreshold)
|
||||
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "PCP logging started"
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "PCP logging started")
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -192,8 +190,7 @@ func StartPCPLogAndExtremaDynamicCap(quit chan struct{}, logging *bool, hiThresh
|
|||
|
||||
select {
|
||||
case <-quit:
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "Stopping PCP logging in 5 seconds"
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Stopping PCP logging in 5 seconds")
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// http://stackoverflow.com/questions/22470193/why-wont-go-kill-a-child-process-correctly
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package powerCap
|
||||
|
||||
|
@ -22,7 +22,6 @@ import (
|
|||
"bufio"
|
||||
"container/ring"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"os/exec"
|
||||
"sort"
|
||||
|
@ -31,8 +30,10 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/constants"
|
||||
elekLogDef "github.com/spdfg/elektron/logging/def"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
"github.com/spdfg/elektron/pcp"
|
||||
"github.com/spdfg/elektron/rapl"
|
||||
"github.com/spdfg/elektron/utilities"
|
||||
|
@ -48,16 +49,14 @@ func getNextCapValue(curCapValue float64, precision int) float64 {
|
|||
return float64(round(curCapValue*output)) / output
|
||||
}
|
||||
|
||||
func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiThreshold, loThreshold float64,
|
||||
logMType chan elekLogDef.LogMessageType, logMsg chan string, pcpConfigFile string) {
|
||||
func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiThreshold, loThreshold float64, pcpConfigFile string) {
|
||||
|
||||
var pcpCommand string = "pmdumptext -m -l -f '' -t 1.0 -d , -c " + pcpConfigFile
|
||||
cmd := exec.Command("sh", "-c", pcpCommand, pcpConfigFile)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||
|
||||
if hiThreshold < loThreshold {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "High threshold is lower than low threshold!"
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "High threshold is lower than low threshold!")
|
||||
}
|
||||
|
||||
pipe, err := cmd.StdoutPipe()
|
||||
|
@ -73,8 +72,7 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
scanner.Scan()
|
||||
|
||||
// Write to logfile
|
||||
logMType <- elekLogDef.PCP
|
||||
logMsg <- scanner.Text()
|
||||
elekLog.Log(PCP, log.InfoLevel, scanner.Text())
|
||||
|
||||
headers := strings.Split(scanner.Text(), ",")
|
||||
|
||||
|
@ -113,13 +111,11 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
|
||||
for scanner.Scan() {
|
||||
if *logging {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "Logging PCP..."
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Logging PCP...")
|
||||
split := strings.Split(scanner.Text(), ",")
|
||||
|
||||
text := scanner.Text()
|
||||
logMType <- elekLogDef.PCP
|
||||
logMsg <- text
|
||||
elekLog.Log(PCP, log.InfoLevel, text)
|
||||
|
||||
totalPower := 0.0
|
||||
for _, powerIndex := range powerIndexes {
|
||||
|
@ -130,10 +126,10 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
powerHistories[host].Value = power
|
||||
powerHistories[host] = powerHistories[host].Next()
|
||||
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Host: %s, Power %f",
|
||||
indexToHost[powerIndex], (power * pcp.RAPLUnits))
|
||||
|
||||
elekLog.WithFields(log.Fields{
|
||||
"Host": indexToHost[powerIndex],
|
||||
"Power": fmt.Sprintf("%f", power*pcp.RAPLUnits),
|
||||
}).Log(CONSOLE, log.InfoLevel, "")
|
||||
totalPower += power
|
||||
}
|
||||
clusterPower := totalPower * pcp.RAPLUnits
|
||||
|
@ -143,16 +139,16 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
|
||||
clusterMean := pcp.AverageClusterPowerHistory(clusterPowerHist)
|
||||
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Total power: %f, %d Sec Avg: %f", clusterPower, clusterPowerHist.Len(), clusterMean)
|
||||
elekLog.WithFields(log.Fields{
|
||||
"Total power": fmt.Sprintf("%f %d Sec", clusterPower, clusterPowerHist.Len()),
|
||||
"Avg": fmt.Sprintf("%f", clusterMean),
|
||||
}).Log(CONSOLE, log.InfoLevel, "")
|
||||
|
||||
if clusterMean >= hiThreshold {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "Need to cap a node"
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Cap values of capped victims: %v", cappedVictims)
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Cap values of victims to uncap: %v", orderCappedVictims)
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Need to cap a node")
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Cap values of capped victims %v", cappedVictims)
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Cap values of victims to uncap %v", orderCappedVictims)
|
||||
|
||||
// Create statics for all victims and choose one to cap
|
||||
victims := make([]pcp.Victim, 0, 8)
|
||||
|
||||
|
@ -179,11 +175,11 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
}
|
||||
// Need to cap this victim.
|
||||
if err := rapl.Cap(victims[i].Host, "rapl", 50.0); err != nil {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Error capping host %s", victims[i].Host)
|
||||
|
||||
elekLog.Logf(CONSOLE, log.ErrorLevel, "Error capping host %s", victims[i].Host)
|
||||
} else {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Capped host[%s] at %f", victims[i].Host, 50.0)
|
||||
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Capped host[%s] at %f", victims[i].Host, 50.0)
|
||||
// Keeping track of this victim and it's cap value
|
||||
cappedVictims[victims[i].Host] = 50.0
|
||||
newVictimFound = true
|
||||
|
@ -206,12 +202,11 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
if capValue > constants.LowerCapLimit {
|
||||
newCapValue := getNextCapValue(capValue, 2)
|
||||
if err := rapl.Cap(alreadyCappedHosts[i], "rapl", newCapValue); err != nil {
|
||||
logMType <- elekLogDef.ERROR
|
||||
logMsg <- fmt.Sprintf("Error capping host[%s]", alreadyCappedHosts[i])
|
||||
|
||||
elekLog.Logf(CONSOLE, log.ErrorLevel, "Error capping host %s", alreadyCappedHosts[i])
|
||||
} else {
|
||||
// Successful cap
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Capped host[%s] at %f", alreadyCappedHosts[i], newCapValue)
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Capped host[%s] at %f", alreadyCappedHosts[i], newCapValue)
|
||||
// Checking whether this victim can be capped further
|
||||
if newCapValue <= constants.LowerCapLimit {
|
||||
// Deleting victim from cappedVictims.
|
||||
|
@ -234,18 +229,15 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
}
|
||||
}
|
||||
if !canCapAlreadyCappedVictim {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "No Victim left to cap."
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "No Victim left to cap")
|
||||
}
|
||||
}
|
||||
|
||||
} else if clusterMean < loThreshold {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "Need to uncap a node"
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Cap values of capped victims: %v", cappedVictims)
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Cap values of victims to uncap: %v", orderCappedVictims)
|
||||
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Need to uncap a node")
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Cap values of capped victims - %v", cappedVictims)
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Cap values of victims to uncap - %v", orderCappedVictims)
|
||||
if len(orderCapped) > 0 {
|
||||
// We pick the host that is capped the most to uncap.
|
||||
orderCappedToSort := utilities.GetPairList(orderCappedVictims)
|
||||
|
@ -255,12 +247,11 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
// This is a floating point operation and might suffer from precision loss.
|
||||
newUncapValue := orderCappedVictims[hostToUncap] * 2.0
|
||||
if err := rapl.Cap(hostToUncap, "rapl", newUncapValue); err != nil {
|
||||
logMType <- elekLogDef.ERROR
|
||||
logMsg <- fmt.Sprintf("Error uncapping host[%s]", hostToUncap)
|
||||
|
||||
elekLog.Logf(CONSOLE, log.ErrorLevel, "Error uncapping host %s", hostToUncap)
|
||||
} else {
|
||||
// Successful uncap
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- fmt.Sprintf("Uncapped host[%s] to %f", hostToUncap, newUncapValue)
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Uncapped host[%s] to %f", hostToUncap, newUncapValue)
|
||||
// Can we uncap this host further. If not, then we remove its entry from orderCapped
|
||||
if newUncapValue >= 100.0 { // can compare using ==
|
||||
// Deleting entry from orderCapped
|
||||
|
@ -281,8 +272,7 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
}
|
||||
}
|
||||
} else {
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "No host staged for Uncapped"
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "No host staged for Uncapped")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,9 +281,7 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
|
||||
}(logging, hiThreshold, loThreshold)
|
||||
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "PCP logging started"
|
||||
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "PCP logging started")
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -302,8 +290,7 @@ func StartPCPLogAndProgressiveExtremaCap(quit chan struct{}, logging *bool, hiTh
|
|||
|
||||
select {
|
||||
case <-quit:
|
||||
logMType <- elekLogDef.GENERAL
|
||||
logMsg <- "Stopping PCP logging in 5 seconds"
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Stopping PCP logging in 5 seconds")
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// http://stackoverflow.com/questions/22470193/why-wont-go-kill-a-child-process-correctly
|
||||
|
|
12
rapl/cap.go
12
rapl/cap.go
|
@ -1,31 +1,31 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package rapl
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
elekEnv "github.com/spdfg/elektron/environment"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Cap(host, username string, percentage float64) error {
|
||||
|
|
44
scheduler.go
44
scheduler.go
|
@ -21,7 +21,6 @@ package main // import github.com/spdfg/elektron
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
|
@ -30,8 +29,10 @@ import (
|
|||
"github.com/golang/protobuf/proto"
|
||||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/def"
|
||||
elekLogDef "github.com/spdfg/elektron/logging/def"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
"github.com/spdfg/elektron/pcp"
|
||||
"github.com/spdfg/elektron/powerCap"
|
||||
"github.com/spdfg/elektron/schedulers"
|
||||
|
@ -55,6 +56,7 @@ var fixFirstSchedPol = flag.String("fixFirstSchedPol", "", "Name of the scheduli
|
|||
var fixSchedWindow = flag.Bool("fixSchedWindow", false, "Fix the size of the scheduling window that every deployed scheduling policy should schedule, provided switching is enabled.")
|
||||
var schedWindowSize = flag.Int("schedWindowSize", 200, "Size of the scheduling window if fixSchedWindow is set.")
|
||||
var schedPolSwitchCriteria = flag.String("schedPolSwitchCriteria", "taskDist", "Scheduling policy switching criteria.")
|
||||
var logConfigFilename = flag.String("logConfigFilename", "logConfig.yaml", "Log Configuration file name")
|
||||
|
||||
// Short hand args
|
||||
func init() {
|
||||
|
@ -76,6 +78,7 @@ func init() {
|
|||
flag.BoolVar(fixSchedWindow, "fixSw", false, "Fix the size of the scheduling window that every deployed scheduling policy should schedule, provided switching is enabled (shorthand).")
|
||||
flag.IntVar(schedWindowSize, "swSize", 200, "Size of the scheduling window if fixSchedWindow is set (shorthand).")
|
||||
flag.StringVar(schedPolSwitchCriteria, "spsCriteria", "taskDist", "Scheduling policy switching criteria (shorthand).")
|
||||
flag.StringVar(logConfigFilename, "lgCfg", "logConfig.yaml", "Log Configuration file name (shorthand).")
|
||||
}
|
||||
|
||||
func listAllSchedulingPolicies() {
|
||||
|
@ -95,10 +98,6 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Logging channels.
|
||||
logMType := make(chan elekLogDef.LogMessageType)
|
||||
logMsg := make(chan string)
|
||||
|
||||
// First we need to build the scheduler using scheduler options.
|
||||
var schedOptions []schedulers.SchedulerOptions = make([]schedulers.SchedulerOptions, 0, 10)
|
||||
|
||||
|
@ -120,11 +119,6 @@ func main() {
|
|||
pcpLog := make(chan struct{})
|
||||
recordPCP := false
|
||||
|
||||
// Logging channels.
|
||||
// These channels are used by the framework to log messages.
|
||||
// The channels are used to send the type of log message and the message string.
|
||||
schedOptions = append(schedOptions, schedulers.WithLoggingChannels(logMType, logMsg))
|
||||
|
||||
// Shutdown indicator channels.
|
||||
// These channels are used to notify,
|
||||
// 1. scheduling is complete.
|
||||
|
@ -228,28 +222,25 @@ func main() {
|
|||
log.Fatal(fmt.Sprintf("Unable to create scheduler driver: %s", err))
|
||||
}
|
||||
|
||||
// If here, then all command-line arguments validate.
|
||||
// Creating logger and attaching different logging platforms.
|
||||
startTime := time.Now()
|
||||
formattedStartTime := startTime.Format("20060102150405")
|
||||
// Checking if prefix contains any special characters.
|
||||
if strings.Contains(*pcplogPrefix, "/") {
|
||||
log.Fatal("log file prefix should not contain '/'.")
|
||||
}
|
||||
logPrefix := *pcplogPrefix + "_" + formattedStartTime
|
||||
logger := elekLogDef.BuildLogger(startTime, logPrefix)
|
||||
// Starting the logging go-routine.
|
||||
go logger.Listen(logMType, logMsg)
|
||||
|
||||
// Build Logger.
|
||||
if err := elekLog.BuildLogger(*pcplogPrefix, *logConfigFilename); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Starting PCP logging.
|
||||
if noPowercap {
|
||||
go pcp.Start(pcpLog, &recordPCP, logMType, logMsg, *pcpConfigFile)
|
||||
go pcp.Start(pcpLog, &recordPCP, *pcpConfigFile)
|
||||
} else if extrema {
|
||||
go powerCap.StartPCPLogAndExtremaDynamicCap(pcpLog, &recordPCP, *hiThreshold,
|
||||
*loThreshold, logMType, logMsg, *pcpConfigFile)
|
||||
*loThreshold, *pcpConfigFile)
|
||||
} else if progExtrema {
|
||||
go powerCap.StartPCPLogAndProgressiveExtremaCap(pcpLog, &recordPCP, *hiThreshold,
|
||||
*loThreshold, logMType, logMsg, *pcpConfigFile)
|
||||
*loThreshold, *pcpConfigFile)
|
||||
}
|
||||
|
||||
// Take a second between starting PCP log and continuing.
|
||||
|
@ -284,8 +275,6 @@ func main() {
|
|||
close(pcpLog)
|
||||
time.Sleep(5 * time.Second) //Wait for PCP to log a few more seconds
|
||||
// Closing logging channels.
|
||||
close(logMType)
|
||||
close(logMsg)
|
||||
//case <-time.After(shutdownTimeout):
|
||||
}
|
||||
|
||||
|
@ -296,7 +285,10 @@ func main() {
|
|||
|
||||
// Starting the scheduler driver.
|
||||
if status, err := driver.Run(); err != nil {
|
||||
log.Printf("Framework stopped with status %s and error: %s\n", status.String(), err.Error())
|
||||
elekLog.WithFields(log.Fields{
|
||||
"status": status.String(),
|
||||
"error": err.Error(),
|
||||
}).Log(CONSOLE, log.ErrorLevel, "Framework stopped ")
|
||||
}
|
||||
log.Println("Exiting...")
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Exiting...")
|
||||
}
|
||||
|
|
|
@ -1,28 +1,27 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/def"
|
||||
"github.com/spdfg/elektron/utilities/mesosUtils"
|
||||
"github.com/spdfg/elektron/utilities/offerUtils"
|
||||
|
|
|
@ -1,28 +1,27 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/def"
|
||||
"github.com/spdfg/elektron/utilities/mesosUtils"
|
||||
"github.com/spdfg/elektron/utilities/offerUtils"
|
||||
|
|
|
@ -1,27 +1,26 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -29,8 +28,10 @@ import (
|
|||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
"github.com/mesos/mesos-go/api/v0/mesosutil"
|
||||
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/def"
|
||||
elekLogDef "github.com/spdfg/elektron/logging/def"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
"github.com/spdfg/elektron/utilities"
|
||||
"github.com/spdfg/elektron/utilities/schedUtils"
|
||||
)
|
||||
|
@ -68,11 +69,6 @@ type BaseScheduler struct {
|
|||
|
||||
schedTrace *log.Logger
|
||||
|
||||
// Send the type of the message to be logged
|
||||
logMsgType chan elekLogDef.LogMessageType
|
||||
// Send the message to be logged
|
||||
logMsg chan string
|
||||
|
||||
mutex sync.Mutex
|
||||
|
||||
// Whether switching of scheduling policies at runtime has been enabled
|
||||
|
@ -252,179 +248,126 @@ func (s *BaseScheduler) StatusUpdate(driver sched.SchedulerDriver, status *mesos
|
|||
}
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) Log(lmt elekLogDef.LogMessageType, msg string) {
|
||||
s.mutex.Lock()
|
||||
s.logMsgType <- lmt
|
||||
s.logMsg <- msg
|
||||
s.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogTaskStarting(ts *def.Task, offer *mesos.Offer) {
|
||||
lmt := elekLogDef.GENERAL
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
var msg string
|
||||
if ts == nil {
|
||||
msg = msgColor.Sprintf("TASKS STARTING... host = [%s]", offer.GetHostname())
|
||||
elekLog.WithField("host", offer.GetHostname()).Log(CONSOLE, log.InfoLevel, "TASKS STARTING...")
|
||||
} else {
|
||||
msg = msgColor.Sprintf("TASK STARTING... task = [%s], Instance = %d, host = [%s]",
|
||||
ts.Name, *ts.Instances, offer.GetHostname())
|
||||
elekLog.WithFields(log.Fields{
|
||||
"task": ts.Name,
|
||||
"Instance": fmt.Sprintf("%d", *ts.Instances),
|
||||
"host": offer.GetHostname(),
|
||||
}).Log(CONSOLE, log.InfoLevel, "TASK STARTING... ")
|
||||
}
|
||||
s.Log(lmt, msg)
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogTaskWattsConsideration(ts def.Task, host string, wattsToConsider float64) {
|
||||
lmt := elekLogDef.GENERAL
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("Watts considered for task[%s] and host[%s] = %f Watts",
|
||||
ts.Name, host, wattsToConsider)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithFields(log.Fields{
|
||||
"task": ts.Name,
|
||||
"host": host,
|
||||
"Watts": fmt.Sprintf("%f", wattsToConsider),
|
||||
}).Log(CONSOLE, log.InfoLevel, "Watts considered for ")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogOffersReceived(offers []*mesos.Offer) {
|
||||
lmt := elekLogDef.GENERAL
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("Received %d resource offers", len(offers))
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithField("numOffers", fmt.Sprintf("%d", len(offers))).Log(CONSOLE, log.InfoLevel, "Resource offers received")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogNoPendingTasksDeclineOffers(offer *mesos.Offer) {
|
||||
lmt := elekLogDef.WARNING
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("DECLINING OFFER for host[%s]... "+
|
||||
"No tasks left to schedule", offer.GetHostname())
|
||||
s.Log(lmt, msg)
|
||||
elekLog.Logf(CONSOLE, log.WarnLevel, "DECLINING OFFER for host %s. No tasks left to schedule", offer.GetHostname())
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogNumberOfRunningTasks() {
|
||||
lmt := elekLogDef.GENERAL
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("Number of tasks still Running = %d", s.tasksRunning)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Number of tasks still running %d", s.tasksRunning)
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogCoLocatedTasks(slaveID string) {
|
||||
lmt := elekLogDef.GENERAL
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
buffer := bytes.Buffer{}
|
||||
buffer.WriteString(fmt.Sprintln("Colocated with:"))
|
||||
s.TasksRunningMutex.Lock()
|
||||
for taskName := range s.Running[slaveID] {
|
||||
buffer.WriteString(fmt.Sprintln(taskName))
|
||||
}
|
||||
s.TasksRunningMutex.Unlock()
|
||||
msg := msgColor.Sprintf(buffer.String())
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithField("Tasks", buffer.String()).Log(CONSOLE, log.InfoLevel, "Colocated with")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogSchedTrace(taskToSchedule *mesos.TaskInfo, offer *mesos.Offer) {
|
||||
msg := fmt.Sprint(offer.GetHostname() + ":" + taskToSchedule.GetTaskId().GetValue())
|
||||
s.Log(elekLogDef.SCHED_TRACE, msg)
|
||||
elekLog.WithField(offer.GetHostname(), taskToSchedule.GetTaskId().GetValue()).Log(SCHED_TRACE, log.InfoLevel, "")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogTerminateScheduler() {
|
||||
lmt := elekLogDef.GENERAL
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprint("Done scheduling all tasks!")
|
||||
s.Log(lmt, msg)
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Done scheduling all tasks!")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogInsufficientResourcesDeclineOffer(offer *mesos.Offer,
|
||||
offerResources ...interface{}) {
|
||||
lmt := elekLogDef.WARNING
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
buffer := bytes.Buffer{}
|
||||
buffer.WriteString(fmt.Sprintln("DECLINING OFFER... Offer has insufficient resources to launch a task"))
|
||||
buffer.WriteString(fmt.Sprintf("Offer Resources <CPU: %f, RAM: %f, Watts: %f>", offerResources...))
|
||||
msg := msgColor.Sprint(buffer.String())
|
||||
s.Log(lmt, msg)
|
||||
buffer.WriteString(fmt.Sprintf("<CPU: %f, RAM: %f, Watts: %f>", offerResources...))
|
||||
elekLog.WithField("Offer Resources", buffer.String()).Log(CONSOLE,
|
||||
log.WarnLevel, "DECLINING OFFER... Offer has insufficient resources to launch a task")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogOfferRescinded(offerID *mesos.OfferID) {
|
||||
lmt := elekLogDef.ERROR
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("OFFER RESCINDED: OfferID = %s", offerID)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithField("OfferID", *offerID.Value).Log(CONSOLE, log.ErrorLevel, "OFFER RESCINDED")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogSlaveLost(slaveID *mesos.SlaveID) {
|
||||
lmt := elekLogDef.ERROR
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("SLAVE LOST: SlaveID = %s", slaveID)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithField("SlaveID", *slaveID.Value).Log(CONSOLE, log.ErrorLevel, "SLAVE LOST")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogExecutorLost(executorID *mesos.ExecutorID, slaveID *mesos.SlaveID) {
|
||||
lmt := elekLogDef.ERROR
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("EXECUTOR LOST: ExecutorID = %s, SlaveID = %s", executorID, slaveID)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithFields(log.Fields{
|
||||
"ExecutorID": *executorID.Value,
|
||||
"SlaveID": *slaveID.Value,
|
||||
}).Log(CONSOLE, log.ErrorLevel, "EXECUTOR LOST")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogFrameworkMessage(executorID *mesos.ExecutorID,
|
||||
slaveID *mesos.SlaveID, message string) {
|
||||
lmt := elekLogDef.GENERAL
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("Received Framework message from executor [%s]: %s", executorID, message)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel, "Received Framework message from executor %v", executorID)
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogMesosError(err string) {
|
||||
lmt := elekLogDef.ERROR
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("MESOS ERROR: %s", err)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.Logf(CONSOLE, log.ErrorLevel, "MESOS CONSOLE %v", err)
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogElectronError(err error) {
|
||||
lmt := elekLogDef.ERROR
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("ELECTRON ERROR: %v", err)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.Logf(CONSOLE, log.ErrorLevel, "ELEKTRON CONSOLE %v", err)
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogFrameworkRegistered(frameworkID *mesos.FrameworkID,
|
||||
masterInfo *mesos.MasterInfo) {
|
||||
lmt := elekLogDef.SUCCESS
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("FRAMEWORK REGISTERED! frameworkID = %s, master = %s",
|
||||
frameworkID, masterInfo)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithFields(log.Fields{
|
||||
"frameworkID": *frameworkID.Value,
|
||||
"master": fmt.Sprintf("%v", masterInfo),
|
||||
}).Log(CONSOLE, log.InfoLevel, "FRAMEWORK REGISTERED!")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogFrameworkReregistered(masterInfo *mesos.MasterInfo) {
|
||||
lmt := elekLogDef.GENERAL
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprintf("Framework re-registered with master %s", masterInfo)
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithField("master", fmt.Sprintf("%v", masterInfo)).Log(CONSOLE, log.InfoLevel, "Framework re-registered")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogDisconnected() {
|
||||
lmt := elekLogDef.WARNING
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := msgColor.Sprint("Framework disconnected with master")
|
||||
s.Log(lmt, msg)
|
||||
elekLog.Log(CONSOLE, log.WarnLevel, "Framework disconnected with master")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogTaskStatusUpdate(status *mesos.TaskStatus) {
|
||||
var lmt elekLogDef.LogMessageType
|
||||
level := log.InfoLevel
|
||||
switch *status.State {
|
||||
case mesos.TaskState_TASK_ERROR, mesos.TaskState_TASK_FAILED,
|
||||
mesos.TaskState_TASK_KILLED, mesos.TaskState_TASK_LOST:
|
||||
lmt = elekLogDef.ERROR
|
||||
case mesos.TaskState_TASK_FINISHED:
|
||||
lmt = elekLogDef.SUCCESS
|
||||
level = log.ErrorLevel
|
||||
default:
|
||||
lmt = elekLogDef.GENERAL
|
||||
level = log.InfoLevel
|
||||
}
|
||||
msgColor := elekLogDef.LogMessageColors[lmt]
|
||||
msg := elekLogDef.LogMessageColors[elekLogDef.GENERAL].Sprintf("Task Status received for task [%s] --> %s",
|
||||
*status.TaskId.Value, msgColor.Sprint(NameFor(status.State)))
|
||||
s.Log(lmt, msg)
|
||||
elekLog.WithFields(log.Fields{
|
||||
"task": *status.TaskId.Value,
|
||||
"state": NameFor(status.State),
|
||||
}).Log(CONSOLE, level, "Task Status received")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogSchedPolicySwitch(name string, nextPolicy SchedPolicyState) {
|
||||
logSPS := func() {
|
||||
s.Log(elekLogDef.SPS, name)
|
||||
elekLog.WithField("Name", name).Log(SPS, log.InfoLevel, "")
|
||||
}
|
||||
if s.hasReceivedResourceOffers && (s.curSchedPolicy != nextPolicy) {
|
||||
logSPS()
|
||||
|
@ -433,10 +376,13 @@ func (s *BaseScheduler) LogSchedPolicySwitch(name string, nextPolicy SchedPolicy
|
|||
}
|
||||
// Logging the size of the scheduling window and the scheduling policy
|
||||
// that is going to schedule the tasks in the scheduling window.
|
||||
s.Log(elekLogDef.SCHED_WINDOW, fmt.Sprintf("%d %s", s.schedWindowSize, name))
|
||||
elekLog.WithFields(log.Fields{
|
||||
"Window size": fmt.Sprintf("%d", s.schedWindowSize),
|
||||
"Name": name,
|
||||
}).Log(SCHED_WINDOW, log.InfoLevel, "")
|
||||
}
|
||||
|
||||
func (s *BaseScheduler) LogClsfnAndTaskDistOverhead(overhead time.Duration) {
|
||||
// Logging the overhead in microseconds.
|
||||
s.Log(elekLogDef.CLSFN_TASKDIST_OVERHEAD, fmt.Sprintf("%f", float64(overhead.Nanoseconds())/1000.0))
|
||||
elekLog.WithField("Overhead in microseconds", fmt.Sprintf("%f", float64(overhead.Nanoseconds())/1000.0)).Log(CLSFN_TASKDISTR_OVERHEAD, log.InfoLevel, "")
|
||||
}
|
||||
|
|
|
@ -1,28 +1,27 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/def"
|
||||
"github.com/spdfg/elektron/utilities/mesosUtils"
|
||||
"github.com/spdfg/elektron/utilities/offerUtils"
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
|
@ -24,7 +24,6 @@ import (
|
|||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
||||
"github.com/spdfg/elektron/def"
|
||||
elekLogDef "github.com/spdfg/elektron/logging/def"
|
||||
)
|
||||
|
||||
// Implements mesos scheduler.
|
||||
|
@ -38,8 +37,6 @@ type ElectronScheduler interface {
|
|||
// Each of these functions are supposed to call the Log(...) that sends the
|
||||
// log message type, and the log message to the corresponding channels.
|
||||
|
||||
// Pass the logMessageType and the logMessage to the loggers for logging.
|
||||
Log(logMType elekLogDef.LogMessageType, logMsg string)
|
||||
// To be called when about to launch a task.
|
||||
// Log message indicating that a task is about to start executing.
|
||||
// Also, log the host on which the task is going to be launched.
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
|
|
|
@ -20,24 +20,26 @@ package schedulers
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/constants"
|
||||
"github.com/spdfg/elektron/def"
|
||||
elekLogDef "github.com/spdfg/elektron/logging/def"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
"github.com/spdfg/elektron/utilities"
|
||||
"github.com/spdfg/elektron/utilities/mesosUtils"
|
||||
"log"
|
||||
)
|
||||
|
||||
func coLocated(tasks map[string]bool, s BaseScheduler) {
|
||||
|
||||
for task := range tasks {
|
||||
s.Log(elekLogDef.GENERAL, task)
|
||||
for _, task := range tasks {
|
||||
elekLog.WithField("Task", fmt.Sprintf("%v", task)).Log(CONSOLE, log.InfoLevel, "")
|
||||
}
|
||||
|
||||
s.Log(elekLogDef.GENERAL, "---------------------")
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "---------------------")
|
||||
}
|
||||
|
||||
// Get the powerClass of the given hostname.
|
||||
|
@ -129,14 +131,6 @@ func WithPCPLog(pcpLog chan struct{}) SchedulerOptions {
|
|||
}
|
||||
}
|
||||
|
||||
func WithLoggingChannels(lmt chan elekLogDef.LogMessageType, msg chan string) SchedulerOptions {
|
||||
return func(s ElectronScheduler) error {
|
||||
s.(*BaseScheduler).logMsgType = lmt
|
||||
s.(*BaseScheduler).logMsg = msg
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithSchedPolSwitchEnabled(enableSchedPolicySwitch bool, switchingCriteria string) SchedulerOptions {
|
||||
return func(s ElectronScheduler) error {
|
||||
s.(*BaseScheduler).schedPolSwitchEnabled = enableSchedPolicySwitch
|
||||
|
|
|
@ -1,32 +1,33 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
sched "github.com/mesos/mesos-go/api/v0/scheduler"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/def"
|
||||
elekLogDef "github.com/spdfg/elektron/logging/def"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
)
|
||||
|
||||
type SchedPolicyContext interface {
|
||||
|
@ -89,7 +90,7 @@ func switchTaskDistBased(baseSchedRef *BaseScheduler) string {
|
|||
// Determine the distribution of tasks in the new scheduling window.
|
||||
taskDist, err := def.GetTaskDistributionInWindow(baseSchedRef.schedWindowSize, baseSchedRef.tasks)
|
||||
baseSchedRef.LogClsfnAndTaskDistOverhead(time.Now().Sub(startTime))
|
||||
baseSchedRef.Log(elekLogDef.GENERAL, fmt.Sprintf("Switching... TaskDistribution[%f]", taskDist))
|
||||
elekLog.WithField("Task Distribution", fmt.Sprintf("%f", taskDist)).Log(CONSOLE, log.InfoLevel, "Switching... ")
|
||||
if err != nil {
|
||||
// All the tasks in the window were only classified into 1 cluster.
|
||||
// Max-Min and Max-GreedyMins would work the same way as Bin-Packing for this situation.
|
||||
|
@ -217,9 +218,11 @@ func (bsps *baseSchedPolicyState) SwitchIfNecessary(spc SchedPolicyContext) {
|
|||
switchToPolicyName = switchBasedOn[baseSchedRef.schedPolSwitchCriteria](baseSchedRef)
|
||||
} else {
|
||||
// We continue working with the currently deployed scheduling policy.
|
||||
log.Println("Continuing with the current scheduling policy...")
|
||||
log.Printf("TasksScheduled[%d], SchedWindowSize[%d]", bsps.numTasksScheduled,
|
||||
baseSchedRef.schedWindowSize)
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Continuing with the current scheduling policy...")
|
||||
elekLog.WithFields(log.Fields{
|
||||
"TasksScheduled": fmt.Sprintf("%d", bsps.numTasksScheduled),
|
||||
"SchedWindowSize": fmt.Sprintf("%d", baseSchedRef.schedWindowSize),
|
||||
}).Log(CONSOLE, log.InfoLevel, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -231,9 +234,11 @@ func (bsps *baseSchedPolicyState) SwitchIfNecessary(spc SchedPolicyContext) {
|
|||
bsps.numTasksScheduled = 0
|
||||
} else {
|
||||
// We continue working with the currently deployed scheduling policy.
|
||||
log.Println("Continuing with the current scheduling policy...")
|
||||
log.Printf("TasksScheduled[%d], SchedWindowSize[%d]", bsps.numTasksScheduled,
|
||||
baseSchedRef.schedWindowSize)
|
||||
elekLog.Log(CONSOLE, log.InfoLevel, "Continuing with the current scheduling policy...")
|
||||
elekLog.WithFields(log.Fields{
|
||||
"TasksScheduled": fmt.Sprintf("%d", bsps.numTasksScheduled),
|
||||
"SchedWindowSize": fmt.Sprintf("%d", baseSchedRef.schedWindowSize),
|
||||
}).Log(CONSOLE, log.InfoLevel, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedulers
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package mesosUtils
|
||||
|
||||
|
|
|
@ -1,29 +1,31 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package offerUtils
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
mesos "github.com/mesos/mesos-go/api/v0/mesosproto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/constants"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
)
|
||||
|
||||
func OfferAgg(offer *mesos.Offer) (float64, float64, float64) {
|
||||
|
@ -88,12 +90,15 @@ func UpdateEnvironment(offer *mesos.Offer) {
|
|||
var host = offer.GetHostname()
|
||||
// If this host is not present in the set of hosts.
|
||||
if _, ok := constants.Hosts[host]; !ok {
|
||||
log.Printf("New host detected. Adding host [%s]", host)
|
||||
elekLog.WithField("host", host).Log(CONSOLE, log.InfoLevel, "New host detected")
|
||||
// Add this host.
|
||||
constants.Hosts[host] = struct{}{}
|
||||
// Get the power class of this host.
|
||||
class := PowerClass(offer)
|
||||
log.Printf("Registering the power class... Host [%s] --> PowerClass [%s]", host, class)
|
||||
elekLog.WithFields(log.Fields{
|
||||
"host": host,
|
||||
"PowerClass": class,
|
||||
}).Log(CONSOLE, log.InfoLevel, "Registering the power class...")
|
||||
// If new power class, register the power class.
|
||||
if _, ok := constants.PowerClasses[class]; !ok {
|
||||
constants.PowerClasses[class] = make(map[string]struct{})
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
/*
|
||||
A utility to calculate the running average.
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package schedUtils
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spdfg/elektron/def"
|
||||
elekLog "github.com/spdfg/elektron/logging"
|
||||
. "github.com/spdfg/elektron/logging/types"
|
||||
"github.com/spdfg/elektron/utilities"
|
||||
)
|
||||
|
||||
|
@ -77,8 +78,8 @@ func (s *fillNextOfferCycle) apply(taskQueue []def.Task) (int, int) {
|
|||
for _, task := range taskQueue {
|
||||
numberOfTasksTraversed++
|
||||
for i := *task.Instances; i > 0; i-- {
|
||||
log.Printf("Checking if Instance #%d of Task[%s] can be scheduled "+
|
||||
"during the next offer cycle...", i, task.Name)
|
||||
elekLog.Logf(CONSOLE, log.InfoLevel,
|
||||
"Checking if Instance #%d of Task[%s] can be scheduled "+"during the next offer cycle...", i, task.Name)
|
||||
if canSchedule(task) {
|
||||
filledCPU += task.CPU
|
||||
filledRAM += task.RAM
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package utilities
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (C) 2018 spdfg
|
||||
//
|
||||
//
|
||||
// This file is part of Elektron.
|
||||
//
|
||||
//
|
||||
// Elektron 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// Elektron 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 Elektron. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
//
|
||||
|
||||
package utilities
|
||||
|
||||
|
|
Reference in a new issue