How to rename label within a metric in Prometheus - monitoring

I have a query:
node_systemd_unit_state{instance="server-01",job="node-exporters",name="kubelet.service",state="active"} 1
I want the label name being renamed (or replaced) to unit_name ONLY within the node_systemd_unit_state metric. So, desired result is:
node_systemd_unit_state{instance="server-01",job="node-exporters",unit_name="kubelet.service",state="active"} 1
There are many other metrics with a label name name in the node-exporters job. That's why I can't use relabel config across the job.

you can use the label_replace function in promQL, but it also add the label, don't replace it
label_replace(
<vector_expr>, "<desired_label>", "$1", "<existing_label>", "(.+)"
)
label_replace(
node_systemd_unit_state{instance="server-01",job="node-exporters",name="kubelet.service",state="active"},
"unit_name","$1","name", "(.+)"
)
So, to avoid the repetition you can add:
sum(label_replace(
node_systemd_unit_state{instance="server-01",job="node-exporters",name="kubelet.service",state="active"},
"unit_name","$1","name", "(.+)"
)
)by(unit_name)

I got tired of all the fragmented documentation and I feel I provided a better answer in this post here:
https://medium.com/#texasdave2/replace-and-remove-a-label-in-a-prometheus-query-9500faa302f0
Replace is not a true REPLACE
Your goal is to simply replace the old label name “old_job_id” with a new label name “new_task_id”. Prometheus label_replace will really “add” the new label name. It will preserve the old label name as well… So, that could be a problem, it’s not a true “replace in place”.
So if you want to “add” your new label name and “remove” the old label name, you need to do this:
sum without (old_job_id) (label_replace(metric, "new_task_id", "$1", "old_job_id", "(.*)"))
Here’s how this reads:
sum without (old_job_id) will remove the old label name from the
query output
metric is your metric, like “node_filesystem_avail_bytes”
“new_task_id” is where you would put your new label name
“$1” is regex for using the string in new label name, don’t change
this
“old_job_id” is where you’ll put your old label, the one you want to
get rid of (.*……. that mess is regex that will replace the whole
label name

You can have more than one source label, so:
- source_labels: [__name__, name]
regex: "node_systemd_unit_state;(.+)"
target_label: unit_name
If the label name isn't matching up with other metrics/exporters, you should file a bug with them. Relabelling like this should only be a temporary solution while a proper fix is being pursued.

Prometheus allows renaming labels in the following places:
During metric scrape. In this case you need to add the following relabeling rules into metric_relabel_configs section at the corresponding scrape_config:
metric_relabel_configs:
- source_labels: [__name__, name]
regex: "node_systemd_unit_state;(.+)"
target_label: unit_name
- source_labels: [__name__, name]
regex: "node_systemd_unit_state;(.+)"
target_label: name
replacement: ""
The first rule copies name label value into unit_name label for metrics with node_systemd_unit_state name. The second rule sets name label value to an empty string (e.g. deletes the name label) for metrics with node_systemd_unit_state name.
During querying via label_join() function:
label_join(
label_join(node_systemd_unit_state, "unit_name", "", "name"),
"name", "", "non_existing_label"
)
The inner label_join() copies name label into unit_name label. The outer label_join() substitutes the original name label with an empty string (e.g. remove the name label).
As you can see, label_join() isn't the best function for label renaming. The label_replace() isn't the best function for label renaming too. While Prometheus doesn't provide better solutions for label renaming, such solution exist in Prometheus-like systems such as VictoriaMetrics (I'm the author of this system). It provides label_move() function:
label_move(node_systemd_unit_state, "name", "unit_name")
Additionally, VictoriaMetrics provides if option for conditional relabeling rules. For example, the following relabeling rules are equivalent to the rules above, but are easier to understand and maintain:
metric_relabel_configs:
- if: 'node_systemd_unit_state{name!=""}'
source_labels: [name]
target_label: unit_name
- if: 'node_systemd_unit_state{name!=""}'
target_label: name
replacement: ""

https://demo.promlens.com/?q=label_replace(up%2C%20%22hostname%22%2C%20%22%241%22%2C%20%22instance%22%2C%20%22(.%2B)%3A(%5C%5Cd%2B)%22)
Assume you have metric namely up
up{instance="cadvisor:8080", job="cadvisor"}
up{instance="demo-service-0:10000", job="demo"}
up{instance="demo-service-1:10001", job="demo"}
up{instance="demo-service-2:10002", job="demo"}
up{instance="docker-hub-exporter:9170", job="docker-hub-exporter"}
up{instance="node-exporter:9100", job="node"}
up{instance="prometheus:9090", job="prometheus"}
Now query
label_replace(up, "hostname", "$1", "instance", "(.+)-(.+)-(\\d+):(\\d+)")
will return with new label hostname with first match group ("$1").
up{instance="cadvisor:8080", job="cadvisor"}
up{hostname="demo", instance="demo-service-0:10000", job="demo"}
up{hostname="demo", instance="demo-service-1:10001", job="demo"}
up{hostname="demo", instance="demo-service-2:10002", job="demo"}
up{instance="docker-hub-exporter:9170", job="docker-hub-exporter"}
up{instance="node-exporter:9100", job="node"}
up{instance="prometheus:9090", job="prometheus"}
Query
label_replace(up, "hostname", "$2", "instance", "(.+)-(.+)-(\\d+):(\\d+)")
will return with new label hostname with second match group ("$2") of the regEx.
up{instance="cadvisor:8080", job="cadvisor"}
up{hostname="service", instance="demo-service-0:10000", job="demo"}
up{hostname="service", instance="demo-service-1:10001", job="demo"}
up{hostname="service", instance="demo-service-2:10002", job="demo"}
up{instance="docker-hub-exporter:9170", job="docker-hub-exporter"}
up{instance="node-exporter:9100", job="node"}
up{instance="prometheus:9090", job="prometheus"}

Related

How to keep objects in node Neo4j

I have array of objects with this structure
[{
name:'here is name, which can have punctuation marks ',
value: 'here will be text '
},
{
name:'here is name, which can have punctuation marks ',
value: 'here will be text '
}]
I am trying to find the best way to keep it in neo4j node. Since later I am going to search, filter ... on this data I don't want to keep hole object as string. Creating property by name object.name is not possible because I have punctuation marks. The ideal way would be to keep it as property, because I am going to use this data as property of node, but removing punctuation marks from name is not an option too.
Probably I could keep them in array
['here is the name', ' and the second element of array is the text']
In this case the problem will be to give correct name to the property, which will have this array.
Another option could be to keep all data in list like this
tabs: ['first name - first value', ' second name - second value']
but to search later I will need to use regex inside the list. this doesn't seem flexible.
So what would be the best way ?
Thank you in advance!
You have few possibilities in terms of storing objects in the Neo4j database.
You can turn your JSON object into a string and save it as a property and later you can use APOC procedures for conversation to/from (using these procedures can help you with filtering or sorting on these).
You can create the helper nodes and treat each element of a list as a separate node (I think this is the suggested approach).
Worth to mention, that you can link your nodes to keep the order or just connect them directly if you don't really care about order.
The simplest solution is to use backticks as mentioned in neo4j community forum by Andreas Kollegger
CREATE ({`here is "name", which has punctuation marks!`:"here will be text"})
for more complex cases Giuseppe Villani suggested better solution
CALL apoc.create.nodes(["MyLabel"], [{
`name.with.dots`:'here is name, which can have punctuation marks .',
value: 'here will be text '
},
{
name:'here is name, which can have punctuation marks ',
value: 'here will be text '
}]) yield node
return node
to create a Node with a label ("MyLabel" in this case), so that you can have every data you need in a specific label (possibly to be indexed and/or connect with other entities)

What does the map for SynonymType.entities look like?

I can't seem to figure out how to actually create a synonym for Google Assistant to map labels and label to label when answering a query.
Here's my type file:
synonym:
# matchType: FUZZY_MATCH
acceptUnknownValues: false
entities:
label:
Unfortunately, the value of intent.params.{fieldName}.resolved continues to map to labels (plural) when spoken as a plural phrase. The documentation doesn't specify what the map for entities should look like.
Documentation links:
https://developers.google.com/assistant/actionssdk/reference/rest/Shared.Types/Type
https://developers.google.com/assistant/actionssdk/reference/rest/Shared.Types/SynonymType
Based on this example: https://github.com/actions-on-google/actions-builder-facts-about-google-nodejs/blob/master/sdk/custom/types/fact_category.yaml
Google Assistant SDK SynonymType should look like this:
synonym:
entities:
'resolved value':
synonyms:
- 'proposed match 1'
- 'proposed match 2'
- 'proposed match 3'
matchType: EXACT_MATCH

How to merge labels of two Prometheus queries? [duplicate]

I am using the consul exporter to ingest the health and status of my services into Prometheus. I'd like to fire alerts when the status of services and nodes in Consul is critical and then use tags extracted from Consul when routing those alerts.
I understand from this discussion that service tags are likely to be exported as a separate metric, but I'm not sure how to join one series with another so I can leverage the tags with the health status.
For example, the following query:
max(consul_health_service_status{status="critical"}) by (service_name, status,node) == 1
could return:
{node="app-server-02",service_name="app-server",status="critical"} 1
but I'd also like 'env' from this series:
consul_service_tags{node="app-server-02",service_name="app-server",env="prod"} 1
to get joined along node and service_name to pass the following to the Alertmanager as a single series:
{node="app-server-02",service_name="app-server",status="critical",env="prod"} 1
I could then match 'env' in my routing.
Is there any way to do this? It doesn't look to me like any operations or functions give me the ability to group or join like this. As far as I can see, the tags would already need to be labels on the consul_health_service_status metric.
You can use the argument list of group_left to include extra labels from the right operand (parentheses and indents for clarity):
(
max(consul_health_service_status{status="critical"})
by (service_name,status,node) == 1
)
+ on(service_name,node) group_left(env)
(
0 * consul_service_tags
)
The important part here is the operation + on(service_name,node) group_left(env):
the + is "abused" as a join operator (fine since 0 * consul_service_tags always has the value 0)
group_left(env) is the modifier that includes the extra label env from the right (consul_service_tags)
The answer in this question is accurate. I want to also share a clearer explanation on joining two metrics preserving SAME Labels (might not be directly answering the question). In these metrics following label is there.
name (eg: aaa, bbb, ccc)
I have a metric name metric_a, and if this returns no data for some of the labels, I wish to fetch data from metric_b. i.e:
metric_a has values for {name="aaa"} and {name="bbb"}
metric_b has values for {name="ccc"}
I want the output to be for all three name labels. The solution is to use or in Prometheus.
sum by (name) (increase(metric_a[1w]))
or
sum by (name) (increase(metric_b[1w]))
The result of this will have values for {name="aaa"}, {name="bbb"} and {name="ccc"}.
It is a good practice in Prometheus ecosystem to expose additional labels, which can be joined to multiple metrics, via a separate info-like metric as explained in this article. For example, consul_service_tags metric exposes a set of tags, which can be joined to metrics via (service_name, node) labels.
The join is usually performed via on() and group_left() modifiers applied to * operation. The * doesn't modify values for time series on the left side because info-like metrics usually have constant 1 values. The on() modifier is used for limiting the labels used for finding matching time series on the left and the right side of *. The group_left() modifier is used for adding additional labels from time series on the right side of *. See these docs for details.
For example, the following PromQL query adds env label from consul_service_tags metric to consul_health_service_status metric with the same set of (service_name, node) labels:
consul_health_service_status
* on(service_name, node) group_left(env)
consul_service_tags
Additional label filters can be added to consul_health_service_status if needed. For example, the following query returns only time series with status="critical" label:
consul_health_service_status{status="critical"}
* on(service_name, node) group_left(env)
consul_service_tags

Replace a exact string using Regex in ruby

Consider the the following text
The capital asset as defined in section 2(14) is an exhaustive definition which encompasses all properties of any kind with certain exceptions but the key word is that the property should be "held" section 2.
Now I want to find section 2, for the same I have written the following Regex:
/\bsection+\.*\s+2\b/i
But it is also matching section 2 of section 2(14). I just want it to only match the exact text, not the part of text which is matching with the regex. I know I need to modify the regex, but what are the changes required?
Try with \bsection+\.*\s+2([ .,;?|!])/i . This will only match with section 2 if it is followed by a space or a punctuation mark different than (.
/\bsection+.*\s+2\b([[:punct:]]|\s/
basically you would want the word to end with whitespace or a punctuation.

How to add multiple labels to a node in Neo4J when using Neo4jImport.bat

I am using Neo4jImport.bat to perform my initial database load. I have a node file that looks like this:
application_id:ID(application_id),:LABEL
2036983247,application_id
2037028183,application_id
I would like to (sometimes) add a second :suspect label to some of these rows. For example:
application_id:ID(application_id),:LABEL
2036983247,"application_id,suspect"
2037028183,application_id
Using the above format, the files will load successfully, however, when I try and query the data using cypher I run into issues. Specifically, the below queries return 0 results:
match (n:application_id {application_id:"2036983247"}) return *
match (n:suspect) return *
Whilst the query against the row with a single label works fine:
match (n:application_id {application_id:"2037028183"}) return *
To make it more confusing, the labels() function seems to correctly show the labels as expected being returned in an array for the app with multiple labels.
According to the import documentation on labels:
LABEL
Read one or more labels from this field. For multiple labels, the values are separated by the array delimiter.
What am I doing wrong?
Each :LABEL column can have multiple labels in them, separated by whatever --array-delimiter specifies (defaults to ';'). Also, as Robert mentioned, multiple :LABEL columns is also supported.
To add additional labels to a node, simply add an additional :LABEL header column for each additional label you wish to add.
application_id:ID(application_id),:LABEL,:LABEL
In the contents of the file, you then delimit your labels with whatever delimiter you are using:
2036983247,application_id,suspect
2037028183,application_id
Unlike properties, it seems that the import tool will allow :LABEL columns to be 'missing' (at least if they're the last column).

Resources