Hi,
too much time passed since this post, but thanks to Stipe who pointed me
to this post.
Attached is a patch that implements simple bandwidth meter with
heuristic and needed changes to bearerbox status.
Bearerbox status show now 3 speeds: 1 minute sample, 5 minute sample,
and over livetime.
Example:
SMS: inbound (0.00,0.00,0.00) msg/sec, outbound (0.00,0.00,0.00) msg/sec
Comments please...
Thanks,
Alex
Alexander Malysh schrieb:
Hi,
I already implemented this in my tree, just give me some time to extract
this...
Rafael Alfaro wrote:
Hello Alex,
First of all, thanks for your time,
Could you explain me a little bit about: "Simple bandwidth meter should do
it"? How is the best way to implement this?
Thanks in advance.
Rafael Alfaro.
On Tue, Mar 25, 2008 at 4:06 AM, Alexander Malysh <[EMAIL PROTECTED]>
wrote:
Hi Rafael,
-1 for this patch. You don't need yet another thread to do this. Simple
bandwidth meter should do it...
Rafael Alfaro wrote:
> Hello Everybody,
>
> I did this patch with the following purpose:
> Provide the bearerbox status web page with an online incoming and
> outgoing sms rate display (msg/sec).
>
> For example, if you take a look to the current bearerbox status web
> page, you will see that the sms rate is the average since the
> bearerbox is online, because the current code is:
>
> (float) counter_value(incoming_sms_counter)/t,
> (float) counter_value(outgoing_sms_counter)/t,
>
> So, I added a new feature to the core group cfg: "sms-rate-refresh".
> This will launch a thread that will be sampling the
> "counter_value(incoming_sms_counter)" and
> "counter_value(outgoing_sms_counter)" every "sms_rate_refresh"
> seconds, and with this information we can calculate the current sms
> rate (msg/sec).
>
> If the "sms-rate-refresh" feature is not used at the configuration
> file, by default, the average since bearerbox is online will be
> displayed (like right now is coded).
>
> Best Regards,
--
Thanks,
Alex
Index: gw/load.c
===================================================================
RCS file: gw/load.c
diff -N gw/load.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gw/load.c 12 Sep 2008 12:32:28 -0000
@@ -0,0 +1,215 @@
+/* ====================================================================
+ * The Kannel Software License, Version 1.0
+ *
+ * Copyright (c) 2001-2008 Kannel Group
+ * Copyright (c) 1998-2001 WapIT Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Kannel Group (http://www.kannel.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Kannel" and "Kannel Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please
+ * contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Kannel",
+ * nor may "Kannel" appear in their name, without prior written
+ * permission of the Kannel Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Kannel Group. For more information on
+ * the Kannel Group, please see <http://www.kannel.org/>.
+ *
+ * Portions of this software are based upon software originally written at
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.
+ */
+
+/**
+ * load.c
+ *
+ * Alexander Malysh <amalysh at kannel.org> 2008 for project Kannel
+ */
+
+#include "gwlib/gwlib.h"
+#include "load.h"
+
+
+struct load_entry {
+ float prev;
+ float curr;
+ time_t last;
+ int interval;
+ int dirty;
+};
+
+
+struct load {
+ struct load_entry **entries;
+ int len;
+ int heuristic;
+ RWLock *lock;
+};
+
+
+Load* load_create_real(int heuristic)
+{
+ struct load *load;
+
+ load = gw_malloc(sizeof(*load));
+ load->len = 0;
+ load->entries = NULL;
+ load->heuristic = heuristic;
+ load->lock = gw_rwlock_create();
+
+ return load;
+}
+
+
+int load_add_interval(Load *load, int interval)
+{
+ int i;
+ struct load_entry *entry;
+
+ if (load == NULL)
+ return -1;
+
+ gw_rwlock_wrlock(load->lock);
+
+ /* first look if we have equal interval added already */
+ for (i = 0; i < load->len; i++) {
+ if (load->entries[i]->interval == interval) {
+ gw_rwlock_unlock(load->lock);
+ return -1;
+ }
+ }
+ /* so no equal interval there, add new one */
+ entry = gw_malloc(sizeof(struct load_entry));
+ entry->prev = entry->curr = 0.0;
+ entry->interval = interval;
+ entry->dirty = 1;
+ time(&entry->last);
+
+ load->entries = gw_realloc(load->entries, sizeof(struct load*) *
(load->len + 1));
+ load->entries[load->len] = entry;
+ load->len++;
+
+ gw_rwlock_unlock(load->lock);
+
+ return 0;
+}
+
+
+void load_destroy(Load *load)
+{
+ int i;
+
+ if (load == NULL)
+ return;
+
+ for (i = 0; i < load->len; i++) {
+ gw_free(load->entries[i]);
+ }
+ gw_free(load->entries);
+ gw_rwlock_destroy(load->lock);
+ gw_free(load);
+}
+
+
+void load_increase_with(Load *load, unsigned long value)
+{
+ time_t now;
+ int i;
+
+ if (load == NULL)
+ return;
+ gw_rwlock_wrlock(load->lock);
+ time(&now);
+ for (i = 0; i < load->len; i++) {
+ struct load_entry *entry = load->entries[i];
+ /* check for special case, load over whole live time */
+ if (entry->interval != -1 && now >= entry->last + entry->interval) {
+ /* rotate */
+ entry->curr /= entry->interval;
+ if (entry->prev > 0)
+ entry->prev = (2*entry->curr + entry->prev)/3;
+ else
+ entry->prev = entry->curr;
+ entry->last = now;
+ entry->curr = 0.0;
+ entry->dirty = 0;
+ }
+ entry->curr += value;
+ }
+ gw_rwlock_unlock(load->lock);
+}
+
+
+float load_get(Load *load, int pos)
+{
+ float ret;
+ time_t now;
+ struct load_entry *entry;
+
+ if (load == NULL || pos >= load->len) {
+ return -1.0;
+ }
+
+ /* first maybe rotate load */
+ load_increase_with(load, 0);
+
+ time(&now);
+ gw_rwlock_rdlock(load->lock);
+ entry = load->entries[pos];
+ if (load->heuristic && !entry->dirty) {
+ ret = entry->prev;
+ } else {
+ time_t diff = (now - entry->last);
+ if (diff == 0) diff = 1;
+ ret = entry->curr/diff;
+ }
+ gw_rwlock_unlock(load->lock);
+
+ return ret;
+}
+
+
+int load_len(Load *load)
+{
+ int ret;
+ if (load == NULL)
+ return 0;
+ gw_rwlock_rdlock(load->lock);
+ ret = load->len;
+ gw_rwlock_unlock(load->lock);
+ return ret;
+}
Index: gw/load.h
===================================================================
RCS file: gw/load.h
diff -N gw/load.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gw/load.h 12 Sep 2008 12:32:28 -0000
@@ -0,0 +1,112 @@
+/* ====================================================================
+ * The Kannel Software License, Version 1.0
+ *
+ * Copyright (c) 2001-2008 Kannel Group
+ * Copyright (c) 1998-2001 WapIT Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Kannel Group (http://www.kannel.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Kannel" and "Kannel Group" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please
+ * contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Kannel",
+ * nor may "Kannel" appear in their name, without prior written
+ * permission of the Kannel Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Kannel Group. For more information on
+ * the Kannel Group, please see <http://www.kannel.org/>.
+ *
+ * Portions of this software are based upon software originally written at
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.
+ */
+
+/**
+ * load.h
+ *
+ * Alexander Malysh <amalysh at kannel.org> 2008 for project Kannel
+ */
+
+#ifndef LOAD_H
+#define LOAD_H 1
+
+#include <time.h>
+
+/**
+ * Anonymos Load typedef.
+ */
+typedef struct load Load;
+
+/**
+ * Create new Load object.
+ * @heuristic - 0 disable heuristic (means get always current load); 1 enable
+ */
+Load* load_create_real(int heuristic);
+#define load_create() load_create_real(1)
+
+/**
+ * Add load measure interval.
+ * @load - load object
+ * @interval - measure interval in seconds
+ * @return -1 if error occurs (e.g. interval already exists); 0 if all was fine
+ */
+int load_add_interval(Load *load, int interval);
+
+/**
+ * Increase load values with @value.
+ * @load - load object
+ * @valu - how much to increase
+ */
+void load_increase_with(Load *load, unsigned long value);
+#define load_increase(load) load_increase_with(load, 1)
+
+/**
+ * Destroy load object.
+ * @load - load object
+ */
+void load_destroy(Load *load);
+
+/**
+ * Get measured load value at position @pos.
+ */
+float load_get(Load *load, int pos);
+
+/**
+ * Get length of intervals.
+ */
+int load_len(Load *load);
+
+#endif
Index: gw/bb_smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_smscconn.c,v
retrieving revision 1.96
diff -a -u -p -r1.96 bb_smscconn.c
--- gw/bb_smscconn.c 9 Jan 2008 20:06:56 -0000 1.96
+++ gw/bb_smscconn.c 12 Sep 2008 12:32:28 -0000
@@ -87,6 +87,7 @@
#include "numhash.h"
#include "smscconn.h"
#include "dlr.h"
+#include "load.h"
#include "bb_smscconn_cb.h" /* callback functions for connections */
#include "smscconn_p.h" /* to access counters */
@@ -100,6 +101,9 @@ extern List *outgoing_sms;
extern Counter *incoming_sms_counter;
extern Counter *outgoing_sms_counter;
+extern Load *outgoing_sms_load;
+extern Load *incoming_sms_load;
+
extern List *flow_threads;
extern List *suspended;
extern List *isolated;
@@ -251,6 +255,7 @@ void bb_smscconn_sent(SMSCConn *conn, Ms
}
counter_increase(outgoing_sms_counter);
+ load_increase(outgoing_sms_load);
if (conn) counter_increase(conn->sent);
/* write ACK to store file */
@@ -424,6 +429,7 @@ long bb_smscconn_receive(SMSCConn *conn,
switch(ret) {
case concat_pending:
counter_increase(incoming_sms_counter); /* ?? */
+ load_increase(incoming_sms_load);
if (conn != NULL)
counter_increase(conn->received);
msg_destroy(sms);
@@ -476,6 +482,7 @@ long bb_smscconn_receive(SMSCConn *conn,
bb_alog_sms(conn, sms, "Receive DLR");
counter_increase(incoming_sms_counter);
+ load_increase(incoming_sms_load);
if (conn != NULL) counter_increase(conn->received);
msg_destroy(sms);
Index: gw/bearerbox.c
===================================================================
RCS file: /home/cvs/gateway/gw/bearerbox.c,v
retrieving revision 1.167
diff -a -u -p -r1.167 bearerbox.c
--- gw/bearerbox.c 24 Apr 2008 14:44:59 -0000 1.167
+++ gw/bearerbox.c 12 Sep 2008 12:32:28 -0000
@@ -77,6 +77,7 @@
#include "bearerbox.h"
#include "shared.h"
#include "dlr.h"
+#include "load.h"
/* global variables; included to other modules as needed */
@@ -96,6 +97,10 @@ long max_incoming_sms_qlength;
long max_outgoing_sms_qlength;
+Load *outgoing_sms_load;
+Load *incoming_sms_load;
+
+
/* this is not a list of items; instead it is used as
* indicator to note how many threads we have.
* ALL flow threads must exit before we may safely change
@@ -454,6 +459,17 @@ static Cfg *init_bearerbox(Cfg *cfg)
status_mutex = mutex_create();
+ outgoing_sms_load = load_create();
+ /* add 60,300,-1 entries */
+ load_add_interval(outgoing_sms_load, 60);
+ load_add_interval(outgoing_sms_load, 300);
+ load_add_interval(outgoing_sms_load, -1);
+ incoming_sms_load = load_create();
+ /* add 60,300,-1 entries */
+ load_add_interval(incoming_sms_load, 60);
+ load_add_interval(incoming_sms_load, 300);
+ load_add_interval(incoming_sms_load, -1);
+
setup_signal_handlers();
/* http-admin is REQUIRED */
@@ -544,6 +560,9 @@ static void empty_msg_lists(void)
counter_destroy(incoming_sms_counter);
counter_destroy(outgoing_sms_counter);
+
+ load_destroy(incoming_sms_load);
+ load_destroy(outgoing_sms_load);
}
@@ -816,7 +835,6 @@ Octstr *bb_print_status(int status_type)
{
char *s, *lb;
char *frmt, *footer;
- char buf[1024];
Octstr *ret, *str, *version;
time_t t;
@@ -845,7 +863,7 @@ Octstr *bb_print_status(int status_type)
"(%ld queued)</p>\n\n"
" <p>SMS: received %ld (%ld queued), sent %ld "
"(%ld queued), store size %ld</p>\n"
- " <p>SMS: inbound %.2f msg/sec, outbound %.2f msg/sec</p>\n\n"
+ " <p>SMS: inbound (%.2f,%.2f,%.2f) msg/sec, outbound
(%.2f,%.2f,%.2f) msg/sec</p>\n\n"
" <p>DLR: %ld queued, using %s storage</p>\n\n";
footer = "<p>";
} else if (status_type == BBSTATUS_WML) {
@@ -856,8 +874,8 @@ Octstr *bb_print_status(int status_type)
" <p>SMS: received %ld (%ld queued)<br/>\n"
" SMS: sent %ld (%ld queued)<br/>\n"
" SMS: store size %ld<br/>\n"
- " SMS: inbound %.2f msg/sec<br/>\n"
- " SMS: outbound %.2f msg/sec</p>\n\n"
+ " SMS: inbound (%.2f,%.2f,%.2f) msg/sec<br/>\n"
+ " SMS: outbound (%.2f,%.2f,%.2f) msg/sec</p>\n\n"
" <p>DLR: %ld queued<br/>\n"
" DLR: using %s storage</p>\n\n";
footer = "<p>";
@@ -870,19 +888,19 @@ Octstr *bb_print_status(int status_type)
"\t<sms>\n\t\t<received><total>%ld</total><queued>%ld</queued>"
"</received>\n\t\t<sent><total>%ld</total><queued>%ld</queued>"
"</sent>\n\t\t<storesize>%ld</storesize>\n\t\t"
-
"<inbound>%.2f</inbound>\n\t\t<outbound>%.2f</outbound>\n\t</sms>\n"
+
"<inbound>%.2f,%.2f,%.2f</inbound>\n\t\t<outbound>%.2f,%.2f,%.2f</outbound>\n\t</sms>\n"
"\t<dlr>\n\t\t<queued>%ld</queued>\n\t\t<storage>%s</storage>\n\t</dlr>\n";
footer = "";
} else {
frmt = "%s\n\nStatus: %s, uptime %ldd %ldh %ldm %lds\n\n"
"WDP: received %ld (%ld queued), sent %ld (%ld queued)\n\n"
"SMS: received %ld (%ld queued), sent %ld (%ld queued), store
size %ld\n"
- "SMS: inbound %.2f msg/sec, outbound %.2f msg/sec\n\n"
+ "SMS: inbound (%.2f,%.2f,%.2f) msg/sec, outbound
(%.2f,%.2f,%.2f) msg/sec\n\n"
"DLR: %ld queued, using %s storage\n\n";
footer = "";
}
- sprintf(buf, frmt,
+ ret = octstr_format(frmt,
octstr_get_cstr(version),
s, t/3600/24, t/3600%24, t/60%60, t%60,
counter_value(incoming_wdp_counter),
@@ -891,12 +909,11 @@ Octstr *bb_print_status(int status_type)
counter_value(incoming_sms_counter), gwlist_len(incoming_sms),
counter_value(outgoing_sms_counter), gwlist_len(outgoing_sms),
store_messages(),
- (float) counter_value(incoming_sms_counter)/t,
- (float) counter_value(outgoing_sms_counter)/t,
+ load_get(incoming_sms_load,0), load_get(incoming_sms_load,1),
load_get(incoming_sms_load,2),
+ load_get(outgoing_sms_load,0), load_get(outgoing_sms_load,1),
load_get(outgoing_sms_load,2),
dlr_messages(), dlr_type());
octstr_destroy(version);
- ret = octstr_create(buf);
append_status(ret, str, boxc_status, status_type);
append_status(ret, str, smsc2_status, status_type);