How to use 2 conditions inside the elastic watcher - devops

I'm new to ELK, can i use 2 conditions in Elastic watchers. I am getting a field from logs like data = 0 and data = 1 so i need to use that "data" as condition inside my watcher to elobarate the events.
Thanks in advance

There's many solutions. Here's one using painless script:
[query sections...]
},
"condition": {
"script": {
"source": """
def obj = ctx.payload.hits.hits.0;
if (obj.data.value == 0 || obj.data.value == 1) {
return true;
}
return false;
""",
"lang": "painless"
}
},
"actions": {
[actions sections to follow...]
Of course I'm only making up the CTX context data path. In the example, I am referring to the "data" field of the first returned record. You will have to figure out what you want to check. One common piece of data is from aggregations, then you will have a to access ctx.payload.aggregations.*

Related

Applying filters in Sensu

I have tried applying a filter in Sensu, from referring Sensu document, for reducing our monitoring alerts. But problem is, this filter is sending email only when issue is in Resolved state, no critical or warning alerts. Filter looks like :
{
"filters": {
"state_change_only": {
"negate": false,
"attributes": {
"occurrences": "eval: value == 1 || ':::action:::' == 'resolve'"
}
}
}
}
Please help me in understanding this behaviour and what this eval: value == 1 actually means here.
Does it have to do anything with occurrences value? I have values like 2,3 etc. depending on the severity of the checks.

Zapier - add data to JSON response (App development)

We are creating a Zapier app to expose our APIs to the public, so anyone can use it. The main endpoint that people are using returns a very large and complex JSON object. Zapier, it looks like, has a really difficult time parsing nested complex JSON. But it does wonderful with a very simple response object such as
{ "field": "value" }
Our data that is being returned has this structure and we want to move some of the fields to the root of the response so it's easily parsed by Zapier.
"networkSections": [
{
"identifier": "Deductible",
"label": "Deductible",
"inNetworkParameters": [
{
"key": "Annual",
"value": " 600.00",
"message": null,
"otherInfo": null
},
{
"key": "Remaining",
"value": " 600.00",
"message": null,
"otherInfo": null
}
],
"outNetworkParameters": null
},
So, can we do something to return for example the remaining deductible?
I got this far (adding outputFields) but this returns an array of values. I'm not sure how to parse through this array either in the Zap or in the App.
{key: 'networkSections[]inNetworkParameters[]key', label: 'xNetworkSectionsKey',type: 'string'},
ie this returns an array of "Annual", "Remaining", etc
Great question. In this case, there's a lot going on, and outputFields can't quite handle it all. :(
In your example, inNetworkParameters contains an array of objects. Throughout our documentation, we refer to these as line items. These lines items can be passed to other actions, but the different expected structures presents a bit of a problem. The way we've handled this is by letting users map line-items from one step's output to another step's input per field. So if step 1 returns
{
"some_array": [
{
"some_key": "some_value"
}
]
}
and the next step needs to send
{
"data": [
{
"some_other_key": "some_value"
}
]
}
users can accomplish that by mapping some_array.some_key to data.some_other_key.
All of that being said, if you want to always return a Remaining Deductible object, you'll have to do it by modifying the result object itself. As long as this data is always in that same order, you can do something akin to
var data = z.JSON.parse(bundle.response.content);
data["Remaining Deductible"] = data.networkSections[0].inNetworkParameters[1].value;
return data;
If the order differs, you'll have to implement some sort of search to find the objects you'd like to return.
I hope that all helps!
Caleb got me where I wanted to go. For completeness this is the solution.
In the creates directory I have a js file for the actual call. The perform part is below.
perform: (z, bundle) => {
const promise = z.request({
url: 'https://api.example.com/API/Example/' + bundle.inputData.elgRequestID,
method: 'GET',
headers: {
'content-type': 'application/json',
}
});
return promise.then(function(result) {
var data = JSON.parse(result.content);
for (var i=0; i<data.networkSections.length; i++) {
for (var j=0; j<data.networkSections[i].inNetworkParameters.length; j++) {
// DEDUCT
if (data.networkSections[i].identifier == "Deductible" &&
data.networkSections[i].inNetworkParameters[j].key == "Annual")
data["zAnnual Deductible"] = data.networkSections[i].inNetworkParameters[j].value;
} // inner for
} // outer for
return data;
});

Combining Multiple Falcor Data Sources into Single Model

Modified the question to explain better:
I have two Falcor models from two different HttpDataSource, like below:
First model (User model):
const user_model = new falcor.Model(
{
source: new HttpDataSource('http://localhost:3000/api/userManagement')
});
user_model.get(['user', 'list'])
OUTPUT1:
{
"jsonGraph": {
"user": {
"list": {
"$type": "atom",
"value": {
"users": [...]
}
}
}
}
}
Second model (Role model):
const role_model = new falcor.Model(
{
source: new HttpDataSource('http://localhost:3000/api/roleManagement')
});
role_model.get(['role', 'list'])
OUTPUT2:
{
"jsonGraph": {
"role": {
"list": {
"$type": "atom",
"value": {
"roles": [...]
}
}
}
}
}
Is there a way to combine all these Falcor models into a single model?
The purpose is, if I try to do user_model.get(['user', 'list']) more than once it would get the data from Falcor-Model-Cache (after the first fetch from DB).
But if I try to do role_model.get(['user', 'list']), then I have to hit the DB again to get the data (inorder to store the same User list in role_model cache).
So instead if there is a way like below:
all_model = user_model + role_model
then I can do all_model.get(['user', 'list']) (or) all_model.get(['role', 'list']). So basically I would have only one combined Falcor-Model-Cache at the browser end.
Hope the question is more clear now.
You must use forkJoin
forkJoin(model1.source,model2.source).subscribe(res=>{
//in res[0] you have the response of model1.source
//in res[1] you have the response of model2.source
let data={...res[0],...res[1]}
//in data you have all the properties
}

Gatling - Retrieve part of json and check equality

I'm using Gatling tool to load test my service.
I have following response from my server(just an example):
{
"result: {
"288249": {
"allowEdit": 1,
"cells": [
{
"rollupId": "288249",
"description": "Gatling description: 93"
},
{
"rollupId": "288249",
"description": "Gatling description: 83"
}
]
}
}
}
What I need is loop thought all $.result.288249.cells[*].description fields and verify that there's a value, which is equal to what I have in one of my session objects.
It should look similar to following pseudo code:
.check(
jsonPath("$.result.*.cells[*].description").contains("${mySessionValue})
)
Is there are method, which I can use in similar way ?
Thanks in advance!
I think, I've found the solution
.check(
jsonPath("$.result.*.cells[?(#.description == '${mySessionValue}')]")
.find
.exists
)
This should do the work.
You can loop thru as follows
$.each($.result, function(index,obj){
$.each(obj['cells'], function(innerInd, innerObj){
if( ${mySessionValue} == innerObj['description'] )
{
console.log('Found')
return
}
})
})

How to make elasticsearch add the timestamp field to every document in all indices?

Elasticsearch experts,
I have been unable to find a simple way to just tell ElasticSearch to insert the _timestamp field for all the documents that are added in all the indices (and all document types).
I see an example for specific types:
http://www.elasticsearch.org/guide/reference/mapping/timestamp-field/
and also see an example for all indices for a specific type (using _all):
http://www.elasticsearch.org/guide/reference/api/admin-indices-put-mapping/
but I am unable to find any documentation on adding it by default for all documents that get added irrespective of the index and type.
Elasticsearch used to support automatically adding timestamps to documents being indexed, but deprecated this feature in 2.0.0
From the version 5.5 documentation:
The _timestamp and _ttl fields were deprecated and are now removed. As a replacement for _timestamp, you should populate a regular date field with the current timestamp on application side.
You can do this by providing it when creating your index.
$curl -XPOST localhost:9200/test -d '{
"settings" : {
"number_of_shards" : 1
},
"mappings" : {
"_default_":{
"_timestamp" : {
"enabled" : true,
"store" : true
}
}
}
}'
That will then automatically create a _timestamp for all stuff that you put in the index.
Then after indexing something when requesting the _timestamp field it will be returned.
Adding another way to get indexing timestamp. Hope this may help someone.
Ingest pipeline can be used to add timestamp when document is indexed. Here, is a sample example:
PUT _ingest/pipeline/indexed_at
{
"description": "Adds indexed_at timestamp to documents",
"processors": [
{
"set": {
"field": "_source.indexed_at",
"value": "{{_ingest.timestamp}}"
}
}
]
}
Earlier, elastic search was using named-pipelines because of which 'pipeline' param needs to be specified in the elastic search endpoint which is used to write/index documents. (Ref: link) This was bit troublesome as you would need to make changes in endpoints on application side.
With Elastic search version >= 6.5, you can now specify a default pipeline for an index using index.default_pipeline settings. (Refer link for details)
Here is the to set default pipeline:
PUT ms-test/_settings
{
"index.default_pipeline": "indexed_at"
}
I haven't tried out yet, as didn't upgraded to ES 6.5, but above command should work.
You can make use of default index pipelines, leverage the script processor, and thus emulate the auto_now_add functionality you may know from Django and DEFAULT GETDATE() from SQL.
The process of adding a default yyyy-MM-dd HH:mm:ss date goes like this:
1. Create the pipeline and specify which indices it'll be allowed to run on:
PUT _ingest/pipeline/auto_now_add
{
"description": "Assigns the current date if not yet present and if the index name is whitelisted",
"processors": [
{
"script": {
"source": """
// skip if not whitelisted
if (![ "myindex",
"logs-index",
"..."
].contains(ctx['_index'])) { return; }
// don't overwrite if present
if (ctx['created_at'] != null) { return; }
ctx['created_at'] = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
"""
}
}
]
}
Side note: the ingest processor's Painless script context is documented here.
2. Update the default_pipeline setting in all of your indices:
PUT _all/_settings
{
"index": {
"default_pipeline": "auto_now_add"
}
}
Side note: you can restrict the target indices using the multi-target syntax:
PUT myindex,logs-2021-*/_settings?allow_no_indices=true
{
"index": {
"default_pipeline": "auto_now_add"
}
}
3. Ingest a document to one of the configured indices:
PUT myindex/_doc/1
{
"abc": "def"
}
4. Verify that the date string has been added:
GET myindex/_search
An example for ElasticSearch 6.6.2 in Python 3:
from elasticsearch import Elasticsearch
es = Elasticsearch(hosts=["localhost"])
timestamp_pipeline_setting = {
"description": "insert timestamp field for all documents",
"processors": [
{
"set": {
"field": "ingest_timestamp",
"value": "{{_ingest.timestamp}}"
}
}
]
}
es.ingest.put_pipeline("timestamp_pipeline", timestamp_pipeline_setting)
conf = {
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1,
"default_pipeline": "timestamp_pipeline"
},
"mappings": {
"articles":{
"dynamic": "false",
"_source" : {"enabled" : "true" },
"properties": {
"title": {
"type": "text",
},
"content": {
"type": "text",
},
}
}
}
}
response = es.indices.create(
index="articles_index",
body=conf,
ignore=400 # ignore 400 already exists code
)
print ('\nresponse:', response)
doc = {
'title': 'automatically adding a timestamp to documents',
'content': 'prior to version 5 of Elasticsearch, documents had a metadata field called _timestamp. When enabled, this _timestamp was automatically added to every document. It would tell you the exact time a document had been indexed.',
}
res = es.index(index="articles_index", doc_type="articles", id=100001, body=doc)
print(res)
res = es.get(index="articles_index", doc_type="articles", id=100001)
print(res)
About ES 7.x, the example should work after removing the doc_type related parameters as it's not supported any more.
first create index and properties of the index , such as field and datatype and then insert the data using the rest API.
below is the way to create index with the field properties.execute the following in kibana console
`PUT /vfq-jenkins
{
"mappings": {
"properties": {
"BUILD_NUMBER": { "type" : "double"},
"BUILD_ID" : { "type" : "double" },
"JOB_NAME" : { "type" : "text" },
"JOB_STATUS" : { "type" : "keyword" },
"time" : { "type" : "date" }
}}}`
the next step is to insert the data into that index:
curl -u elastic:changeme -X POST http://elasticsearch:9200/vfq-jenkins/_doc/?pretty
-H Content-Type: application/json -d '{
"BUILD_NUMBER":"83","BUILD_ID":"83","JOB_NAME":"OMS_LOG_ANA","JOB_STATUS":"SUCCESS" ,
"time" : "2019-09-08'T'12:39:00" }'

Resources