Logs from Promtail on Windows are too verbose in Grafana

Hi,
I’ve installed Promtail on a Windows machine to collect Windows Security logs (specifically Event ID 4625), and send them to Loki, which is connected to Grafana.

The logs are successfully ingested, but in Grafana the log lines are too long and hard to read, because they include the entire raw JSON.

I just want to display the essential fields, such as:

  • Timestamp
  • TargetUserName
  • IpAddress

How can I configure Grafana (or Promtail) to show only those key fields instead of the full raw message?

Thanks in advance!

It is in general not easy to break up and reform JSON strings with promtail. It can be done, but I wouldn’t recommend it. It is also my preference to not alter original logs when possible.

If you are just worried about displaying the logs, you can use line_format in your logql and show only the text you care about. For example:

{<label_filter>}
  | json
  | line_format "{{ .TargetUserName }} {{ .IpAddress }}"

You’re right — breaking up or modifying JSON strings in Promtail is not easy and should be avoided when possible. To preserve the original log structure, I’ve adopted the line_format approach in LogQL queries to display only the relevant information.

Sample Query

{logsource="windows-eventlog", job="windows-security", username!="", ip!=""}
| json
| event_id == 4625
| line_format "- Login failed: user {{ .username }} from IP {{ .ip }} to {{ .computer }} ({{.destination_ip}})"

Sample promtail-config.yaml

server:
  http_listen_port: 9090
  grpc_listen_port: 0

positions:
  filename: C:\promtail\positions.yaml

clients:
  - url: http://<ip-loki>:<port>/loki/api/v1/push

scrape_configs:
  - job_name: windows-security
    windows_events:
      locale: 1033
      use_incoming_timestamp: true
      exclude_event_data: false
      exclude_user_data: false
      bookmark_path: C:\promtail\bookmark_security.xml
      eventlog_name: "Security"
      xpath_query: '*'
      labels:
        logsource: windows-eventlog
        job: windows-security
        type: security
        hostname: ${COMPUTERNAME}
        destination_ip: Your-server-IP

    pipeline_stages:
      - json:
          expressions:
            event_data: event_data

      - template:
          source: event_data
          template: '{{ .Value | replace "\\u003c" "<" | replace "\\u003e" ">" }}'
          output: event_data

      - regex:
          source: event_data
          expression: "<Data Name='TargetUserName'>(?P<username>[^<]*)</Data>.*?<Data Name='IpAddress'>(?P<ip>[^<]*)</Data>.*?<Data Name='TargetDomainName'>(?P<computer>[^<]*)</Data>"

      - labels:
          username:
          ip:
          computer:

This way, the log remains intact, and parsing is simplified. For alerting or dashboard use cases, I extract only necessary fields into labels using pipeline_stages, and only when absolutely required.

Thank you for the suggestion @tonyswumac