I'm using Zabbix 3.2; I've configured mail alert Action for all triggers. My question is,
Say trigger(A) alerts (Problem event) on escalation and returns to normal (Ok event alert) after few mintues. I need to stop the alert if same 'A' Trigger happened in next few mintues. How can it be possible?
I've tried with this documentation;
https://www.zabbix.com/documentation/3.2/manual/config/notifications/action/escalations
The question seems to be about preventing trigger flapping. In general, three methods are suggested:
use trigger functions - for example, instead of last() use avg(15m) - then the alerting will happen only after the average value for 15 minutes has exceeded the threshold. Other useful trigger functions might be min() and max()
use hysteresis - this makes trigger fire at one threshold but resolve on another. Before Zabbix 3.2 that was done in the trigger expression; since Zabbix 3.2 there is a separate "recovery" field
use action escalations that do nothing at first, and only send an alert when the problem has been there for some period of time - for example, sending out the alert on the second or third step
All three methods achieve a similar outcome, but the key differences are:
the first method - trigger functions - makes the trigger fire later, but reduces the number of events (the times trigger fires)
the second method - hysteresis - makes the trigger fire at the same time as the "flappy" trigger, but delays the recovery event. It also reduces the number of events (the times trigger fires)
the third method - delayed escalation steps - does not affect the trigger at all, it can keep on flapping. It will only alert if the problem is there for a longer time, though.
Hysteresis will usually alert when a trigger would have flapped; delayed escalation steps will ignore short-lived problems.
Complexity-wise, I'd usually go with the first method - it is the easiest to configure, the hardest to misconfigure and the easiest to understand. I'd go with one of the two other methods if I specifically needed the way they make events/alerts behave - those methods have a bit higher potential to be misconfigured or misunderstood.
Note that the item key reference in the comment is wrong - host is separated from key with colon, full key name is missing and the parameter is wrong. See the agent key page in the manual for correct key syntax.
Related
Is it possible to materialize the edits made as part of a scenario into a dataset in foundry?
I want for each scenario to write out the primary keys of the objects edited as part of the scenario.
The motivation is that I need to run multiple processes to compute metrics as part of the changed values for each scenario, at a scale and runtime that is not possible to do with Functions.
Edit with details:
The thing is that I am not doing actual edits to the objects for the object type, I don't want to apply it.
I tested out the "Action Log" and it does not seem like this picks up "uncommitted" actions, meaning actions that is just run as part of a scenario. Also, it does not seem to be a link to the scenario it was a part of, even if the changes were committed.
The workflow is that I have Object Type A, and I define multiple scenarios S on a subset of the objects in A.
Each scenario might make something like 50k edits to a subset of A, through multiple Actions backed by a Function.
I save some of the scenarios. Now I am able to load these scenarios and "apply" them on A again in Workshop.
However I need to be able to get all the primary keys, and the edited values of A materialized into a dataset (for each scenario), as I need to run some transformation logic to compute a metric for the change as part of each scenario (at a scale and execution time not possible in Functions).
The Action Log did not seem to help a lot for this. How do I get the "edits" as part of a saved scenario into a dataset?
The only logic you can run BEFORE applying will be functions.
Not sure about your exact logic but Function's Custom Aggregations can be very powerful: Docs here
this might not directly let you calculate the Diff but you could use the scenario compare widgets in workshop to compare your aggregation between multiple Scenarios
e.g. you have a function that sums(total profit)
Your Workshop could show:
Current Data:
$10k
Scenario A:
$5k
Scneario B:
$13k
instead of like:
Scenario A:
-$5k
Scenario B:
+$3k
Afaik there's no first class way of doing this (yet).
"Applying" a scenario basically means you're submitting the actions queued on the scenario to the ontology. So neither the actions nor the ontology are aware that they came from a scenario.
What I've been doing to achieve what you're working on is using the "Action Log". It's still in Beta so you might need to ask for it to be enabled. It will allow you on each action to define a "log" object to be created that can track the pks of your edited objects per Action.
How I do the action log is:
My Action log has the "timestamp" of the action when they were run.
My Scenarios have the "timestamp" of when it was applied.
Since "Applying a Scenario" means -> actually running all actions on Ontology (underlying data) this gets me this structure if I sort everything by timestamp:
Action 1
Action 2
Scenario A applied
Action 3
Action 4
Scenario B applied
this allows you to do a mapping later on of Action 1/2 must come from Scenario A and Action 3+4 come from Scenario B.
EDIT: Apparently you might be able to use the Scenario RID directly in the Action Logs too (which is a recent addition I haven't adopted yet)
This won't allow you tho to compute (in transforms...) anything BEFORE applying a scenario tho
I am not sure if I have put right words in title to explain. But here it is.
Application: Coldfusion/MySQL
Problem exceptionally occurred during bad internet reception which triggered double requests before the first one completed. In result two database entries were made.
Application is only handling double request with a SELECT query first to check if there is already a same record in db. In that case old record is updated with an UPDATE statement. Otherwise an INSERT statement is used to insert a new record. The SELECT/INSERT/UPDATE are enclosed within CFTRANSACTION.
<cftransction>
<cfquery></cfquery> //SELECT
<cfif SELECT.found>
<cfquery></cfquery> //UPDATE
<cfelse>
<cfquery></cfquery> //INSERT
</cfif>
</cftransaction>
In most cases when there is some delay in two requests, it works fine. To reproduce the problem,
I first tried initiating two simultaneous requests via browser and it didn't trouble in many tries.
To make two requests quick, I used two post statements right after one on the page (it's an AJAX app). It also worked as expected as second request was only updating the previously entered record.
What I could do to make those two requests even quicker, I reached out at the server itself (where both the ColdFusion and MySQL are running) and opened the browser. Now one browser request with two post statements started frequent double entries.
Above code might insert two entries when the REQUEST.2 SELECT runs before REQUEST.1 INSERT. What could be possible solution on the server end?
Handling on the client side with disabling subsequent requests before the first request completes. but want to secure it on the server.
So I used the solution porvided by #Leigh in comments to original question. Just answering to make it standout and what other things I had to do to actually use this solution.
Instead of the SELECT .. INSERT approach have you looked at db options such as REPLACE or INSERT ... ON DUPLICATE KEY UPDATE? – Leigh
While both the solutions seemed good to solve the problem but REPLACE was more attractive as it only required me to change "INSERT" keyword in the queries with "REPLACE"
With a quick overview from the docs, REPLACE exactly replaces and works like INSERT statement but performs the purpose only when a row is found with duplicate PRIMARY KEY or UNIQUE index.
1- As I required three columns to be unique in that sense which I was using in a WHERE clause with SELECT before inserting them. I had to add a UNIQUE index on those three columns before REPLACE could work to restrict duplicate rows.
2- If duplicate row found, REPLACE first deletes the old row and then inserts the new one. This process also could loose some values from other columns in the table. But in my application, these columns are updated on every REQUEST while the values for those are derived from other tables. So it was not problem for me as the data can be updated for the new row inserted.
The <cftransaction> will group together the select + insert/update queries but will not prevent a second+ request from executing, even from the same browser before the transaction is completely finished.
I have run into similar problems with the IE browser. The user could spam-click the submit and IE would submit for each time the submit button was clicked.
The most common solution that I've employed is to disable the submit button after it is clicked, or replace (hide it) it with a message that says something like "please wait, submitting form...". I've used JavaScript/jQuery for this task. It isn't 100% effective and does depend on what browser is being used and if JavaScript is enabled.
Another option is to use a named <cflock> to make sure that code can only be executed as a batch. This could cause a performance bottleneck if several people are using the form at the same time. So, I would plan to use a session variable as part of the named <cflock> name. That way the lock is unique to each user.
Below is a CF 11 example:
<cflock name="lckInsUpdt_#listFirst(session.sessionid, '.')#" timeout="300" throwontimeout="no" type="exclusive">
<cftransction>
<cfquery></cfquery> //SELECT
<cfif SELECT.found>
<cfquery></cfquery> //UPDATE
<cfelse>
<cfquery></cfquery> //INSERT
</cfif>
</cftransaction>
</cflock>
I have a project in Delphi 7 that uses a database in MySQL to store some configuration.
Whenever I change a config, a "Save" button is enabled. The OnClick procedure in this button calls TADOQuery.Edit, Select the fields with the SQL property, TADOQuery.Open and set the various FieldsByName. In the end, it TADOQuery.Post the configuration and Requery it.
This works well, only if at least one of these fields is actually changed.
If, for example, I check a checkBox (originally unchecked) and then unCheck it again, the Save button would go enabled, but the actual data in database doesn't change. In this case, when I call Post, an Exception is raised.
I saw this question that would solve my problem, checking if there ara any modification, but as soon as I set the first field, the Modified property of TADOQuery becomes true, invalidating this solution.
Another option would be to check, before setting the field, if it will actually change, setting an flag to, in the end, actually post it or not. But, there are hundreds of fields to do that, which will be pretty boring to do.
A third alternative I thought is to create a new field in database with a "Last Modified" datestamp, which forces to always have at least one modification, but I prefer to not mess with the existing database.
Is there any other way to know if a TADOQuery.Post will trigger an exception, because no data has really changed? How can I solve this problem? Or there's a simple workaround for it?
The ADOQuery variable is dynamically created in the Save button's routine (and free'd in the end).
It would be a nice approach to use CheckBrowseMode() instead of Post().
ADOQuery1.CheckBrowseMode
CheckBrowseMode():
Automatically posts or cancels data changes when the active record changes.
You can read more about here:
http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/DB_TDataSet_CheckBrowseMode.html
I am looking for a way to create a trigger after any changes occur in a table on any row or field.
I want for my web app to automatically refresh if they're have been any changes to the data since it was last loaded. For this I need a "modified_on" attribute for a table which will apply to the whole table, not just a row.
Not sure what database triggers have to do with this problem, as they are not going to be able to trigger any behavior at the web application level. You will need to build logic in your web application to inspect the data looking for a change. Most likely, this would take the form of some some-client triggered refresh process (i.e. AJAX), which would need to call a application script that would take information from the client on when it last checked for an update and compare it to the most recently updated row(s) in the table. As long as you have a timestamp/datetime field on the table and update each row when it is updated, you can retrieve all updated rows via a simple query such as
SELECT {fields} FROM {table}
WHERE {timestamp field} > '{last time checked}'
I you want, you could use this to only update those rows in the application view which need updating rather than re-rendering the whole table (this would minimize response bandwidth/download time, rendering time, etc.). If you simply want to check if the table has been updated from some certain, but don't care about individual rows, you can just check that the above query returns 1 or more rows.
If you don't want the client application view to have to check at regular intervals (as would likely be done with AJAX), you might also consider websockets or similar to enable bi-directional client-server communication, but this still wouldn't change the fact that your server-side application would need to query the database to look for changed records.
So i have an issue, where that properties on my website are either active or inactive. A property is deemed as inactive by default, and i want it to only become active once it has met some criteria. For example, i only want it to become active when a description is provided, at least one rate has been applied, and only when it has a valid ZIP code assigned.
How would i achieve this, since a user might not populate all this information upon first registration, and may want to come back at a later date to finish updating before it becomes active.
The only way i can think of, is to run an "if" statement, each time i update information on a property, which i can work with, but i was wondering if there was any other conditional way of making this happen, where the database regularly checks to see if should set something to active?
Thanks, Gavin
If you were running a full version of SQL Server, you could accomplish this with a trigger and a bitflag column like VoidKing suggested. On the save the trigger would trigger and you would write a complex sql statement that test if all the needed fields are filled and set the bitflag to true or false depending.
I did something like this in a simpler way by having two save buttons. A "save" that didn't trigger any validation and a "Save and Release" button that applied validation to all the needed fields. Both buttons saved the data, but the save and release button would only save if the validation passed and it would save the bitfield "isActive" to 1 where the other save method would save it as a 0.
Might be a good approach else you are left with your checking logic on the single save button, which isn't a bad way to go either.