Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/issue 655 clear all old feed data #910

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Lib/tablejs/custom-table-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,30 @@ function list_format_updated(time) {
return "<span style='color:"+color+";'>"+updated+"</span>";
}

// Calculate relative time
function relative_time(time) {
time = time * 1000;
var servertime = (new Date()).getTime() - table.timeServerLocalOffset;
var update = (new Date(time)).getTime();

var secs = (servertime-update)/1000;
var mins = secs/60;
var hour = secs/3600;
var day = hour/24;
var year = day/365;

var relative_time = secs.toFixed(0) + "s";
if (update == 0) relative_time = "n/a";
else if (secs< 0) relative_time = secs.toFixed(0) + "s"; // update time ahead of server date is signal of slow network
else if (secs.toFixed(0) < 10) relative_time = "a few seconds";
else if (day>365) relative_time = year.toFixed(2)+" years";
else if (day>2) relative_time = day.toFixed(1)+" days";
else if (hour>2) relative_time = hour.toFixed(0)+" hrs";
else if (secs>180) relative_time = mins.toFixed(0)+" mins";

return relative_time
}

// Format value dynamically
function list_format_value(value) {
if (value == null) return 'NULL';
Expand Down
34 changes: 32 additions & 2 deletions Lib/tablejs/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ var table = {

'draw_row': function(t,row,child_row) {
var html = "<tr uid='"+child_row+"_"+row+"'>";
for (field in t.fields) html += "<td row='"+row+"' child_row='"+child_row+"' field='"+field+"' >"+this.fieldtypes[t.fields[field].type].draw(t,row,child_row,field)+"</td>";
for (field in t.fields) {
html += "<td row='"+row+"' child_row='"+child_row+"' field='"+field+"' >"+this.fieldtypes[t.fields[field].type].draw(t,row,child_row,field)+"</td>";
}
html += "</tr>";
return html;
},
Expand Down Expand Up @@ -230,6 +232,28 @@ var table = {
}
$(table.element).trigger("onDeleteExpand",[$(this).attr('uid'),$(this).attr('row'), $(this).attr('child_row')]); // If your code has an expand table use this instead of onDelete
});
// Event: clear all feed data
$(table.element).on('click', 'a[type=clear]', function() {
var child_row = $(this).attr('child_row');
if (child_row == "root") { t=table; }
else { t=table.expand[child_row]; }
if (table.cleardata) table.remove($(this).attr('row'), $(this).attr('child_row') );
if (child_row == "root") {
$(table.element).trigger("onClear",[$(this).attr('uid'),$(this).attr('row'), $(this).attr('child_row')]); // Only called for root table (to keep compatibility)
}
$(table.element).trigger("onClearExpand",[$(this).attr('uid'),$(this).attr('row'), $(this).attr('child_row')]); // If your code has an expand table use this instead of onDelete
});
// Event: trim feed data to a start_time
$(table.element).on('click', 'a[type=trim]', function() {
var child_row = $(this).attr('child_row');
if (child_row == "root") { t=table; }
else { t=table.expand[child_row]; }
if (table.cleardata) table.remove($(this).attr('row'), $(this).attr('child_row') );
if (child_row == "root") {
$(table.element).trigger("onTrim",[$(this).attr('uid'),$(this).attr('row'), $(this).attr('child_row')]); // Only called for root table (to keep compatibility)
}
$(table.element).trigger("onTrimExpand",[$(this).attr('uid'),$(this).attr('row'), $(this).attr('child_row')]); // If your code has an expand table use this instead of onDelete
});

// Event: inline edit
$(table.element).on('click', 'a[type=edit]', function() {
Expand Down Expand Up @@ -317,7 +341,6 @@ var table = {
'fixed': {
'draw': function (t,row,child_row,field) { return t.data[row][field] }
},

'text': {
'draw': function (t,row,child_row,field) {
value = t.data[row][field];
Expand Down Expand Up @@ -406,6 +429,13 @@ var table = {
'draw': function (t,row,child_row,field) { return "<a type='expand' row='"+row+"' child_row='"+child_row+"' uid='"+t.data[row][t.expandByField]+"' mode='" + (t.expand[t.data[row][t.expandByField]] == undefined || !t.expand[t.data[row][t.expandByField]].expanded ? "expand":"close") + "'><i class='" + (t.expand[t.data[row][t.expandByField]] == undefined || !t.expand[t.data[row][t.expandByField]].expanded ? "icon-chevron-down":"icon-chevron-up") + "' style='cursor:pointer'></i></a>"; },
},

'relative_days': {
'draw': function (t,row,child_row,field) {
let value = t.data[row][field]
return value == 0 ? 0 : Math.round(((new Date().getTime()/1000) - value) / 60 / 60 / 24)
}
},

'blank': {
'draw': function (t,row,child_row,field) { return ""; }
}
Expand Down
131 changes: 117 additions & 14 deletions Modules/feed/Views/feedlist_view.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@
#table th[fieldg="size"], th[fieldg="time"] { font-weight:normal; }
#table th[fieldg="processList"] { font-weight:normal; }

input[type="range"]{
padding: .35em .5em;
border: 1px solid #ddd;
border-right-width: 1px;
}
.input-append > input[type="range"]{
border-right-width: 0;
}
.modal-wide{
width:650px;
margin-left:-325px;
}
</style>

<div>
Expand All @@ -53,20 +65,48 @@
<div id="feedDeleteModal" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="feedDeleteModalLabel" aria-hidden="true" data-backdrop="static">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="feedDeleteModalLabel"><?php echo _('Delete feed'); ?></h3>
<h3 id="feedDeleteModalLabel"><?php echo _('Delete feed'); ?>
<span id="feedDelete-message" class="label label-important" data-default="<?php echo _('Deleting a feed is permanent.'); ?>"><?php echo _('Deleting a feed is permanent.'); ?></span>
</h3>
</div>
<div class="modal-body">
<p><?php echo _('Deleting a feed is permanent.'); ?></p>
<br>
<div id="deleteFeedText"><?php echo _('If you have Input Processlist processors that use this feed, after deleting it, review that process lists or they will be in error, freezing other Inputs. Also make sure no Dashboards use the deleted feed.'); ?></div>
<div id="deleteVirtualFeedText"><?php echo _('This is a Virtual Feed, after deleting it, make sure no Dashboard continue to use the deleted feed.'); ?></div>
<br><br>
<p><?php echo _('Are you sure you want to delete?'); ?></p>
<div id="feedDelete-loader" class="ajax-loader" style="display:none;"></div>
<div class="clearfix">
<div class="span6">
<div style="min-height:10.6em; position:relative" class="well well-small">
<h4 class="text-info">Clear:</h4>
<p>Empty feed of all data</p>
<button id="feedClear-confirm" class="btn btn-info" style="position:absolute;bottom:.8em" onclick="return confirm('Are you sure you want to delete all the feed\'s data?')"><?php echo _('Clear Data'); ?>&hellip;</button>
</div>
</div>

<div class="span6">
<div class="well well-small">
<h4 class="text-info">Trim:</h4>
<p>Empty feed data up to:</p>
<div id="trim_start_time_container" class="control-group">
<div class="controls">
<div id="feed_trim_datetimepicker" class="input-append date">
<input id="trim_start_time" class="input-medium" data-format="dd/MM/yyyy hh:mm:ss" type="text" placeholder="dd/mm/yyyy hh:mm:ss">
<span class="add-on"> <i data-time-icon="icon-time" data-date-icon="icon-calendar" class="icon-calendar"></i></span>
</div>
</div>
</div>
<button id="feedTrim-confirm" class="btn btn-info"><?php echo _('Trim Data'); ?>&hellip;</button>
</div>
</div>
</div>

<div class="well well-small">
<h4 class="text-info">Delete:</h4>
<p id="deleteFeedText"><?php echo _('If you have Input Processlist processors that use this feed, after deleting it, review that process lists or they will be in error, freezing other Inputs. Also make sure no Dashboards use the deleted feed.'); ?></p>
<p id="deleteVirtualFeedText"><?php echo _('This is a Virtual Feed, after deleting it, make sure no Dashboard continue to use the deleted feed.'); ?></p>
<button id="feedDelete-confirm" class="btn btn-danger" onclick="return confirm('<?php echo _('Are you sure you want to delete?'); ?>')"><?php echo _('Delete feed permanently'); ?></button>
</div>
</div>

<div class="modal-footer">
<div id="feedDelete-loader" class="ajax-loader" style="display:none;"></div>
<button class="btn" data-dismiss="modal" aria-hidden="true"><?php echo _('Cancel'); ?></button>
<button id="feedDelete-confirm" class="btn btn-primary"><?php echo _('Delete permanently'); ?></button>
</div>
</div>

Expand Down Expand Up @@ -216,6 +256,7 @@
pulses: "pulses",
dB: "dB"
}},
'start_time':{title:"<?php echo _('Days'); ?>",type:'relative_days'},
// Actions
'edit-action':{'title':'', 'type':"edit"},
'delete-action':{'title':'', 'type':"delete"},
Expand Down Expand Up @@ -291,20 +332,71 @@ function updaterStart(func, interval){
$('#feedDeleteModal').attr('the_id',id);
$('#feedDeleteModal').attr('the_row',row);
});

function updateFeedDeleteModalMessage(message){
var $msg = $('#feedDelete-message')
$msg.text(message).removeClass('label-important').addClass('label-info')
setTimeout(function(){
$msg.stop().fadeOut(function(){
$msg.text($msg.data('default')).removeClass('label-info').addClass('label-important').fadeIn()
})
}, 2800)
}
$("#feedDelete-confirm").click(function(){
var id = $('#feedDeleteModal').attr('the_id');
var row = $('#feedDeleteModal').attr('the_row');
feed.remove(id);
table.remove(row);
update();
updateFeedDeleteModalMessage("<?php echo _('Feed deleted') ?>")
setTimeout(function(){
update();
updaterStart(update, 5000);
$('#feedDeleteModal').modal('hide')
}, 3000)

});

$('#feedDeleteModal').modal('hide');
$("#feedClear-confirm").click(function(){
$modal = $('#feedDeleteModal')
var id = $modal.attr('the_id');
$("#feedDelete-loader").fadeIn();
let response = feed.clear(id);
$("#feedDelete-loader").stop().fadeOut();
updateFeedDeleteModalMessage(response.message)
update();
updaterStart(update, 5000);
});

$("#feedTrim-confirm").click(function(){
$modal = $('#feedDeleteModal')
let id = $modal.attr('the_id');
let $input = $modal.find("#trim_start_time");
let input_date_string = $input.val();
// dont submit if nothing selected
// convert uk dd/mm/yyyy h:m:s to RFC2822 date
let start_date = new Date(input_date_string.replace( /(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})/, "$3-$2-$1T$4:$5:$6"))
let isValidDate = !isNaN(start_date.getTime()) && input_date_string != "";
// exit if supplied date not valid
if (!isValidDate) {
$('#trim_start_time_container').addClass('error')
$input.focus();
return false;
}else{
if(confirm('Are you sure you want to trim the feed\'s data?')==true) {
$('#trim_start_time_container').removeClass('error')
// set to seconds from milliseconds
let start_time = start_date.getTime()/1000;
$("#feedDelete-loader").fadeIn();
let response = feed.trim(id, start_time);
$("#feedDelete-loader").stop().fadeOut();
updateFeedDeleteModalMessage(response.message)
update();
updaterStart(update, 5000);
}
}
});

$("#refreshfeedsize").click(function(){
$.ajax({ url: path+"feed/updatesize.json", async: true, success: function(data){ update(); alert("<?php echo _('Total size of used space for feeds:'); ?>" + list_format_size(data)); } });
$.ajax({ url: path+"feed/updatesize.json", async: true, sucinput_date_stringcess: function(data){ update(); alert("<?php echo _('Total size of used space for feeds:'); ?>" + list_format_size(data)); } });
});

//show the input field when "custom" selected in units
Expand Down Expand Up @@ -361,6 +453,8 @@ function updaterStart(func, interval){
language: 'en-EN',
useCurrent: false //Important! See issue #1075
});
$('#feed_trim_datetimepicker').datetimepicker({language: 'en-EN'});


$('#datetimepicker1').on("changeDate", function (e) {
$('#datetimepicker2').data("datetimepicker").setStartDate(e.date);
Expand Down Expand Up @@ -495,5 +589,14 @@ function parse_timepicker_time(timestr){
$("#save-processlist").click(function (){
var result = feed.set_process(processlist_ui.contextid,processlist_ui.encode(processlist_ui.contextprocesslist));
if (result.success) { processlist_ui.saved(table); } else { alert('<?php echo _('ERROR: Could not save processlist.'); ?> '+result.message); }
});
});

/**
* triggered on input change
*/
function showNewStartTime(event){
let input = event.target
let new_start_time = input.value
document.getElementById('feed_shift_slider_value').innerText = new_start_time
}
</script>
11 changes: 10 additions & 1 deletion Modules/feed/engine/CassandraEngine.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<?php
// engine_methods interface in shared_helper.php
include_once dirname(__FILE__) . '/shared_helper.php';

/**
* CassandraEngine
*
* @SuppressWarnings(PHPMD.TooManyMethods)
*
*/
class CassandraEngine
class CassandraEngine implements engine_methods
{
const ONE_TABLE_PER_FEED = false;
protected $cluster;
Expand Down Expand Up @@ -224,6 +226,13 @@ public function csv_export($feedid,$start,$end,$outinterval,$usertimezone)
// TODO implement
}

public function trim($feedid,$start_time){
return array('success'=>false,'message'=>'"Trim" not available for this storage engine');
}
public function clear($feedid){
return array('success'=>false,'message'=>'"Clear" not available for this storage engine');
}

// #### /\ Above are required methods

// #### \/ Below engine specific public methods
Expand Down
10 changes: 9 additions & 1 deletion Modules/feed/engine/Histogram.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
// engine_methods interface in shared_helper.php
include_once dirname(__FILE__) . '/shared_helper.php';

class Histogram
class Histogram implements engine_methods
{
private $mysqli;

Expand Down Expand Up @@ -145,4 +147,10 @@ public function csv_export($feedid,$start,$end,$outinterval,$usertimezone)
{

}
public function trim($feedid,$start_time){
return array('success'=>false,'message'=>'"Trim" not available for this storage engine');
}
public function clear($feedid){
return array('success'=>false,'message'=>'"Clear" not available for this storage engine');
}
}
35 changes: 33 additions & 2 deletions Modules/feed/engine/MysqlTimeSeries.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
include_once dirname(__FILE__) . '/shared_helper.php';

class MysqlTimeSeries
class MysqlTimeSeries implements engine_methods
{
protected $mysqli;
protected $log;
Expand Down Expand Up @@ -698,6 +699,36 @@ public function csv_export($feedid,$start,$end,$outinterval,$usertimezone)
exit;
}


public function clear($feedid){
$feedid = filter_var ( $feedid, FILTER_SANITIZE_NUMBER_INT);
$table = "feed_$feedid";
$sql = "TRUNCATE TABLE $table";
if(!$this->mysqli->query($sql)) {
return array('success'=>false,'message'=>"0 rows deleted");
} else {
return array('success'=>true,'message'=>"All database rows deleted");
}
}

public function trim($feedid, $start_time){
$feedid = filter_var ( $feedid, FILTER_SANITIZE_NUMBER_INT);
$start_time = filter_var ( $start_time, FILTER_SANITIZE_NUMBER_INT);
$table = "feed_$feedid";
$stmt = $this->mysqli->prepare("DELETE FROM $table WHERE time < ?");
if(!$stmt) return array('success'=>false,'message'=>"Error accessing database");
if(!$stmt->bind_param("i", $start_time)) return array('success'=>false,'message'=>"Error passing parameters to database");
if(!$stmt->execute()) return array('success'=>false,'message'=>"Error executing commands on database");
$affected_rows = $stmt->affected_rows;
if($affected_rows>0){
return array('success'=>true,'message'=>"$affected_rows rows deleted");
} else {
return array('success'=>false,'message'=>"0 rows deleted");
}
}



// #### /\ Above are required methods


Expand Down Expand Up @@ -780,5 +811,5 @@ private function writebuffer_update_time($feedid,$time,$newvalue) {
}
return false;
}

}
Loading