Skip to main content

Field Detection

Graytool automatically discovers fields from log rows using multiple strategies.

Detection Strategies

Priority Order

1. Data Attributes (highest)  — data-field, data-testid
2. JSON Message Parsing — Clipboard, full_message, pre tags
3. DOM Patterns (lowest) — dt/dd, field-name class

Each strategy works independently and discovered fields are merged and deduplicated.

Strategy 1: Data Attributes

The most reliable method. Reads data attributes from Graylog's DOM structure.

Legacy Format

<td data-field="userId">12345</td>
<td data-field="source">api-gateway</td>

Modern Format (Graylog 5.x+)

<td data-testid="message-summary-field-userId">12345</td>
<td data-testid="message-summary-field-source">api-gateway</td>

Source Type

source: "data-field"  // Priority: 4 (highest)

Strategy 2: JSON Message Parsing

Finds JSON content in the log row and extracts fields.

JSON Sources (in priority order)

  1. Clipboard button — If copy button contains JSON:
<button data-clipboard-text='{"userId":"12345","level":"ERROR"}'>Copy</button>
  1. full_message field — If expanded message contains JSON:
<td data-field="full_message">{"userId":"12345","request":{...}}</td>
  1. Pre tags — If code blocks contain JSON:
<pre>{"userId":"12345","level":"ERROR"}</pre>

JSON Flattening

Nested JSON objects are flattened:

// Original
{
"userId": "12345",
"context": {
"user": {
"name": "John",
"role": "admin"
}
},
"tags": ["api", "auth"]
}

// Flattened
{
"userId": "12345",
"context.user.name": "John",
"context.user.role": "admin",
"tags.0": "api",
"tags.1": "auth"
}

Depth Limit

Controlled by the jsonParseMaxDepth setting (default: 5):

Depth 0: { "a": { "b": { "c": "value" } } }
Depth 1: a → object (continue)
Depth 2: a.b → object (continue)
Depth 3: a.b.c → "value" (string, stop)

JSON String Parsing

When parseJsonStrings: true, embedded JSON in string values is parsed:

// Original
{ "details": "{\"userId\": \"123\"}" }

// Parse result
{ "details.userId": "123" }

Source Type

source: "json-parse"  // Priority: 2

Strategy 3: DOM Patterns

Discovers fields from structural HTML elements.

Description List (dt/dd)

In Graylog's expanded view:

<dl>
<dt>userId</dt>
<dd>12345</dd>
<dt>source</dt>
<dd>api-gateway</dd>
</dl>

Field Name Classes

<span class="field-name">userId</span>
<span class="field-value">12345</span>

Source Type

source: "text-pattern"  // Priority: 1 (lowest)

Deduplication

When the same field is discovered by multiple strategies, the highest-priority source is kept:

Priority order:
data-field → 4 (highest)
dom-attribute → 3
json-parse → 2
text-pattern → 1 (lowest)

Example

"userId" found:
- data-field: "12345" (priority 4) ← Selected ✅
- json-parse: "12345" (priority 2) ← Skipped
- text-pattern: "12345" (priority 1) ← Skipped

DiscoveredField Structure

interface DiscoveredField {
name: string; // Field name: "userId"
value: string; // Field value: "12345"
source: FieldSource; // Discovery method: "data-field"
element?: Element; // DOM reference (optional)
}

type FieldSource = "data-field" | "json-parse" | "text-pattern" | "dom-attribute";

Row Field Prefixes

Some Graylog configurations add prefixes to fields. Graytool searches with configured prefixes:

Prefixes: ["msg.", "context.", ""]

Searching for: "userId"
Scan order:
1. "msg.userId" → { source: "data-field", value: "12345" } ✅
2. "context.userId" → Not found
3. "userId" → Not found (already found)

Troubleshooting

Fields not being detected

  1. Verify there are actual log rows on the page
  2. Make sure your Graylog version is supported
  3. Check the Row Field Prefixes setting
  4. Check the browser console for errors

Wrong field values

  1. Check the parseJsonStrings setting
  2. Try increasing jsonParseMaxDepth
  3. Use the JSON viewer to inspect raw data