diff --git a/apps/landing/public/screenshots/guides/log-parsing-01-attributes.webp b/apps/landing/public/screenshots/guides/log-parsing-01-attributes.webp new file mode 100644 index 0000000000..be271b3386 Binary files /dev/null and b/apps/landing/public/screenshots/guides/log-parsing-01-attributes.webp differ diff --git a/apps/landing/public/screenshots/guides/log-parsing-02-columns.webp b/apps/landing/public/screenshots/guides/log-parsing-02-columns.webp new file mode 100644 index 0000000000..a30e9aede4 Binary files /dev/null and b/apps/landing/public/screenshots/guides/log-parsing-02-columns.webp differ diff --git a/apps/landing/src/lib/guide-highlight.ts b/apps/landing/src/lib/guide-highlight.ts index 3179a89dbf..fdb13d0086 100644 --- a/apps/landing/src/lib/guide-highlight.ts +++ b/apps/landing/src/lib/guide-highlight.ts @@ -1,7 +1,18 @@ // Tiny highlighter for guide code blocks. The token classes match the colors a // guide uses in its diagrams (metric name, labels, value), so a block reads the // same way as the annotated example above it. Style the `tok-*` classes on the page. -export type GuideLang = "exposition" | "promql" | "yaml" | "python" | "typescript" | "go" | "rust" | "java" | "csharp"; +export type GuideLang = + | "exposition" + | "promql" + | "yaml" + | "python" + | "typescript" + | "go" + | "rust" + | "java" + | "csharp" + | "shell" + | "otel-debug"; const escape = (s: string) => s.replace(/&/g, "&").replace(//g, ">"); const span = (cls: string, text: string) => `${escape(text)}`; @@ -98,5 +109,31 @@ const rust = braces("use|fn|let|mut|for|in"); const java = braces("import|public|static|final|class|void|new|try|throws"); const csharp = braces("using|var|new|await"); +// Shell commands: the program name, flags and quoted arguments. Single-quoted +// arguments (awk programs, jq filters) are one string, whatever quotes they hold. +const shell = (code: string) => + tokenize(code, [ + [/#.*/y, (m) => span("comment", m[0])], + [/(?<=^|\n|\| )(\s*)([\w.-]+)/y, (m) => escape(m[1]) + span("fn", m[2])], + [/'[^'\n]*'/y, (m) => span("labels", m[0])], + [/"[^"\n]*"/y, (m) => span("labels", m[0])], + [/(?<=\s)--?[\w-]+/y, (m) => span("value", m[0])], + ]); + +// The OpenTelemetry Collector's debug exporter output: field and attribute keys +// as names, values as values, the type wrappers (Str, Int) as comments. A value +// that runs over several lines leaves its closing parenthesis to the last one. +const otelDebug = (code: string) => + code + .split("\n") + .map((line) => { + const attr = /^(\s*-> )([\w.]+)(: )(\w+\()(.*?)(\)?)$/.exec(line); + if (attr) return span("comment", attr[1]) + span("name", attr[2]) + escape(attr[3]) + span("comment", attr[4]) + span("value", attr[5]) + span("comment", attr[6]); + const field = /^(\w[\w ]*)(:)(.*)$/.exec(line); + if (field) return span("name", field[1]) + escape(field[2]) + span("value", field[3]); + return escape(line); + }) + .join("\n"); + export const highlight = (code: string, lang: GuideLang) => - ({ exposition, promql, yaml, python, typescript, go, rust, java, csharp })[lang](code); + ({ exposition, promql, yaml, python, typescript, go, rust, java, csharp, shell, "otel-debug": otelDebug })[lang](code); diff --git a/apps/landing/src/pages/guides/_log-parsing/debug.yaml b/apps/landing/src/pages/guides/_log-parsing/debug.yaml new file mode 100644 index 0000000000..d9f1e159fb --- /dev/null +++ b/apps/landing/src/pages/guides/_log-parsing/debug.yaml @@ -0,0 +1,9 @@ +# debug.yaml: print parsed records instead of exporting them +exporters: + debug: + verbosity: detailed + +service: + pipelines: + logs: + exporters: [debug] diff --git a/apps/landing/src/pages/guides/_log-parsing/json.yaml b/apps/landing/src/pages/guides/_log-parsing/json.yaml new file mode 100644 index 0000000000..2bbf535a0f --- /dev/null +++ b/apps/landing/src/pages/guides/_log-parsing/json.yaml @@ -0,0 +1,14 @@ +receivers: + file_log/app: + include: [/var/log/app/app.json.log] + operators: + - type: json_parser + timestamp: + parse_from: attributes.ts + layout_type: gotime + layout: "2006-01-02T15:04:05Z07:00" + severity: + parse_from: attributes.level + - type: move + from: attributes.msg + to: body diff --git a/apps/landing/src/pages/guides/_log-parsing/logfmt.yaml b/apps/landing/src/pages/guides/_log-parsing/logfmt.yaml new file mode 100644 index 0000000000..f554f33cf9 --- /dev/null +++ b/apps/landing/src/pages/guides/_log-parsing/logfmt.yaml @@ -0,0 +1,11 @@ +receivers: + file_log/worker: + include: [/var/log/worker/worker.log] + operators: + - type: key_value_parser + timestamp: + parse_from: attributes.time + layout_type: gotime + layout: "2006-01-02T15:04:05Z07:00" + severity: + parse_from: attributes.level diff --git a/apps/landing/src/pages/guides/_log-parsing/multiline.yaml b/apps/landing/src/pages/guides/_log-parsing/multiline.yaml new file mode 100644 index 0000000000..8ae83f0d90 --- /dev/null +++ b/apps/landing/src/pages/guides/_log-parsing/multiline.yaml @@ -0,0 +1,14 @@ +receivers: + file_log/java: + include: [/var/log/checkout/app.log] + multiline: + line_start_pattern: '^\d{4}-\d{2}-\d{2} ' + operators: + - type: regex_parser + regex: '(?s)^(?P