cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Null result for capture group on request naming regex

gmichels
Guide

Hello all,

 

I am trying to generalize the requests one app receives by leveraging request naming rules using regular expressions. Here are some requests to use as sample:

 

  • /v3/profiles/users/6941094/offices/3619
  • /v3/profiles/users/24325/offices/1123
  • /v3/profiles/users/41241/offices/65689/preferences
  • /v3/profiles/users/9893810/offices/83721
  • /v3/profiles/users/88720/offices/73334/roles

 

My goal is to have them all show in Dynatrace as :

 

  • /v3/profiles/users/<userid>/offices/<officeid>
  • /v3/profiles/users/<userid>/offices/<officeid>/roles
  • /v3/profiles/users/<userid>/offices/<officeid>/preferences

 

I am trying to tackle this using a single global request naming rule using placeholders (using global here because I need to have this done across multiple tenants):

 

 

{
    "enabled": true,
    "namingPattern": "{before_userid}/<userid>/offices/<officeid>{after_officeid}",
    "managementZones": [],
    "conditions": [
        {
            "attribute": "WEBREQUEST_URL_PATH",
            "comparisonInfo": {
                "type": "STRING",
                "comparison": "REGEX_MATCHES",
                "value": "[\\w\/]{1,100}\/users\/[\\w\/]{1,100}\/offices\/",
                "values": null,
                "negate": false,
                "caseSensitive": false
            }
        }
    ],
    "placeholders": [
        {
            "name": "before_userid",
            "attribute": "WEBREQUEST_URL_PATH",
            "kind": "REGEX_EXTRACTION",
            "delimiterOrRegex": "([\\w\/]{1,100}\/users)\/",
            "endDelimiter": null,
            "requestAttribute": null,
            "normalization": "TO_LOWER_CASE",
            "useFromChildCalls": null,
            "aggregation": null,
            "source": null
        },
        {
            "name": "after_officeid",
            "attribute": "WEBREQUEST_URL_PATH",
            "kind": "REGEX_EXTRACTION",
            "delimiterOrRegex": "\/offices\/\\d{1,10}([^$]*+)",
            "endDelimiter": null,
            "requestAttribute": null,
            "normalization": "TO_LOWER_CASE",
            "useFromChildCalls": null,
            "aggregation": null,
            "source": null
        }
    ]
}

 

 

The request naming rule I am using works perfectly for the samples that have something after the office id above, but it does not work for when the request simply ends in the office id number. I get this:

 

  • /v3/profiles/users/<userid>/offices/<officeid>/offices/3619
  • /v3/profiles/users/<userid>/offices/<officeid>/offices/1123
  • /v3/profiles/users/<userid>/offices/<officeid>/preferences
  • /v3/profiles/users/<userid>/offices/<officeid>/offices/83721
  • /v3/profiles/users/<userid>/offices/<officeid>/roles

 

For the requests that end up in simply the office id, the regex results for after_officeid end up in a null capture group:

 

gmichels_0-1662732827339.png

 

I would assume Dynatrace would use the null result from the capture group as a an empty string placeholder, but I am probably doing it wrong, as it's using the regex result itself in the replacement.

 

Does anyone have any clues on having the null result become an empty string, so the replacement works as expected? Apart from creating multiple rules, that is 🙂

 

Thanks

4 REPLIES 4

Julius_Loman
DynaMight Legend
DynaMight Legend

@gmichels please have a look at this TIP POST which contains the solution for your case.

Certified Dynatrace Master | Alanata a.s., Slovakia, Dynatrace Master Partner

Hi @Julius_Loman , thanks for the tip, it indeed helped me in some cases, but it still doesn't work appropriately when the URL ends solely in an ID. Using this request URL, for example :

 

  • /v3/profiles/users/6941094/offices/3619

The goal is to generalize both IDs, so it reads:

 

  • /v3/profiles/users/[ID]/offices/[ID]

 

Using the regex suggested in the pro tip post, it does not match, as the regex requires something to exist after the 2nd ID:

/offices/\d++(/[^/]*+)$

 

gmichels_1-1665166226219.png

 

Using an adaptation of the regex, so it matches, albeit the capture group output is now null:

/offices/\d{1,10}([^$]*+)

gmichels_2-1665166258793.png

 

The end result in Dynatrace:

 

  • /v3/profiles/users/[ID]/offices/[ID]/offices/3619

This is likely happening because when the capture group output is null, Dynatrace uses the match itself in the replacement. I would expect it to honor the null result and substitute the postfix replacement with an empty string.

 

Worth noting the rule works fine when there is something after the last number, such as:

 

  • /v3/profiles/users/6941094/offices/3619/roles

 

Would you think of this as a bug? I can open a ticket with support and have them look at it. 

 

Full request naming rule, for completeness (in Terraform notion, but it's pretty similar to the API request):

 

# for requests such as /v2/profiles/users/[ID]/offices/[ID]/roles
resource "dynatrace_request_naming" "_10_userid_officeid" {
  enabled        = true
  naming_pattern = "{prefix}[ID]/offices/[ID]{postfix}"
  conditions {
    condition {
      attribute = "WEBREQUEST_URL_PATH"
      comparison {
        negate = false
        string {
          case_sensitive = false
          operator       = "REGEX_MATCHES"
          value          = "/users/[\\w/]{1,100}/offices/"
        }
      }
    }
  }
  placeholders {
    placeholder {
      name               = "prefix"
      attribute          = "WEBREQUEST_URL_PATH"
      delimiter_or_regex = "^(.*?/)\\d+"
      kind               = "REGEX_EXTRACTION"
      normalization      = "TO_LOWER_CASE"
    }
    placeholder {
      name               = "postfix"
      attribute          = "WEBREQUEST_URL_PATH"
      delimiter_or_regex = "/offices/\\d{1,10}([^$]*+)"
      kind               = "REGEX_EXTRACTION"
      normalization      = "TO_LOWER_CASE"
    }
  }
}

 

Thank you,

Gustavo

Hey @gmichels ,

 

just tried that on your URL example (/v3/profiles/users/6941094/offices/3619
) and it works for me as expected with my generic rules:

Julius_Loman_1-1665171561051.png

Aren't some rules overriding the global ones in your case?

 

 

Certified Dynatrace Master | Alanata a.s., Slovakia, Dynatrace Master Partner

Hi @Julius_Loman, guess I was overthinking this and indeed it works as you highlighted, although it doesn't make much sense to me as the regex doesn't fully match. But I am going to stop complaining :).

 

The postfix rule needed amending, though, as it doesn't work when there are more sub-paths after the id. For example:

 

  • /v2/directory/plans/someplan/offices/548443/vendor-address/search

 

Was becoming simply:

 

  • /v2/directory/plans/someplan/offices/[ID]

 

Amended postfix regex with:

 

/\d++(/[^$]*+)$
 
And it works as expected.
 
I am still going through some edge cases, but in general I have what I need.
 
Thanks for the help!

Featured Posts