Hiding Root Causes
You may want to hide a root cause for a time period if you are not planning on addressing it immediately or if you are performing maintenance and the behavior is expected.
The recommended way to hide a specific root cause is to use Entity Configs of type IgnoreRC. To avoid overwriting existing configuration for that entity, you should:
- Query the current
IgnoreRCconfig for the entity. - Merge your new rule with any existing entries.
- Call the
CreateEntityConfigsmutation with the combined config.
Each example below reuses the helper utilities defined in the Authentication and GraphQL Clients sections (get_causely_access_token, create_graphql_client, post_query, and their language equivalents).
- python
- javascript
- bash
- go
- graphql
import os
import json
# Reuse helpers defined earlier in this guide:
# - get_causely_access_token
# - create_graphql_client
# - post_query
GET_CONFIGS_QUERY = """
query GetEntityConfigs($entityId: String!, $configType: String!) {
entityConfigs(entityId: $entityId, configType: $configType) {
entityId
type
data
}
}
"""
CREATE_CONFIGS_MUTATION = """
mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) {
createEntityConfigs(entityConfigs: $entityConfigs) {
entityId
type
data
}
}
"""
def load_existing_ignore_rc_configs(client, entity_id, config_type="IgnoreRC"):
"""Fetch existing IgnoreRC configs and return them as a Python list."""
variables = {"entityId": entity_id, "configType": config_type}
result = post_query(client, GET_CONFIGS_QUERY, variables)
entries = []
for cfg in result.get("entityConfigs", []):
data_str = cfg.get("data") or "[]"
try:
entries.extend(json.loads(data_str))
except json.JSONDecodeError:
# If data is malformed, skip rather than failing the whole operation
continue
return entries
def save_ignore_rc_configs(client, entity_id, configs, config_type="IgnoreRC"):
"""Persist the merged IgnoreRC configs back to Causely."""
variables = {
"entityConfigs": [{
"entityId": entity_id,
"type": config_type, # If your schema uses ENUMs, pass the enum instead
"data": json.dumps(configs), # Must be a JSON string
}]
}
return post_query(client, CREATE_CONFIGS_MUTATION, variables)
if __name__ == "__main__":
# Get credentials from environment
cid, secret = os.getenv("CAUSELY_CLIENT_ID"), os.getenv("CAUSELY_CLIENT_SECRET")
if not cid or not secret:
raise EnvironmentError("Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET")
# Get access token and create GraphQL client
token = get_causely_access_token(cid, secret)
client = create_graphql_client(token)
# Target entity and root cause name you want to hide
# Replace these example values with your actual entity ID and root cause name
entity_id = "47c29d23-9f57-5d47-9f91-a72815edc8cf"
defect_name_to_hide = "Malfunction"
# 1) Load existing IgnoreRC configuration (if any)
existing_configs = load_existing_ignore_rc_configs(client, entity_id)
# 2) Add or update the entry for this root cause without losing existing ones
new_entry = {
"DefectName": defect_name_to_hide,
# Set an appropriate expiry time for the ignore rule
"UntilTime": "2025-11-15T10:51:00-04:00",
}
# Avoid adding duplicate entries for the same defect name
merged_configs = [
cfg for cfg in existing_configs
if cfg.get("DefectName") != defect_name_to_hide
]
merged_configs.append(new_entry)
# 3) Save the merged configuration back using the mutation
result = save_ignore_rc_configs(client, entity_id, merged_configs)
print(json.dumps(result, indent=2))
// Reuses helpers defined earlier in this guide:
// - getCauselyAccessToken
// - createGraphQLClient
// - postQuery (for queries)
const { gql } = require('@apollo/client');
const { CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET } = process.env;
const GET_CONFIGS_QUERY = `
query GetEntityConfigs($entityId: String!, $configType: String!) {
entityConfigs(entityId: $entityId, configType: $configType) {
entityId
type
data
}
}
`;
const CREATE_CONFIGS_MUTATION = `
mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) {
createEntityConfigs(entityConfigs: $entityConfigs) {
entityId
type
data
}
}
`;
async function loadExistingIgnoreRcConfigs(client, entityId, configType = 'IgnoreRC') {
const variables = { entityId, configType };
const data = await postQuery(client, GET_CONFIGS_QUERY, variables);
const entries = [];
for (const cfg of data.entityConfigs || []) {
const dataStr = cfg.data || '[]';
try {
entries.push(...JSON.parse(dataStr));
} catch {
// Skip malformed data instead of failing the whole operation
continue;
}
}
return entries;
}
async function saveIgnoreRcConfigs(client, entityId, configs, configType = 'IgnoreRC') {
const variables = {
entityConfigs: [
{
entityId,
type: configType, // If your schema uses ENUMs, pass the enum instead
data: JSON.stringify(configs), // Must be a JSON string
},
],
};
const result = await client.mutate({
mutation: gql(CREATE_CONFIGS_MUTATION),
variables,
});
return result.data;
}
(async () => {
if (!CAUSELY_CLIENT_ID || !CAUSELY_CLIENT_SECRET) {
console.error('Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET');
process.exit(1);
}
// Get access token and create GraphQL client
const token = await getCauselyAccessToken(CAUSELY_CLIENT_ID, CAUSELY_CLIENT_SECRET);
const client = createGraphQLClient(token);
// Replace these example values with your actual entity ID and root cause name
const entityId = '47c29d23-9f57-5d47-9f91-a72815edc8cf';
const defectNameToHide = 'Malfunction';
// 1) Load existing IgnoreRC configuration (if any)
const existingConfigs = await loadExistingIgnoreRcConfigs(client, entityId);
// 2) Add or update the entry for this root cause without losing existing ones
const newEntry = {
DefectName: defectNameToHide,
// Set an appropriate expiry time for the ignore rule
UntilTime: '2025-11-15T10:51:00-04:00',
};
const mergedConfigs = existingConfigs.filter((cfg) => cfg.DefectName !== defectNameToHide);
mergedConfigs.push(newEntry);
// 3) Save the merged configuration back using the mutation
const result = await saveIgnoreRcConfigs(client, entityId, mergedConfigs);
console.log(JSON.stringify(result, null, 2));
})();
#!/usr/bin/env bash
set -euo pipefail
# Prerequisites:
# - CAUSELY_CLIENT_ID / CAUSELY_CLIENT_SECRET exported
# - CAUSELY_ACCESS_TOKEN exported (see Authentication section)
# - post_query / post_query_curl functions defined (see Bash GraphQL helpers section)
# - jq installed
# Replace these example values with your actual entity ID, root cause name and time
ENTITY_ID="47c29d23-9f57-5d47-9f91-a72815edc8cf"
DEFECT_NAME_TO_HIDE="Malfunction"
UNTIL_TIME="2025-11-15T10:51:00-04:00"
# 1) Define GraphQL query and mutation
cat > get_entity_configs.graphql << 'EOF'
query GetEntityConfigs($entityId: String!, $configType: String!) {
entityConfigs(entityId: $entityId, configType: $configType) {
entityId
type
data
}
}
EOF
cat > create_entity_configs.graphql << 'EOF'
mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) {
createEntityConfigs(entityConfigs: $entityConfigs) {
entityId
type
data
}
}
EOF
# 2) Query existing IgnoreRC config
cat > get_entity_configs_variables.json << EOF
{
"entityId": "${ENTITY_ID}",
"configType": "IgnoreRC"
}
EOF
if command -v gq &> /dev/null; then
RAW_RESPONSE=$(gq https://api.causely.app/query/ \
--header "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \
--query-file get_entity_configs.graphql \
--variables-file get_entity_configs_variables.json)
else
QUERY=$(tr '\n' ' ' < get_entity_configs.graphql)
VARIABLES=$(cat get_entity_configs_variables.json)
RAW_RESPONSE=$(post_query_curl "$QUERY" "$VARIABLES")
fi
# 3) Extract current config entries (data is a JSON string)
CURRENT_CONFIGS=$(echo "${RAW_RESPONSE}" \
| jq -r '.data.entityConfigs[0].data // "[]"' \
| jq -c 'try fromjson catch []')
# 4) Merge in the new ignore rule (avoid duplicates on DefectName)
MERGED_CONFIGS=$(
jq -c --arg name "${DEFECT_NAME_TO_HIDE}" --arg until "${UNTIL_TIME}" '
(map(select(.DefectName != $name))) + [
{ "DefectName": $name, "UntilTime": $until }
]
' <<< "${CURRENT_CONFIGS}"
)
# 5) Build variables for CreateEntityConfigs (data must be a JSON string)
DATA_STRING=$(jq -Rs . <<< "${MERGED_CONFIGS}")
cat > create_entity_configs_variables.json << EOF
{
"entityConfigs": [
{
"entityId": "${ENTITY_ID}",
"type": "IgnoreRC",
"data": ${DATA_STRING}
}
]
}
EOF
# 6) Call the mutation
if command -v gq &> /dev/null; then
gq https://api.causely.app/query/ \
--header "Authorization: Bearer ${CAUSELY_ACCESS_TOKEN}" \
--query-file create_entity_configs.graphql \
--variables-file create_entity_configs_variables.json
else
MUTATION=$(tr '\n' ' ' < create_entity_configs.graphql)
VARIABLES=$(cat create_entity_configs_variables.json)
post_query_curl "$MUTATION" "$VARIABLES"
fi
# 7) Cleanup
rm -f get_entity_configs.graphql create_entity_configs.graphql \
get_entity_configs_variables.json create_entity_configs_variables.json
package main
import (
"encoding/json"
"fmt"
"os"
)
// Reuse helpers defined earlier:
// - getToken(id, secret, url)
// - createGraphQLClient(accessToken string) *graphql.Client
// - postQuery(client *graphql.Client, queryString string, variables map[string]interface{}) (interface{}, error)
const getConfigsQuery = `
query GetEntityConfigs($entityId: String!, $configType: String!) {
entityConfigs(entityId: $entityId, configType: $configType) {
entityId
type
data
}
}
`
const createConfigsMutation = `
mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) {
createEntityConfigs(entityConfigs: $entityConfigs) {
entityId
type
data
}
}
`
type entityConfigsResponse struct {
EntityConfigs []struct {
EntityID string `json:"entityId"`
Type string `json:"type"`
Data string `json:"data"`
} `json:"entityConfigs"`
}
func loadExistingIgnoreRCConfigs(gqlClient *graphql.Client, entityID string, configType string) ([]map[string]interface{}, error) {
variables := map[string]interface{}{
"entityId": entityID,
"configType": configType,
}
raw, err := postQuery(gqlClient, getConfigsQuery, variables)
if err != nil {
return nil, err
}
// postQuery returns interface{}; marshal + unmarshal into a typed struct
bytes, err := json.Marshal(raw)
if err != nil {
return nil, err
}
var wrapped struct {
Data entityConfigsResponse `json:"data"`
}
if err := json.Unmarshal(bytes, &wrapped); err != nil {
return nil, err
}
entries := []map[string]interface{}{}
for _, cfg := range wrapped.Data.EntityConfigs {
dataStr := cfg.Data
if dataStr == "" {
continue
}
var arr []map[string]interface{}
if err := json.Unmarshal([]byte(dataStr), &arr); err != nil {
// Skip malformed data instead of failing the whole operation
continue
}
entries = append(entries, arr...)
}
return entries, nil
}
func saveIgnoreRCConfigs(gqlClient *graphql.Client, entityID string, configs []map[string]interface{}, configType string) (interface{}, error) {
dataBytes, err := json.Marshal(configs)
if err != nil {
return nil, err
}
variables := map[string]interface{}{
"entityConfigs": []map[string]interface{}{
{
"entityId": entityID,
"type": configType, // If your schema uses ENUMs, pass the enum instead
"data": string(dataBytes), // Must be a JSON string
},
},
}
return postQuery(gqlClient, createConfigsMutation, variables)
}
func main() {
id, secret := os.Getenv("CAUSELY_CLIENT_ID"), os.Getenv("CAUSELY_CLIENT_SECRET")
if id == "" || secret == "" {
fmt.Fprintln(os.Stderr, "Missing CAUSELY_CLIENT_ID or CAUSELY_CLIENT_SECRET")
os.Exit(1)
}
token, err := getToken(id, secret, "https://auth.causely.app/frontegg/identity/resources/auth/v2/api-token")
if err != nil {
fmt.Fprintln(os.Stderr, "Error getting token:", err)
os.Exit(1)
}
client := createGraphQLClient(token)
// Replace these example values with your actual entity ID, root cause name and time
entityID := "47c29d23-9f57-5d47-9f91-a72815edc8cf"
defectNameToHide := "Malfunction"
untilTime := "2025-11-15T10:51:00-04:00"
// 1) Load existing IgnoreRC configuration (if any)
existing, err := loadExistingIgnoreRCConfigs(client, entityID, "IgnoreRC")
if err != nil {
fmt.Fprintln(os.Stderr, "Error loading configs:", err)
os.Exit(1)
}
// 2) Add or update the entry for this root cause without losing existing ones
merged := make([]map[string]interface{}, 0, len(existing)+1)
for _, cfg := range existing {
if name, ok := cfg["DefectName"].(string); ok && name == defectNameToHide {
continue
}
merged = append(merged, cfg)
}
merged = append(merged, map[string]interface{}{
"DefectName": defectNameToHide,
"UntilTime": untilTime,
})
// 3) Save the merged configuration back using the mutation
result, err := saveIgnoreRCConfigs(client, entityID, merged, "IgnoreRC")
if err != nil {
fmt.Fprintln(os.Stderr, "Error saving configs:", err)
os.Exit(1)
}
out, _ := json.MarshalIndent(result, "", " ")
fmt.Println(string(out))
}
# 1) Query existing IgnoreRC config for an entity
query GetEntityConfigs($entityId: String!, $configType: String!) {
entityConfigs(entityId: $entityId, configType: $configType) {
entityId
type
data
}
}
Variables:
# Replace this example values with your actual entity ID.
{
"entityId": "47c29d23-9f57-5d47-9f91-a72815edc8cf",
"configType": "IgnoreRC"
}
The data field in the response is a JSON string that represents an array of ignore rules, for example:
[{ "DefectName": "SomeOtherDefect", "UntilTime": "2025-11-10T12:00:00-04:00" }]
You should:
- Parse this JSON string in your client.
- Remove any existing entries with the same
DefectNameyou want to hide. - Append a new entry for the root cause you want to hide.
- Stringify the merged array and send it back via
CreateEntityConfigs.
# 2) Save merged IgnoreRC configuration
mutation CreateEntityConfigs($entityConfigs: [EntityConfigInput!]!) {
createEntityConfigs(entityConfigs: $entityConfigs) {
entityId
type
data
}
}
Variables (example after merging):
# Replace this example values with your actual entity ID, root cause name and time
{
"entityConfigs": [
{
"entityId": "47c29d23-9f57-5d47-9f91-a72815edc8cf",
"type": "IgnoreRC",
"data": "[{\"DefectName\":\"SomeOtherDefect\",\"UntilTime\":\"2025-11-10T12:00:00-04:00\"},{\"DefectName\":\"Malfunction\",\"UntilTime\":\"2025-11-15T10:51:00-04:00\"}]"
}
]
}
Note: The
datavalue must be a JSON string, not a nested JSON object. Most clients will useJSON.stringifyor an equivalent function to produce this string.