Alloy extract exceptions as label from log content

I have log lines containing Java exceptions, as shown below. I want to add a label, commonexceptions , to capture frequently searched exceptions like this. In example below it is AsgardFSException… Similarly i have 15 more common exception AsgardCacheException, AsgardException, AsgardCacheFileNotFoundException etc…

I am already extracting log level, I need exception as well. Please provide some pointers on how to proceed.

2025-01-20 17:10:28.366 [264635] ERROR ArchiverHelper:40 - fail to close archive 1737393009422-partition1371.padawan

*.padawan.AsgardFSException: java.lang.Exception: File .....padawan was deleted from local cache before we copied it to Storage

at *.asgard.padawan.AsgardFSException.throwException(AsgardFSException.java:17) ~[minor-compaction-shaded.jar:?]

at *.asgard.padawan.cache.AsgardCacheLocalFSOutput.close(AsgardCacheLocalFSOutput.java:32) ~[minor-compaction-shaded.jar:?]

... 20 more

You first need to determine what string would be the same across all your exceptions, so we can parse from. I picked the string *.asgard.padawan.AsgardFSException.throwException, but i don’t know if this works for you or not.

Assuming your exception log is in one line, you can try:

loki.process "local" {
  forward_to = [<LOKI_RECEIVER>]

  stage.regex {
    expressions = `\*\.asgard\.padawan\.(?P<exception_name>[^\.]+)\.throwException`
  }

  stage.labels {
    values = {
      exception_name = "",
    }
  }
}

1 Like

Thanks Tony! this works when tried for that particular exception, but across the other exceptions it was hard to find common string. So I tried something like below based on your other thread responses and it works.

I am trying to add 15 match stages, Would this create an overhead for the Alloy agent due to the multiple match stages?

stage.regex {
  expression = "^(?s)(?P<date>\\S+) (?P<time>\\S+) (?P<thread>\\[\\d+\\]) (?P<level>\\w+)\\s*(?P<classname>\\w+:\\d*) - (?P<msg>.+)$"
}

stage.labels {
  values = { level = "level" }
}

stage.match {
  selector = "{level=\"ERROR\"}"
  stage.regex {
    expression = `^(?s)(.*Exception.*)$`
  }

  stage.static_labels {
    values = { exception = "GenericException", }
  }
}

stage.match {
  selector = "{exception=\"GenericException\"} |= \"IllegalArgumentException\""

  stage.static_labels {
    values = { exception = "IllegalArgumentException" }
  } 
}

stage.match {
  selector = "{exception=\"GenericException\"} |= \"AsgardCacheException\""

  stage.static_labels {
    values = { exception = "AsgardCacheException" }
  } 
}

stage.match {
  selector = "{exception=\"GenericException\"} |= \"AsgardException\""

  stage.static_labels {
    values = { exception = "AsgardException" }
  } 
}

No, I think generally match block is pretty efficient, and 15 is not a number I would be concerned about.

1 Like