Extract log level via regex and set it as a label

Hi there,

I used to extract my logs level through logfmt with the code below:

loki.process "add_dynamic_label" {
    stage.logfmt {
        mapping = { "extracted_level" = "level" }
    }

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

    forward_to = [loki.write.local_loki.receiver]
}

This works but unfortunately, somehow Alloy reports lots of logfmt errors:

msg=“failed to decode logfmt” component_path=/ component_id=loki.process.add_dynamic_label component=stage type=logfmt err=“logfmt syntax error at pos 117 on line 1: unexpected ‘=’”
msg=“failed to decode logfmt” component_path=/ component_id=loki.process.add_dynamic_label component=stage type=logfmt err=“logfmt syntax error at pos 46 on line 1: unexpected ‘"’”

After doing some researches, those errors do not appear to be fixable for the time being.
Nonetheless, I have decided to go down the regex path to extract my log levels but I am failing. Here is my config:

loki.process "add_dynamic_label" {
    stage.regex {
        expression = `(?i)\b(info|debug|error|warn|trace|fatal)\b`
    }

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

    forward_to = [loki.write.local_loki.receiver]
}

Would any body know how I can extract the log level and assign it to the label “level” with Alloy?

Can you provide some examples of your logs, please?

1 Like

Hi Tony,

Thank you for helping.
My logs are simply coming from Journald:

> journalctl
Oct 14 05:14:34 Lxde zeitgeist-fts[2693]: Error releasing name org.gnome.zeitgeist.SimpleIndexer: The connection is closed
Oct 14 05:14:34 Lxde zeitgeist-fts[2693]: zeitgeist-fts.vala:252: The connection is closed
Oct 14 05:14:34 Lxde org.gnome.zeitgeist.Engine[2678]: [16:14:34.416492 WARNING] zeitgeist-daemon.vala:453: The connection is closed
-- Boot 2c84a3183511457babcdbe528a957ef7 --
Oct 14 09:22:02 Lxde xrdp-sesman[1464]: [INFO ] Starting X server on display 10: /usr/lib/xorg/Xorg :10 -auth .Xauthority -config xrdp/xorg.conf -noreset -nolisten tcp -logfile .xorgxrdp.%s.log
Oct 14 09:22:03 Lxde xrdp-sesman[1463]: [INFO ] Found X server running at /tmp/.X11-unix/X10
Oct 14 09:22:03 Lxde xrdp-sesman[1463]: [INFO ] Starting the default window manager on display 10: /etc/xrdp/startwm.sh
Oct 14 09:22:03 Lxde xrdp-chansrv[1472]: [INFO ] Socket 12: AF_UNIX connection received
Oct 14 09:22:03 Lxde dbus-daemon[1494]: [session uid=10000 pid=1491] AppArmor D-Bus mediation is enabled
Oct 14 09:22:03 Lxde xrdp-chansrv[1472]: [INFO ] sound_process_training: round trip time 100
Oct 14 09:22:03 Lxde dbus-daemon[1552]: [session uid=10000 pid=1550] AppArmor D-Bus mediation is enabled
Oct 14 09:22:03 Lxde dbus-daemon[1552]: [session uid=10000 pid=1550] Activating service name='org.gtk.vfs.Daemon' requested by ':1.2' (uid=10000 pid=1581 comm="/usr/bin/ibus-daemon --daemonize --xim " label="unconfined")
Oct 14 09:22:03 Lxde dbus-daemon[1552]: [session uid=10000 pid=1550] Successfully activated service 'org.gtk.vfs.Daemon'
Oct 14 09:22:03 Lxde dbus-daemon[1552]: [session uid=10000 pid=1550] Activating service name='org.freedesktop.portal.IBus' requested by ':1.2' (uid=10000 pid=1581 comm="/usr/bin/ibus-daemon --daemonize --xim " label="unconfined")
Oct 14 09:22:03 Lxde dbus-daemon[1552]: [session uid=10000 pid=1550] Successfully activated service 'org.freedesktop.portal.IBus'

I can clearly see now that some do not have a log level. Would it be possible to set a default label like “unknown” when there are not any identifiable level?

Cheers,

You are not doing a group capture, so when you reference level in your label stage it’s not created anywhere. You can also add a template stage to insert a default value. Try this (not tested):

stage.regex {
  expression = `(?P<level>(?i)\b(info|debug|error|warn|trace|fatal)\b)`
}

stage.template {
    source   = "level_cleansed"
    template = `{{ default "INFO" .level }}`
}

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

Hi Tony,

It works. However, labels are created for both upper and lower case.

Would you know if there is a way to have everything lower case?

Cheers,

I think the best approach would probably be to change the label during processing to make everything lower case. Maybe something like this (not tested):

stage.regex {
  expression = `(?P<level>(?i)\b(info|debug|error|warn|trace|fatal)\b)`
}

stage.template {
    source   = "level_cleansed"
    template = `{{ default "INFO" .level | ToLower }}`
}

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

Hi Tony,

Thank you, it works perfectly :slight_smile:

hi @tonyswumac isn’t there a free online tool that one can use to vet out alloy? do you remember the url for it?

There is a config generator, but I don’t know if it actually verifies configuration. It does show the flow graph though, that’s somewhat useful.

1 Like

also this is a very nice tool

1 Like