mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
worked on the web interface for schedduler (dropped) and started new logging to syslog
This commit is contained in:
@@ -21,9 +21,9 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"github.com/cgrates/cgrates/balancer"
|
||||
"github.com/cgrates/cgrates/sessionmanager"
|
||||
"github.com/cgrates/cgrates/timespans"
|
||||
"github.com/cgrates/cgrates/balancer"
|
||||
"log"
|
||||
"runtime"
|
||||
"time"
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
var (
|
||||
raterAddress = flag.String("rateraddr", "127.0.0.1:2000", "Rater server address (localhost:2000)")
|
||||
rpcAddress = flag.String("rpcaddr", "127.0.0.1:2001", "Json RPC server address (localhost:2001)")
|
||||
httpApiAddress = flag.String("httpapiaddr", "127.0.0.1:8000", "Http API server address (localhost:2002)")
|
||||
httpApiAddress = flag.String("httpapiaddr", "127.0.0.1:8000", "Http API server address (localhost:8000)")
|
||||
freeswitch = flag.Bool("freeswitch", false, "connect to freeswitch server")
|
||||
freeswitchsrv = flag.String("freeswitchsrv", "localhost:8021", "freeswitch address host:port")
|
||||
freeswitchpass = flag.String("freeswitchpass", "ClueCon", "freeswitch address host:port")
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
Handler for the statistics web client
|
||||
*/
|
||||
func statusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if t, err := template.ParseFiles("templates/status.html"); err == nil {
|
||||
if t, err := template.ParseFiles("templates/base.html", "templates/status.html"); err == nil {
|
||||
t.Execute(w, bal.GetClientAddresses())
|
||||
} else {
|
||||
log.Print("Error rendering status: ", err)
|
||||
|
||||
45
cmd/cgr-balancer/templates/actiontimings.html
Normal file
45
cmd/cgr-balancer/templates/actiontimings.html
Normal file
@@ -0,0 +1,45 @@
|
||||
{{define "title"}}CGRateS Action Timings{{end}}
|
||||
{{define "content"}}
|
||||
<div class="modal hide fade" id="myModal">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3>Modal header</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>One fine body…</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn" data-dismiss="modal">Close</a>
|
||||
<a href="#" class="btn btn-primary">Save changes</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span7">
|
||||
<h1>Action timings</h1>
|
||||
<table id="rater-table" class="table table-striped">
|
||||
{{range .}}
|
||||
<tr>
|
||||
<td>{{.}}</td>
|
||||
<td><a class="btn" data-toggle="modal" href="#myModal" >Edit</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</div>
|
||||
<div class="span5">
|
||||
<h2>Heading</h2>
|
||||
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
|
||||
<p><a class="btn" href="#">View details »</a></p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "extrascripts"}}
|
||||
<script src="static/js/jquery.flot.min.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
$('#myModal').modal({
|
||||
show: false
|
||||
})
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
61
cmd/cgr-balancer/templates/base.html
Normal file
61
cmd/cgr-balancer/templates/base.html
Normal file
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{template "title" .}}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Describes the internal status of CGRateS server.">
|
||||
<meta name="author" content="Radu Ioan Fericean">
|
||||
|
||||
<!-- Le styles -->
|
||||
<link href="static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-top: 60px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
</style>
|
||||
<link href="static/css/bootstrap-responsive.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</a>
|
||||
<a class="brand" href="#">CGRateS</a>
|
||||
<div class="nav-collapse">
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
|
||||
{{template "content" .}}
|
||||
|
||||
<hr>
|
||||
|
||||
<footer>
|
||||
<p>© Radu Fericean 2012</p>
|
||||
</footer>
|
||||
|
||||
</div> <!-- /container -->
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="static/js/jquery-1.7.2.min.js"></script>
|
||||
<script src="static/js/bootstrap.min.js"></script>
|
||||
</script>{{template "extrascripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,48 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CGRateS Status</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Describes the internal status of CGRateS server.">
|
||||
<meta name="author" content="Radu Ioan Fericean">
|
||||
|
||||
<!-- Le styles -->
|
||||
<link href="static/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-top: 60px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
</style>
|
||||
<link href="static/css/bootstrap-responsive.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</a>
|
||||
<a class="brand" href="#">CGRateS</a>
|
||||
<div class="nav-collapse">
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- Main hero unit for a primary marketing message or call to action -->
|
||||
{{define "title"}}CGRateS Status{{end}}
|
||||
{{define "content"}}
|
||||
<div class="hero-unit">
|
||||
<h1>Conected raters</h1>
|
||||
<table id="rater-table" class="table table-striped">
|
||||
@@ -52,8 +9,7 @@
|
||||
</table>
|
||||
<p><a id="rater-refresh" href="#" class="btn btn-primary btn-large">Refresh</a></p>
|
||||
</div>
|
||||
|
||||
<!-- Example row of columns -->
|
||||
|
||||
<div class="row">
|
||||
<div class="span7">
|
||||
<h2>Memory consumption (KB)</h2>
|
||||
@@ -65,21 +21,10 @@
|
||||
<p><a class="btn" href="#">View details »</a></p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<hr>
|
||||
|
||||
<footer>
|
||||
<p>© Radu Fericean 2012</p>
|
||||
</footer>
|
||||
|
||||
</div> <!-- /container -->
|
||||
|
||||
<!-- Le javascript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="static/js/jquery-1.7.2.min.js"></script>
|
||||
<script src="static/js/bootstrap.min.js"></script>
|
||||
<script src="static/js/jquery.flot.min.js" type="text/javascript"></script>
|
||||
{{define "extrascripts"}}
|
||||
<script src="static/js/jquery.flot.min.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
// we use an inline data source in the example, usually data would
|
||||
@@ -134,5 +79,4 @@
|
||||
})
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
@@ -19,9 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cgrates/cgrates/timespans"
|
||||
"log"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@@ -127,6 +127,7 @@ func (csvr *CSVReader) loadActionTimings(fn string) {
|
||||
}
|
||||
for _, t := range ts {
|
||||
at := ×pans.ActionTiming{
|
||||
Id: timespans.GenUUID(),
|
||||
Tag: record[2],
|
||||
Weight: weight,
|
||||
Timing: ×pans.Interval{
|
||||
@@ -139,7 +140,6 @@ func (csvr *CSVReader) loadActionTimings(fn string) {
|
||||
}
|
||||
actionsTimings[tag] = append(actionsTimings[tag], at)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
"github.com/cgrates/cgrates/timespans"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Rate struct {
|
||||
|
||||
46
cmd/cgr-scheduler/actiontimings_webapp.go
Normal file
46
cmd/cgr-scheduler/actiontimings_webapp.go
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Rating system designed to be used in VoIP Carriers World
|
||||
Copyright (C) 2012 Radu Ioan Fericean
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
actionTimings, err := storage.GetAllActionTimings()
|
||||
if err != nil {
|
||||
log.Print("Cannot get action timings:", err)
|
||||
}
|
||||
if t, err := template.ParseFiles("templates/base.html", "templates/actiontimings.html"); err == nil {
|
||||
t.Execute(w, actionTimings)
|
||||
} else {
|
||||
log.Print("Error rendering status: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func startWebApp() {
|
||||
http.Handle("/static/", http.FileServer(http.Dir("")))
|
||||
http.HandleFunc("/", handler)
|
||||
err := http.ListenAndServe(*httpAddress, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,17 @@ import (
|
||||
"github.com/cgrates/cgrates/timespans"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
"os/signal"
|
||||
"sort"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
redisserver = flag.String("redisserver", "127.0.0.1:6379", "redis server address (tcp:127.0.0.1:6379)")
|
||||
redisdb = flag.Int("rdb", 10, "redis database number (10)")
|
||||
redispass = flag.String("pass", "", "redis database password")
|
||||
httpAddress = flag.String("httpapiaddr", "127.0.0.1:8000", "Http API server address (localhost:8000)")
|
||||
storage timespans.StorageGetter
|
||||
timer *time.Timer
|
||||
restartLoop = make(chan byte)
|
||||
@@ -115,5 +116,6 @@ func main() {
|
||||
timespans.SetStorageGetter(storage)
|
||||
loadActionTimings()
|
||||
go stopSingnalHandler()
|
||||
// go startWebApp()
|
||||
s.loop()
|
||||
}
|
||||
|
||||
1
cmd/cgr-scheduler/static
Symbolic link
1
cmd/cgr-scheduler/static
Symbolic link
@@ -0,0 +1 @@
|
||||
../cgr-balancer/static/
|
||||
1
cmd/cgr-scheduler/templates
Symbolic link
1
cmd/cgr-scheduler/templates
Symbolic link
@@ -0,0 +1 @@
|
||||
../cgr-balancer/templates/
|
||||
@@ -19,6 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package timespans
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
@@ -32,6 +34,7 @@ const (
|
||||
)
|
||||
|
||||
type ActionTiming struct {
|
||||
Id string // identify the timing
|
||||
Tag string // informative purpos only
|
||||
UserBalanceIds []string
|
||||
Timing *Interval
|
||||
@@ -210,6 +213,7 @@ func (at *ActionTiming) String() string {
|
||||
Serializes the action timing for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (at *ActionTiming) store() (result string) {
|
||||
result += at.Id + "|"
|
||||
result += at.Tag + "|"
|
||||
for _, ubi := range at.UserBalanceIds {
|
||||
result += ubi + ","
|
||||
@@ -226,13 +230,28 @@ De-serializes the action timing for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (at *ActionTiming) restore(input string) {
|
||||
elements := strings.Split(input, "|")
|
||||
at.Tag = elements[0]
|
||||
for _, ubi := range strings.Split(elements[1], ",") {
|
||||
at.Id = elements[0]
|
||||
at.Tag = elements[1]
|
||||
for _, ubi := range strings.Split(elements[2], ",") {
|
||||
at.UserBalanceIds = append(at.UserBalanceIds, ubi)
|
||||
}
|
||||
|
||||
at.Timing = &Interval{}
|
||||
at.Timing.restore(elements[2])
|
||||
at.Weight, _ = strconv.ParseFloat(elements[3], 64)
|
||||
at.ActionsId = elements[4]
|
||||
at.Timing.restore(elements[3])
|
||||
at.Weight, _ = strconv.ParseFloat(elements[4], 64)
|
||||
at.ActionsId = elements[5]
|
||||
}
|
||||
|
||||
// helper function for uuid generation
|
||||
func GenUUID() string {
|
||||
uuid := make([]byte, 16)
|
||||
n, err := rand.Read(uuid)
|
||||
if n != len(uuid) || err != nil {
|
||||
return strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
}
|
||||
// TODO: verify the two lines implement RFC 4122 correctly
|
||||
uuid[8] = 0x80 // variant bits see page 5
|
||||
uuid[4] = 0x40 // version 4 Pseudo Random, see page 7
|
||||
|
||||
return hex.EncodeToString(uuid)
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ func TestActionTimingStoreRestore(t *testing.T) {
|
||||
BillingUnit: 1.0,
|
||||
}
|
||||
at := &ActionTiming{
|
||||
Id: "some uuid",
|
||||
Tag: "test",
|
||||
UserBalanceIds: []string{"one", "two", "three"},
|
||||
Timing: i,
|
||||
@@ -49,7 +50,7 @@ func TestActionTimingStoreRestore(t *testing.T) {
|
||||
ActionsId: "Commando",
|
||||
}
|
||||
r := at.store()
|
||||
if string(r) != "test|one,two,three|1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;1|10|Commando" {
|
||||
if string(r) != "some uuid|test|one,two,three|1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;1|10|Commando" {
|
||||
t.Errorf("Error serializing action timing: %v", string(r))
|
||||
}
|
||||
o := &ActionTiming{}
|
||||
@@ -630,3 +631,30 @@ func TestActionResetCounterCREDIT(t *testing.T) {
|
||||
t.Error("Reset counters action failed!", ub.UnitCounters)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUUID(t *testing.T) {
|
||||
uuid := GenUUID()
|
||||
if len(uuid) == 0 {
|
||||
t.Fatalf("GenUUID error %s", uuid)
|
||||
}
|
||||
t.Logf("uuid[%s]\n", uuid)
|
||||
}
|
||||
|
||||
/********************************** Benchmarks ********************************/
|
||||
|
||||
func BenchmarkUUID(b *testing.B) {
|
||||
m := make(map[string]int, 1000)
|
||||
for i := 0; i < b.N; i++ {
|
||||
uuid := GenUUID()
|
||||
if len(uuid) == 0 {
|
||||
b.Fatalf("GenUUID error %s", uuid)
|
||||
}
|
||||
b.StopTimer()
|
||||
c := m[uuid]
|
||||
if c > 0 {
|
||||
b.Fatalf("duplicate uuid[%s] count %d", uuid, c)
|
||||
}
|
||||
m[uuid] = c + 1
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,20 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/syslog"
|
||||
"math"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
logger, err = syslog.NewLogger(syslog.LOG_ALERT, log.LstdFlags)
|
||||
if err != nil {
|
||||
logger = log.New(os.Stderr, "", log.LstdFlags)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// the minimum length for a destination prefix to be matched.
|
||||
MinPrefixLength = 2
|
||||
@@ -33,6 +43,11 @@ const (
|
||||
FallbackDestination = "fallback" // the string to be used to mark the fallback destination
|
||||
)
|
||||
|
||||
var (
|
||||
storageGetter StorageGetter
|
||||
logger *log.Logger
|
||||
)
|
||||
|
||||
/*
|
||||
Utility function for rounding a float to a certain number of decimals (not present in math).
|
||||
*/
|
||||
@@ -270,6 +285,7 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) {
|
||||
Cost: cost,
|
||||
ConnectFee: connectionFee,
|
||||
Timespans: timespans}
|
||||
logger.Printf("Get Cost: %v => %v", cd, cc)
|
||||
return cc, err
|
||||
}
|
||||
|
||||
@@ -309,7 +325,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
|
||||
}
|
||||
cost += ts.getCost(cd)
|
||||
}
|
||||
//log.Print(availableCredit, availableSeconds, cost)
|
||||
//logger.Print(availableCredit, availableSeconds, cost)
|
||||
if cost < availableCredit {
|
||||
return maxSessionSeconds, nil
|
||||
} else { //decrease the period by 10% and try again
|
||||
@@ -324,7 +340,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
|
||||
func (cd *CallDescriptor) Debit() (cc *CallCost, err error) {
|
||||
cc, err = cd.GetCost()
|
||||
if err != nil {
|
||||
log.Printf("error getting cost %v", err)
|
||||
logger.Printf("error getting cost %v", err)
|
||||
}
|
||||
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
|
||||
defer storageGetter.SetUserBalance(userBalance)
|
||||
|
||||
@@ -41,10 +41,6 @@ const (
|
||||
ABSOLUTE = "ABSOLUTE"
|
||||
)
|
||||
|
||||
var (
|
||||
storageGetter StorageGetter
|
||||
)
|
||||
|
||||
/*
|
||||
Structure containing information about user's credit (minutes, cents, sms...).'
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user