├── screenshot.png ├── public ├── favicon.ico ├── robots.txt ├── patterns │ ├── maven │ ├── postgresql │ ├── ruby │ ├── mcollective │ ├── redis │ ├── squid │ ├── mongodb │ ├── bind │ ├── rails │ ├── linux-syslog │ ├── httpd │ ├── junos │ ├── exim │ ├── java │ ├── haproxy │ ├── bro │ ├── aws │ ├── zeek │ ├── grok-patterns │ ├── bacula │ ├── nagios │ ├── postfix │ └── firewalls ├── web │ └── onigasm.wasm ├── favicon_io │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── apple-touch-icon.png │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── site.webmanifest │ └── about.txt ├── manifest.json └── index.html ├── src ├── index.js ├── components │ ├── Ad.js │ ├── Navbar.js │ ├── LoadModal.js │ ├── ShareModal.js │ ├── SaveModal.js │ ├── CustomPatternModal.js │ └── MorePatternsModal.js ├── codemirror │ ├── grok.js │ └── codemirror.css ├── hooks │ └── useLocalStorage.js ├── index.css └── App.js ├── .gitignore ├── LICENSE ├── package.json └── README.md /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/screenshot.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/patterns/maven: -------------------------------------------------------------------------------- 1 | MAVEN_VERSION (?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)(?:[.-](RELEASE|SNAPSHOT))? 2 | -------------------------------------------------------------------------------- /public/web/onigasm.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/public/web/onigasm.wasm -------------------------------------------------------------------------------- /public/favicon_io/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/public/favicon_io/favicon.ico -------------------------------------------------------------------------------- /public/favicon_io/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/public/favicon_io/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon_io/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/public/favicon_io/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicon_io/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/public/favicon_io/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon_io/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/public/favicon_io/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/favicon_io/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjslack/grok-debugger/HEAD/public/favicon_io/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/patterns/postgresql: -------------------------------------------------------------------------------- 1 | # Default postgresql pg_log format pattern 2 | POSTGRESQL %{DATESTAMP:timestamp} %{TZ:[event][timezone]} %{DATA:[user][name]} %{GREEDYDATA:[postgresql][log][connection_id]} %{POSINT:[process][pid]:int} 3 | -------------------------------------------------------------------------------- /public/patterns/ruby: -------------------------------------------------------------------------------- 1 | RUBY_LOGLEVEL (?:DEBUG|FATAL|ERROR|WARN|INFO) 2 | RUBY_LOGGER [DFEWI], \[%{TIMESTAMP_ISO8601:timestamp} #%{POSINT:[process][pid]:int}\] *%{RUBY_LOGLEVEL:[log][level]} -- +%{DATA:[process][name]}: %{GREEDYDATA:message} 3 | -------------------------------------------------------------------------------- /public/patterns/mcollective: -------------------------------------------------------------------------------- 1 | # Remember, these can be multi-line events. 2 | MCOLLECTIVE ., \[%{TIMESTAMP_ISO8601:timestamp} #%{POSINT:[process][pid]:int}\]%{SPACE}%{LOGLEVEL:[log][level]} 3 | 4 | MCOLLECTIVEAUDIT %{TIMESTAMP_ISO8601:timestamp}: 5 | -------------------------------------------------------------------------------- /public/favicon_io/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /public/patterns/redis: -------------------------------------------------------------------------------- 1 | REDISTIMESTAMP %{MONTHDAY} %{MONTH} %{TIME} 2 | REDISLOG \[%{POSINT:[process][pid]:int}\] %{REDISTIMESTAMP:timestamp} \* 3 | REDISMONLOG %{NUMBER:timestamp} \[%{INT:[redis][database][id]} %{IP:[client][ip]}:%{POSINT:[client][port]:int}\] "%{WORD:[redis][command][name]}"\s?%{GREEDYDATA:[redis][command][args]} 4 | -------------------------------------------------------------------------------- /public/favicon_io/about.txt: -------------------------------------------------------------------------------- 1 | This favicon was generated using the following font: 2 | 3 | - Font Title: Roboto Condensed 4 | - Font Author: Copyright 2011 Google Inc. All Rights Reserved. 5 | - Font Source: http://fonts.gstatic.com/s/robotocondensed/v25/ieVl2ZhZI2eCN5jzbjEETS9weq8-59WxDCs5cvI.ttf 6 | - Font License: Apache License, version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)) 7 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import { loadWASM } from 'onigasm'; 6 | 7 | (async () => { 8 | await loadWASM('web/onigasm.wasm'); 9 | ReactDOM.render( 10 | 11 | 12 | , 13 | document.getElementById('root') 14 | ); 15 | })(); 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/components/Ad.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | 3 | export const Ad = () => { 4 | useEffect(() => { 5 | const script = document.createElement("script"); 6 | 7 | script.src = "https://media.ethicalads.io/media/client/ethicalads.min.js"; 8 | script.async = true; 9 | 10 | document.body.appendChild(script); 11 | 12 | return () => { 13 | document.body.removeChild(script); 14 | }; 15 | }, []); 16 | 17 | return
; 18 | }; 19 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/patterns/squid: -------------------------------------------------------------------------------- 1 | # Pattern squid3 2 | # Documentation of squid3 logs formats can be found at the following link: 3 | # http://wiki.squid-cache.org/Features/LogFormat 4 | SQUID3_STATUS (?:%{POSINT:[http][response][status_code]:int}|0|000) 5 | SQUID3 %{NUMBER:timestamp}\s+%{NUMBER:[squid][request][duration]:int}\s%{IP:[source][ip]}\s%{WORD:[event][action]}/%{SQUID3_STATUS}\s%{INT:[http][response][bytes]:int}\s%{WORD:[http][request][method]}\s%{NOTSPACE:[url][original]}\s(?:-|%{NOTSPACE:[user][name]})\s%{WORD:[squid][hierarchy_code]}/(?:-|%{IPORHOST:[destination][address]})\s(?:-|%{NOTSPACE:[http][response][mime_type]}) 6 | # :long - %{INT:[http][response][bytes]:int} 7 | -------------------------------------------------------------------------------- /public/patterns/mongodb: -------------------------------------------------------------------------------- 1 | MONGO_LOG %{SYSLOGTIMESTAMP:timestamp} \[%{WORD:[mongodb][component]}\] %{GREEDYDATA:message} 2 | MONGO_QUERY \{ (?<={ ).*(?= } ntoreturn:) \} 3 | MONGO_SLOWQUERY %{WORD:[mongodb][profile][op]} %{MONGO_WORDDASH:[mongodb][database]}\.%{MONGO_WORDDASH:[mongodb][collection]} %{WORD}: %{MONGO_QUERY:[mongodb][query][original]} ntoreturn:%{NONNEGINT:[mongodb][profile][ntoreturn]:int} ntoskip:%{NONNEGINT:[mongodb][profile][ntoskip]:int} nscanned:%{NONNEGINT:[mongodb][profile][nscanned]:int}.*? nreturned:%{NONNEGINT:[mongodb][profile][nreturned]:int}.*? %{INT:[mongodb][profile][duration]:int}ms 4 | MONGO_WORDDASH \b[\w-]+\b 5 | MONGO3_SEVERITY \w 6 | MONGO3_COMPONENT %{WORD} 7 | MONGO3_LOG %{TIMESTAMP_ISO8601:timestamp} %{MONGO3_SEVERITY:[log][level]} (?:-|%{MONGO3_COMPONENT:[mongodb][component]})%{SPACE}(?:\[%{DATA:[mongodb][context]}\])? %{GREEDYDATA:message} 8 | -------------------------------------------------------------------------------- /public/patterns/bind: -------------------------------------------------------------------------------- 1 | BIND9_TIMESTAMP %{MONTHDAY}[-]%{MONTH}[-]%{YEAR} %{TIME} 2 | 3 | BIND9_DNSTYPE (?:A|AAAA|CAA|CDNSKEY|CDS|CERT|CNAME|CSYNC|DLV|DNAME|DNSKEY|DS|HINFO|LOC|MX|NAPTR|NS|NSEC|NSEC3|OPENPGPKEY|PTR|RRSIG|RP|SIG|SMIMEA|SOA|SRV|TSIG|TXT|URI) 4 | BIND9_CATEGORY (?:queries) 5 | 6 | # dns.question.class is static - only 'IN' is supported by Bind9 7 | # bind.log.question.name is expected to be a 'duplicate' (same as the dns.question.name capture) 8 | BIND9_QUERYLOGBASE client(:? @0x(?:[0-9A-Fa-f]+))? %{IP:[client][ip]}#%{POSINT:[client][port]:int} \(%{GREEDYDATA:[bind][log][question][name]}\): query: %{GREEDYDATA:[dns][question][name]} (?<[dns][question][class]>IN) %{BIND9_DNSTYPE:[dns][question][type]}(:? %{DATA:[bind][log][question][flags]})? \(%{IP:[server][ip]}\) 9 | 10 | # for query-logging category and severity are always fixed as "queries: info: " 11 | BIND9_QUERYLOG %{BIND9_TIMESTAMP:timestamp} %{BIND9_CATEGORY:[bind][log][category]}: %{LOGLEVEL:[log][level]}: %{BIND9_QUERYLOGBASE} 12 | 13 | BIND9 %{BIND9_QUERYLOG} 14 | -------------------------------------------------------------------------------- /src/codemirror/grok.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // The start state contains the rules that are intially used 3 | start: [ 4 | // The regex matches the token, the token property contains the type 5 | // You can match multiple tokens at once. Note that the captured 6 | // groups must span the whole string in this case 7 | // { regex: /(%{)([^:]+)(:?)([^}]+)(})/, token: [null, 'keyword', null, 'string', null] }, 8 | // Rules are matched in the order in which they ap 9 | { regex: /(%{)([^:}]+)(})/, token: ['def', 'operator', 'def'] }, 10 | { regex: /(%{)([^:}]+)(:)([^}]+)(})/, token: ['def', 'operator', 'def', 'keyword', 'def'] }, 11 | { regex: /(\\)([\[|\.|\^|\$|\*|\+|\?|\(|\)|\[|\{|\\|\||\]])/, token: ['qualifier', null] }, 12 | { regex: /(\()(\?)(<)([^>]+)(>)/, token: [null, 'def', 'def', 'keyword', 'def'] }, 13 | ], 14 | // The meta property contains global information about the mode. It 15 | // can contain properties like lineComment, which are supported by 16 | // all modes, and also directives like dontIndentStates, which are 17 | // specific to simple modes. 18 | meta: {}, 19 | }; 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Conor Slack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /public/patterns/rails: -------------------------------------------------------------------------------- 1 | RUUID \h{32} 2 | # rails controller with action 3 | RCONTROLLER (?<[rails][controller][class]>[^#]+)#(?<[rails][controller][action]>\w+) 4 | 5 | # this will often be the only line: 6 | RAILS3HEAD (?m)Started %{WORD:[http][request][method]} "%{URIPATHPARAM:[url][original]}" for %{IPORHOST:[source][address]} at (?%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{HOUR}:%{MINUTE}:%{SECOND} %{ISO8601_TIMEZONE}) 7 | # for some a strange reason, params are stripped of {} - not sure that's a good idea. 8 | RPROCESSING \W*Processing by %{RCONTROLLER} as (?<[rails][request][format]>\S+)(?:\W*Parameters: {%{DATA:[rails][request][params]}}\W*)? 9 | RAILS3FOOT Completed %{POSINT:[http][response][status_code]:int}%{DATA} in %{NUMBER:[rails][request][duration][total]:float}ms %{RAILS3PROFILE}%{GREEDYDATA} 10 | RAILS3PROFILE (?:\(Views: %{NUMBER:[rails][request][duration][view]:float}ms \| ActiveRecord: %{NUMBER:[rails][request][duration][active_record]:float}ms|\(ActiveRecord: %{NUMBER:[rails][request][duration][active_record]:float}ms)? 11 | 12 | # putting it all together 13 | RAILS3 %{RAILS3HEAD}(?:%{RPROCESSING})?(?<[rails][request][explain][original]>(?:%{DATA}\n)*)(?:%{RAILS3FOOT})? 14 | -------------------------------------------------------------------------------- /public/patterns/linux-syslog: -------------------------------------------------------------------------------- 1 | SYSLOG5424PRINTASCII [!-~]+ 2 | 3 | SYSLOGBASE2 (?:%{SYSLOGTIMESTAMP:timestamp}|%{TIMESTAMP_ISO8601:timestamp})(?: %{SYSLOGFACILITY})?(?: %{SYSLOGHOST:[host][hostname]})?(?: %{SYSLOGPROG}:)? 4 | SYSLOGPAMSESSION %{SYSLOGBASE} (?=%{GREEDYDATA:message})%{WORD:[system][auth][pam][module]}\(%{DATA:[system][auth][pam][origin]}\): session %{WORD:[system][auth][pam][session_state]} for user %{USERNAME:[user][name]}(?: by %{GREEDYDATA})? 5 | 6 | CRON_ACTION [A-Z ]+ 7 | CRONLOG %{SYSLOGBASE} \(%{USER:[user][name]}\) %{CRON_ACTION:[system][cron][action]} \(%{DATA:message}\) 8 | 9 | SYSLOGLINE %{SYSLOGBASE2} %{GREEDYDATA:message} 10 | 11 | # IETF 5424 syslog(8) format (see http://www.rfc-editor.org/info/rfc5424) 12 | SYSLOG5424PRI <%{NONNEGINT:[log][syslog][priority]:int}> 13 | SYSLOG5424SD \[%{DATA}\]+ 14 | SYSLOG5424BASE %{SYSLOG5424PRI}%{NONNEGINT:[system][syslog][version]} +(?:-|%{TIMESTAMP_ISO8601:timestamp}) +(?:-|%{IPORHOST:[host][hostname]}) +(?:-|%{SYSLOG5424PRINTASCII:[process][name]}) +(?:-|%{POSINT:[process][pid]:int}) +(?:-|%{SYSLOG5424PRINTASCII:[event][code]}) +(?:-|%{SYSLOG5424SD:[system][syslog][structured_data]})? 15 | 16 | SYSLOG5424LINE %{SYSLOG5424BASE} +%{GREEDYDATA:message} 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.5.0", 8 | "@testing-library/user-event": "^7.2.1", 9 | "codemirror": "^5.57.0", 10 | "grok-js": "github:cjslack/grok-js-web", 11 | "node-fetch": "^2.6.1", 12 | "onigasm": "^2.2.5", 13 | "oniguruma": "^7.2.1", 14 | "react": "^16.13.1", 15 | "react-codemirror2": "^7.2.1", 16 | "react-dom": "^16.13.1", 17 | "react-feather": "^2.0.8", 18 | "react-scripts": "^3.4.4", 19 | "react-select": "^5.7.0", 20 | "simplebar-react": "^2.2.1" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": "react-app" 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/components/Navbar.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { GitHub } from "react-feather"; 3 | 4 | const styles = { 5 | navbar: { 6 | display: "flex", 7 | justifyContent: "space-between", 8 | alignItems: "center", 9 | backgroundColor: "var(--dark)", 10 | padding: "0 1rem", 11 | height: "3.5rem", 12 | width: "100%", 13 | position: "fixed", 14 | boxShadow: "-2px 2px rgba(0, 0, 0, .2)", 15 | zIndex: 1, 16 | }, 17 | navLinks: { 18 | display: "flex", 19 | justifyContent: "flex-end", 20 | alignItems: "center", 21 | }, 22 | }; 23 | 24 | export const Navbar = () => { 25 | return ( 26 |
27 |

28 | {/* {'%{'} */} 29 | Grok 30 | {/* : */} 31 | Debugger 32 | {/* {'}'} */} 33 |

34 |
35 | 36 | 37 | GitHub 38 | 39 |
40 |
41 | ); 42 | }; 43 | -------------------------------------------------------------------------------- /public/patterns/httpd: -------------------------------------------------------------------------------- 1 | HTTPDUSER %{EMAILADDRESS}|%{USER} 2 | HTTPDERROR_DATE %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{YEAR} 3 | 4 | # Log formats 5 | HTTPD_COMMONLOG %{IPORHOST:[source][address]} (?:-|%{HTTPDUSER:[apache][access][user][identity]}) (?:-|%{HTTPDUSER:[user][name]}) \[%{HTTPDATE:timestamp}\] "(?:%{WORD:[http][request][method]} %{NOTSPACE:[url][original]}(?: HTTP/%{NUMBER:[http][version]})?|%{DATA})" (?:-|%{INT:[http][response][status_code]:int}) (?:-|%{INT:[http][response][body][bytes]:int}) 6 | # :long - %{INT:[http][response][body][bytes]:int} 7 | HTTPD_COMBINEDLOG %{HTTPD_COMMONLOG} "(?:-|%{DATA:[http][request][referrer]})" "(?:-|%{DATA:[user_agent][original]})" 8 | 9 | # Error logs 10 | HTTPD20_ERRORLOG \[%{HTTPDERROR_DATE:timestamp}\] \[%{LOGLEVEL:[log][level]}\] (?:\[client %{IPORHOST:[source][address]}\] )?%{GREEDYDATA:message} 11 | HTTPD24_ERRORLOG \[%{HTTPDERROR_DATE:timestamp}\] \[(?:%{WORD:[apache][error][module]})?:%{LOGLEVEL:[log][level]}\] \[pid %{POSINT:[process][pid]:int}(:tid %{INT:[process][thread][id]:int})?\](?: \(%{POSINT:[apache][error][proxy][error][code]?}\)%{DATA:[apache][error][proxy][error][message]}:)?(?: \[client %{IPORHOST:[source][address]}(?::%{POSINT:[source][port]:int})?\])?(?: %{DATA:[error][code]}:)? %{GREEDYDATA:message} 12 | # :long - %{INT:[process][thread][id]:int} 13 | HTTPD_ERRORLOG %{HTTPD20_ERRORLOG}|%{HTTPD24_ERRORLOG} 14 | 15 | # Deprecated 16 | COMMONAPACHELOG %{HTTPD_COMMONLOG} 17 | COMBINEDAPACHELOG %{HTTPD_COMBINEDLOG} 18 | -------------------------------------------------------------------------------- /src/hooks/useLocalStorage.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | export default function useLocalStorage(key, initialValue) { 4 | // State to store our value 5 | // Pass initial state function to useState so logic is only executed once 6 | const [storedValue, setStoredValue] = useState(() => { 7 | if (typeof window === "undefined") { 8 | return initialValue; 9 | } 10 | 11 | try { 12 | // Get from local storage by key 13 | const item = window.localStorage.getItem(key); 14 | // Parse stored json or if none return initialValue 15 | return item ? JSON.parse(item) : initialValue; 16 | } catch (error) { 17 | // If error also return initialValue 18 | console.log(error); 19 | return initialValue; 20 | } 21 | }); 22 | 23 | // Return a wrapped version of useState's setter function that ... 24 | // ... persists the new value to localStorage. 25 | const setValue = (value) => { 26 | try { 27 | // Allow value to be a function so we have same API as useState 28 | const valueToStore = value instanceof Function ? value(storedValue) : value; 29 | // Save state 30 | setStoredValue(valueToStore); 31 | // Save to local storage 32 | if (typeof window !== "undefined") { 33 | window.localStorage.setItem(key, JSON.stringify(valueToStore)); 34 | } 35 | } catch (error) { 36 | // A more advanced implementation would handle the error case 37 | console.log(error); 38 | } 39 | }; 40 | 41 | return [storedValue, setValue]; 42 | } 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [grokdebugger.com](https://www.grokdebugger.com) 2 | 3 | This client-side application uses WebAssembly to emulate the logstash grok library in the browser. It is responsive, feature-rich, and can help you quickly debug your grok patterns. Although it works well in most cases, it is not an exact port of logstash grok, so be sure to test your patterns in your environment before deploying. 4 | 5 | **Features:** 6 | 7 | - Real-time processing (see changes as you type) 8 | - Autocomplete 9 | - Match highlighting 10 | - Syntax highlighting 11 | - Multiline debugging 12 | - 20+ pattern sets (AWS, Grok, firewalls, Java, etc.) 13 | - Add more pattern sets with a URL 14 | - Save and use your own custom patterns 15 | 16 | **Limitations:** 17 | 18 | - Does not support nested objects in naming e.g. `%{IP:user.ip}` or `<%{NONNEGINT:[log][syslog][priority]}>` 19 | - Does not support explicitly defined output types e.g. `%{NUMBER:status:int}` 20 | - Does not support inline flag modifiers e.g. `(?i)opid=%{NOTSPACE:event_operation_id}` https://github.com/cjslack/grok-debugger/issues/6 21 | 22 | **Run locally:** 23 | 24 | Must have [node.js](https://nodejs.org/en) installed 25 | ``` 26 | git clone https://github.com/cjslack/grok-debugger.git 27 | cd grok-debugger 28 | npm install 29 | npm start 30 | ``` 31 | 32 | **How I made this:** 33 | 34 | [node-grok](https://github.com/Beh01der/node-grok) is a library that emulates the grok libarary, but it is not an exact port of it. I [forked](https://github.com/cjslack/grok-js-web) this node.js library and adapted it to run in the browser with Web Assembly. 35 | -------------------------------------------------------------------------------- /public/patterns/junos: -------------------------------------------------------------------------------- 1 | # JUNOS 11.4 RT_FLOW patterns 2 | RT_FLOW_TAG (?:RT_FLOW_SESSION_CREATE|RT_FLOW_SESSION_CLOSE|RT_FLOW_SESSION_DENY) 3 | # deprecated legacy name: 4 | RT_FLOW_EVENT RT_FLOW_TAG 5 | 6 | RT_FLOW1 %{RT_FLOW_TAG:[juniper][srx][tag]}: %{GREEDYDATA:[juniper][srx][reason]}: %{IP:[source][ip]}/%{INT:[source][port]:int}->%{IP:[destination][ip]}/%{INT:[destination][port]:int} %{DATA:[juniper][srx][service_name]} %{IP:[source][nat][ip]}/%{INT:[source][nat][port]:int}->%{IP:[destination][nat][ip]}/%{INT:[destination][nat][port]:int} (?:(?:None)|(?:%{DATA:[juniper][srx][src_nat_rule_name]})) (?:(?:None)|(?:%{DATA:[juniper][srx][dst_nat_rule_name]})) %{INT:[network][iana_number]} %{DATA:[rule][name]} %{DATA:[observer][ingress][zone]} %{DATA:[observer][egress][zone]} %{INT:[juniper][srx][session_id]} \d+\(%{INT:[source][bytes]:int}\) \d+\(%{INT:[destination][bytes]:int}\) %{INT:[juniper][srx][elapsed_time]:int} .* 7 | # :long - %{INT:[source][bytes]:int} 8 | # :long - %{INT:[destination][bytes]:int} 9 | 10 | RT_FLOW2 %{RT_FLOW_TAG:[juniper][srx][tag]}: session created %{IP:[source][ip]}/%{INT:[source][port]:int}->%{IP:[destination][ip]}/%{INT:[destination][port]:int} %{DATA:[juniper][srx][service_name]} %{IP:[source][nat][ip]}/%{INT:[source][nat][port]:int}->%{IP:[destination][nat][ip]}/%{INT:[destination][nat][port]:int} (?:(?:None)|(?:%{DATA:[juniper][srx][src_nat_rule_name]})) (?:(?:None)|(?:%{DATA:[juniper][srx][dst_nat_rule_name]})) %{INT:[network][iana_number]} %{DATA:[rule][name]} %{DATA:[observer][ingress][zone]} %{DATA:[observer][egress][zone]} %{INT:[juniper][srx][session_id]} .* 11 | 12 | RT_FLOW3 %{RT_FLOW_TAG:[juniper][srx][tag]}: session denied %{IP:[source][ip]}/%{INT:[source][port]:int}->%{IP:[destination][ip]}/%{INT:[destination][port]:int} %{DATA:[juniper][srx][service_name]} %{INT:[network][iana_number]}\(\d\) %{DATA:[rule][name]} %{DATA:[observer][ingress][zone]} %{DATA:[observer][egress][zone]} .* 13 | 14 | -------------------------------------------------------------------------------- /public/patterns/exim: -------------------------------------------------------------------------------- 1 | EXIM_MSGID [0-9A-Za-z]{6}-[0-9A-Za-z]{6}-[0-9A-Za-z]{2} 2 | # <= message arrival 3 | # => normal message delivery 4 | # -> additional address in same delivery 5 | # *> delivery suppressed by -N 6 | # ** delivery failed; address bounced 7 | # == delivery deferred; temporary problem 8 | EXIM_FLAGS (?:<=|=>|->|\*>|\*\*|==|<>|>>) 9 | EXIM_DATE (:?%{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{TIME}) 10 | EXIM_PID \[%{POSINT:[process][pid]:int}\] 11 | EXIM_QT ((\d+y)?(\d+w)?(\d+d)?(\d+h)?(\d+m)?(\d+s)?) 12 | EXIM_EXCLUDE_TERMS (Message is frozen|(Start|End) queue run| Warning: | retry time not reached | no (IP address|host name) found for (IP address|host) | unexpected disconnection while reading SMTP command | no immediate delivery: |another process is handling this message) 13 | EXIM_REMOTE_HOST (H=(%{NOTSPACE:[source][address]} )?(\(%{NOTSPACE:[exim][log][remote_address]}\) )?\[%{IP:[source][ip]}\](?::%{POSINT:[source][port]:int})?) 14 | EXIM_INTERFACE (I=\[%{IP:[destination][ip]}\](?::%{NUMBER:[destination][port]:int})) 15 | EXIM_PROTOCOL (P=%{NOTSPACE:[network][protocol]}) 16 | EXIM_MSG_SIZE (S=%{NUMBER:[exim][log][message][size]:int}) 17 | EXIM_HEADER_ID (id=%{NOTSPACE:[exim][log][header_id]}) 18 | EXIM_QUOTED_CONTENT (?:\\.|[^\\"])* 19 | EXIM_SUBJECT (T="%{EXIM_QUOTED_CONTENT:[exim][log][message][subject]}") 20 | 21 | EXIM_UNKNOWN_FIELD (?:[A-Za-z0-9]{1,4}=(?:%{QUOTEDSTRING}|%{NOTSPACE})) 22 | EXIM_NAMED_FIELDS (?: (?:%{EXIM_REMOTE_HOST}|%{EXIM_INTERFACE}|%{EXIM_PROTOCOL}|%{EXIM_MSG_SIZE}|%{EXIM_HEADER_ID}|%{EXIM_SUBJECT}|%{EXIM_UNKNOWN_FIELD}))* 23 | 24 | EXIM_MESSAGE_ARRIVAL %{EXIM_DATE:timestamp} (?:%{EXIM_PID} )?%{EXIM_MSGID:[exim][log][message][id]} (?<[exim][log][flags]><=) (?<[exim][log][status]>[a-z:] )?%{EMAILADDRESS:[exim][log][sender][email]}%{EXIM_NAMED_FIELDS}(?:(?: from ?)? for %{EMAILADDRESS:[exim][log][recipient][email]})? 25 | 26 | EXIM %{EXIM_MESSAGE_ARRIVAL} 27 | -------------------------------------------------------------------------------- /src/components/LoadModal.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { X, Edit2, Trash2 } from "react-feather"; 3 | 4 | export const LoadModal = ({ setShowModal, customPatterns, setCustomPatterns, setPattern }) => { 5 | const handleDelete = (id) => { 6 | const updatedCustomPatterns = customPatterns.filter((p) => p.id !== id); 7 | setCustomPatterns(updatedCustomPatterns); 8 | }; 9 | 10 | const handleEdit = (id) => { 11 | const pattern = customPatterns.find((p) => p.id === id); 12 | setPattern(pattern.pattern); 13 | setShowModal(null); 14 | }; 15 | 16 | return ( 17 |
18 |
19 |
20 |

Edit Custom Patterns

21 | setShowModal(null)} /> 22 |
23 |
24 | {!!customPatterns.length ? ( 25 |
26 |
27 |
Name
28 |
Pattern
29 |
30 |
31 | {customPatterns.map((pattern) => { 32 | return ( 33 |
34 |
{pattern.id}
35 |
{pattern.pattern}
36 |
handleEdit(pattern.id)}> 37 | 38 |
39 |
handleDelete(pattern.id)}> 40 | 41 |
42 |
43 | ); 44 | })} 45 |
46 |
47 | ) : ( 48 |

No custom patterns yet

49 | )} 50 |
51 |
52 |
53 | ); 54 | }; 55 | -------------------------------------------------------------------------------- /src/components/ShareModal.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useRef } from "react"; 2 | import { X, AlertTriangle, Copy } from "react-feather"; 3 | 4 | export const ShareModal = ({ setShowModal, pattern, sample }) => { 5 | const [showWarn, setShowWarn] = useState(false); 6 | const [url, setUrl] = useState(""); 7 | 8 | const [copyIndicator, setCopyIndicator] = useState(false); 9 | 10 | const ref = useRef(); 11 | 12 | const onLoad = async () => { 13 | setUrl( 14 | window.location.origin + "?pattern=" + encodeURIComponent(pattern) + "&sample=" + encodeURIComponent(sample) 15 | // + "&collections=" + 16 | // encodeURIComponent(JSON.stringify(collections.filter((c) => c.active))) 17 | ); 18 | }; 19 | 20 | useEffect(() => { 21 | onLoad(); 22 | }, []); 23 | 24 | useEffect(() => { 25 | ref.current.select(); 26 | if (url.length > 2000) return setShowWarn(true); 27 | setShowWarn(false); 28 | }, [url]); 29 | 30 | const handleSubmit = (e) => { 31 | e.preventDefault(); 32 | navigator.clipboard.writeText(url); 33 | setCopyIndicator(true); 34 | setTimeout(() => { 35 | setCopyIndicator(false); 36 | }, 2000); 37 | }; 38 | 39 | return ( 40 |
41 |
42 |
43 |

Share

44 | setShowModal(null)} /> 45 |
46 |
47 |
48 | {showWarn && ( 49 |
50 | 51 | This url may be too long to work on some browsers 52 |
53 | )} 54 | 55 |
56 |
57 | 61 |
62 |
63 |
64 |
65 | ); 66 | }; 67 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 18 | 19 | 28 | Grok Debugger | Autocomplete and Live Match Highlghting 29 | 30 | 31 | 32 |
33 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /public/patterns/java: -------------------------------------------------------------------------------- 1 | JAVACLASS (?:[a-zA-Z$_][a-zA-Z$_0-9]*\.)*[a-zA-Z$_][a-zA-Z$_0-9]* 2 | #Space is an allowed character to match special cases like 'Native Method' or 'Unknown Source' 3 | JAVAFILE (?:[a-zA-Z$_0-9. -]+) 4 | #Allow special , methods 5 | JAVAMETHOD (?:(<(?:cl)?init>)|[a-zA-Z$_][a-zA-Z$_0-9]*) 6 | #Line number is optional in special cases 'Native method' or 'Unknown source' 7 | JAVASTACKTRACEPART %{SPACE}at %{JAVACLASS:[java][log][origin][class][name]}\.%{JAVAMETHOD:[log][origin][function]}\(%{JAVAFILE:[log][origin][file][name]}(?::%{INT:[log][origin][file][line]:int})?\) 8 | # Java Logs 9 | JAVATHREAD (?:[A-Z]{2}-Processor[\d]+) 10 | JAVALOGMESSAGE (?:.*) 11 | 12 | # MMM dd, yyyy HH:mm:ss eg: Jan 9, 2014 7:13:13 AM 13 | # matches default logging configuration in Tomcat 4.1, 5.0, 5.5, 6.0, 7.0 14 | CATALINA7_DATESTAMP %{MONTH} %{MONTHDAY}, %{YEAR} %{HOUR}:%{MINUTE}:%{SECOND} (?:AM|PM) 15 | CATALINA7_LOG %{CATALINA7_DATESTAMP:timestamp} %{JAVACLASS:[java][log][origin][class][name]}(?: %{JAVAMETHOD:[log][origin][function]})?\s*(?:%{LOGLEVEL:[log][level]}:)? %{JAVALOGMESSAGE:message} 16 | 17 | # 31-Jul-2020 16:40:38.578 in Tomcat 8.5/9.0 18 | CATALINA8_DATESTAMP %{MONTHDAY}-%{MONTH}-%{YEAR} %{HOUR}:%{MINUTE}:%{SECOND} 19 | CATALINA8_LOG %{CATALINA8_DATESTAMP:timestamp} %{LOGLEVEL:[log][level]} \[%{DATA:[java][log][origin][thread][name]}\] %{JAVACLASS:[java][log][origin][class][name]}\.(?:%{JAVAMETHOD:[log][origin][function]})? %{JAVALOGMESSAGE:message} 20 | 21 | CATALINA_DATESTAMP (?:%{CATALINA8_DATESTAMP})|(?:%{CATALINA7_DATESTAMP}) 22 | CATALINALOG (?:%{CATALINA8_LOG})|(?:%{CATALINA7_LOG}) 23 | 24 | # in Tomcat 5.5, 6.0, 7.0 it is the same as catalina.out logging format 25 | TOMCAT7_LOG %{CATALINA7_LOG} 26 | TOMCAT8_LOG %{CATALINA8_LOG} 27 | 28 | # NOTE: a weird log we started with - not sure what TC version this should match out of the box (due the | delimiters) 29 | TOMCATLEGACY_DATESTAMP %{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{HOUR}:%{MINUTE}:%{SECOND}(?: %{ISO8601_TIMEZONE})? 30 | TOMCATLEGACY_LOG %{TOMCATLEGACY_DATESTAMP:timestamp} \| %{LOGLEVEL:[log][level]} \| %{JAVACLASS:[java][log][origin][class][name]} - %{JAVALOGMESSAGE:message} 31 | 32 | TOMCAT_DATESTAMP (?:%{CATALINA8_DATESTAMP})|(?:%{CATALINA7_DATESTAMP})|(?:%{TOMCATLEGACY_DATESTAMP}) 33 | 34 | TOMCATLOG (?:%{TOMCAT8_LOG})|(?:%{TOMCAT7_LOG})|(?:%{TOMCATLEGACY_LOG}) 35 | -------------------------------------------------------------------------------- /src/components/SaveModal.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { Save, X, XOctagon, AlertTriangle } from 'react-feather'; 3 | 4 | export const SaveModal = ({ setShowModal, pattern, savedPatterns, setSavedPatterns }) => { 5 | const [title, setTitle] = useState(''); 6 | const [showWarn, setShowWarn] = useState(false); 7 | const [showError, setShowError] = useState(false); 8 | 9 | const handleSubmit = async (e) => { 10 | e.preventDefault(); 11 | if (!(title && pattern)) { 12 | return setShowError(true); 13 | } 14 | localStorage.setItem('grokdebugger-' + title, pattern); 15 | setSavedPatterns([...savedPatterns.filter((p) => p.title !== title), { title, pattern }]); 16 | setShowModal(null); 17 | }; 18 | 19 | useEffect(() => { 20 | let timeout = setTimeout(() => { 21 | if (savedPatterns.find((p) => p.title === title)) { 22 | setShowWarn(true); 23 | } else { 24 | setShowWarn(false); 25 | } 26 | }, 250); 27 | return () => clearTimeout(timeout); 28 | }, [title]); 29 | 30 | return ( 31 |
32 |
33 |
34 |

Save Pattern

35 | setShowModal(null)} /> 36 |
37 |
handleSubmit(e)}> 38 |
39 | {showWarn && ( 40 |
41 | 42 | This title already exists. Submit to overwrite. 43 |
44 | )} 45 | {showError && ( 46 |
47 | 48 | Title or pattern is blank. 49 |
50 | )} 51 | setTitle(e.target.value)} name="title" placeholder="title" autoComplete="off"> 52 |
53 |
54 | 58 |
59 |
60 |
61 |
62 | ); 63 | }; 64 | -------------------------------------------------------------------------------- /src/components/CustomPatternModal.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef, useState } from "react"; 2 | import { AlertTriangle, PlusSquare, Save, X } from "react-feather"; 3 | 4 | const nameRegex = /^([A-Z0-9_]+)$/; 5 | 6 | export const CustomPatternModal = ({ 7 | setShowModal, 8 | groks, 9 | pattern, 10 | setPattern, 11 | patterns, 12 | customPatterns, 13 | setCustomPatterns, 14 | }) => { 15 | const [name, setName] = useState(""); 16 | const [warnMessage, setWarnMessage] = useState(null); 17 | 18 | const firstUpdate = useRef(true); 19 | 20 | useEffect(() => { 21 | if (pattern == "") { 22 | return setWarnMessage("Grok pattern cannot be blank."); 23 | } 24 | if (firstUpdate.current) { 25 | firstUpdate.current = false; 26 | return; 27 | } 28 | let timeout = setTimeout(() => { 29 | if (!nameRegex.test(name)) { 30 | return setWarnMessage("Pattern name can only contain letters, numbers, or underscores."); 31 | } 32 | if (patterns.map((p) => p.id).includes(name)) { 33 | return setWarnMessage("This pattern name already exists in a collection. Try another name."); 34 | } else { 35 | return setWarnMessage(null); 36 | } 37 | }, 500); 38 | return () => clearTimeout(timeout); 39 | }, [name]); 40 | 41 | const handleSubmit = (e) => { 42 | e.preventDefault(); 43 | if (warnMessage) return; 44 | groks.createPattern(pattern, name); 45 | setCustomPatterns(() => [...customPatterns, { id: name, pattern }]); 46 | setPattern(() => `%{${name}}`); 47 | setShowModal(null); 48 | }; 49 | 50 | return ( 51 |
52 |
53 |
54 |

Add as Custom Pattern

55 | setShowModal(null)} /> 56 |
57 |
58 |
59 | {warnMessage && ( 60 |
61 | 62 | {warnMessage} 63 |
64 | )} 65 | setName(e.target.value.toUpperCase())} 69 | name="name" 70 | placeholder="NAME" 71 | autoComplete="off" 72 | /> 73 | {/*
74 | 75 |
*/} 76 |
77 |
78 | 82 |
83 |
84 |
85 |
86 | ); 87 | }; 88 | -------------------------------------------------------------------------------- /public/patterns/haproxy: -------------------------------------------------------------------------------- 1 | 2 | HAPROXYTIME (?!<[0-9])%{HOUR}:%{MINUTE}(?::%{SECOND})(?![0-9]) 3 | HAPROXYDATE %{MONTHDAY}/%{MONTH}/%{YEAR}:%{HAPROXYTIME}.%{INT} 4 | 5 | # Override these default patterns to parse out what is captured in your haproxy.cfg 6 | HAPROXYCAPTUREDREQUESTHEADERS %{DATA:[haproxy][http][request][captured_headers]} 7 | HAPROXYCAPTUREDRESPONSEHEADERS %{DATA:[haproxy][http][response][captured_headers]} 8 | 9 | # Example: 10 | # These haproxy config lines will add data to the logs that are captured 11 | # by the patterns below. Place them in your custom patterns directory to 12 | # override the defaults. 13 | # 14 | # capture request header Host len 40 15 | # capture request header X-Forwarded-For len 50 16 | # capture request header Accept-Language len 50 17 | # capture request header Referer len 200 18 | # capture request header User-Agent len 200 19 | # 20 | # capture response header Content-Type len 30 21 | # capture response header Content-Encoding len 10 22 | # capture response header Cache-Control len 200 23 | # capture response header Last-Modified len 200 24 | # 25 | # HAPROXYCAPTUREDREQUESTHEADERS %{DATA:[haproxy][http][request][host]}\|%{DATA:[haproxy][http][request][x_forwarded_for]}\|%{DATA:[haproxy][http][request][accept_language]}\|%{DATA:[http][request][referrer]}\|%{DATA:[user_agent][original]} 26 | # HAPROXYCAPTUREDRESPONSEHEADERS %{DATA:[http][response][mime_type]}\|%{DATA:[haproxy][http][response][encoding]}\|%{DATA:[haproxy][http][response][cache_control]}\|%{DATA:[haproxy][http][response][last_modified]} 27 | 28 | HAPROXYURI (?:%{URIPROTO:[url][scheme]}://)?(?:%{USER:[url][username]}(?::[^@]*)?@)?(?:%{IPORHOST:[url][domain]}(?::%{POSINT:[url][port]:int})?)?(?:%{URIPATH:[url][path]}(?:\?%{URIQUERY:[url][query]})?)? 29 | 30 | HAPROXYHTTPREQUESTLINE (?:|(?:%{WORD:[http][request][method]} %{HAPROXYURI:[url][original]}(?: HTTP/%{NUMBER:[http][version]})?)) 31 | 32 | # parse a haproxy 'httplog' line 33 | HAPROXYHTTPBASE %{IP:[source][address]}:%{INT:[source][port]:int} \[%{HAPROXYDATE:[haproxy][request_date]}\] %{NOTSPACE:[haproxy][frontend_name]} %{NOTSPACE:[haproxy][backend_name]}/(?:|%{NOTSPACE:[haproxy][server_name]}) (?:-1|%{INT:[haproxy][http][request][time_wait_ms]:int})/(?:-1|%{INT:[haproxy][total_waiting_time_ms]:int})/(?:-1|%{INT:[haproxy][connection_wait_time_ms]:int})/(?:-1|%{INT:[haproxy][http][request][time_wait_without_data_ms]:int})/%{NOTSPACE:[haproxy][total_time_ms]} %{INT:[http][response][status_code]:int} %{INT:[source][bytes]:int} (?:-|%{DATA:[haproxy][http][request][captured_cookie]}) (?:-|%{DATA:[haproxy][http][response][captured_cookie]}) %{NOTSPACE:[haproxy][termination_state]} %{INT:[haproxy][connections][active]:int}/%{INT:[haproxy][connections][frontend]:int}/%{INT:[haproxy][connections][backend]:int}/%{INT:[haproxy][connections][server]:int}/%{INT:[haproxy][connections][retries]:int} %{INT:[haproxy][server_queue]:int}/%{INT:[haproxy][backend_queue]:int}(?: \{%{HAPROXYCAPTUREDREQUESTHEADERS}\}(?: \{%{HAPROXYCAPTUREDRESPONSEHEADERS}\})?)?(?: "%{HAPROXYHTTPREQUESTLINE}"?)? 34 | # :long - %{INT:[source][bytes]:int} 35 | 36 | HAPROXYHTTP (?:%{SYSLOGTIMESTAMP:timestamp}|%{TIMESTAMP_ISO8601:timestamp}) %{IPORHOST:[host][hostname]} %{SYSLOGPROG}: %{HAPROXYHTTPBASE} 37 | 38 | # parse a haproxy 'tcplog' line 39 | HAPROXYTCP (?:%{SYSLOGTIMESTAMP:timestamp}|%{TIMESTAMP_ISO8601:timestamp}) %{IPORHOST:[host][hostname]} %{SYSLOGPROG}: %{IP:[source][address]}:%{INT:[source][port]:int} \[%{HAPROXYDATE:[haproxy][request_date]}\] %{NOTSPACE:[haproxy][frontend_name]} %{NOTSPACE:[haproxy][backend_name]}/(?:|%{NOTSPACE:[haproxy][server_name]}) (?:-1|%{INT:[haproxy][total_waiting_time_ms]:int})/(?:-1|%{INT:[haproxy][connection_wait_time_ms]:int})/%{NOTSPACE:[haproxy][total_time_ms]} %{INT:[source][bytes]:int} %{NOTSPACE:[haproxy][termination_state]} %{INT:[haproxy][connections][active]:int}/%{INT:[haproxy][connections][frontend]:int}/%{INT:[haproxy][connections][backend]:int}/%{INT:[haproxy][connections][server]:int}/%{INT:[haproxy][connections][retries]:int} %{INT:[haproxy][server_queue]:int}/%{INT:[haproxy][backend_queue]:int} 40 | # :long - %{INT:[source][bytes]:int} 41 | -------------------------------------------------------------------------------- /public/patterns/bro: -------------------------------------------------------------------------------- 1 | # supports the 'old' BRO log files, for updated Zeek log format see the patters/ecs-v1/zeek 2 | # https://www.bro.org/sphinx/script-reference/log-files.html 3 | 4 | BRO_BOOL [TF] 5 | BRO_DATA [^\t]+ 6 | 7 | # http.log - old format (before the Zeek rename) : 8 | BRO_HTTP %{NUMBER:timestamp}\t%{NOTSPACE:[zeek][session_id]}\t%{IP:[source][ip]}\t%{INT:[source][port]:int}\t%{IP:[destination][ip]}\t%{INT:[destination][port]:int}\t%{INT:[zeek][http][trans_depth]:int}\t(?:-|%{WORD:[http][request][method]})\t(?:-|%{BRO_DATA:[url][domain]})\t(?:-|%{BRO_DATA:[url][original]})\t(?:-|%{BRO_DATA:[http][request][referrer]})\t(?:-|%{BRO_DATA:[user_agent][original]})\t(?:-|%{NUMBER:[http][request][body][bytes]:int})\t(?:-|%{NUMBER:[http][response][body][bytes]:int})\t(?:-|%{POSINT:[http][response][status_code]:int})\t(?:-|%{DATA:[zeek][http][status_msg]})\t(?:-|%{POSINT:[zeek][http][info_code]:int})\t(?:-|%{DATA:[zeek][http][info_msg]})\t(?:-|%{BRO_DATA:[zeek][http][filename]})\t(?:\(empty\)|%{BRO_DATA:[zeek][http][tags]})\t(?:-|%{BRO_DATA:[url][username]})\t(?:-|%{BRO_DATA:[url][password]})\t(?:-|%{BRO_DATA:[zeek][http][proxied]})\t(?:-|%{BRO_DATA:[zeek][http][orig_fuids]})\t(?:-|%{BRO_DATA:[http][request][mime_type]})\t(?:-|%{BRO_DATA:[zeek][http][resp_fuids]})\t(?:-|%{BRO_DATA:[http][response][mime_type]}) 9 | # :long - %{NUMBER:[http][request][body][bytes]:int} 10 | # :long - %{NUMBER:[http][response][body][bytes]:int} 11 | 12 | # dns.log - old format 13 | BRO_DNS %{NUMBER:timestamp}\t%{NOTSPACE:[zeek][session_id]}\t%{IP:[source][ip]}\t%{INT:[source][port]:int}\t%{IP:[destination][ip]}\t%{INT:[destination][port]:int}\t%{WORD:[network][transport]}\t(?:-|%{INT:[dns][id]:int})\t(?:-|%{BRO_DATA:[dns][question][name]})\t(?:-|%{INT:[zeek][dns][qclass]:int})\t(?:-|%{BRO_DATA:[zeek][dns][qclass_name]})\t(?:-|%{INT:[zeek][dns][qtype]:int})\t(?:-|%{BRO_DATA:[dns][question][type]})\t(?:-|%{INT:[zeek][dns][rcode]:int})\t(?:-|%{BRO_DATA:[dns][response_code]})\t(?:-|%{BRO_BOOL:[zeek][dns][AA]})\t(?:-|%{BRO_BOOL:[zeek][dns][TC]})\t(?:-|%{BRO_BOOL:[zeek][dns][RD]})\t(?:-|%{BRO_BOOL:[zeek][dns][RA]})\t(?:-|%{NONNEGINT:[zeek][dns][Z]:int})\t(?:-|%{BRO_DATA:[zeek][dns][answers]})\t(?:-|%{DATA:[zeek][dns][TTLs]})\t(?:-|%{BRO_BOOL:[zeek][dns][rejected]}) 14 | 15 | # conn.log - old bro, also supports 'newer' format (optional *zeek.connection.local_resp* flag) compared to non-ecs mode 16 | BRO_CONN %{NUMBER:timestamp}\t%{NOTSPACE:[zeek][session_id]}\t%{IP:[source][ip]}\t%{INT:[source][port]:int}\t%{IP:[destination][ip]}\t%{INT:[destination][port]:int}\t%{WORD:[network][transport]}\t(?:-|%{BRO_DATA:[network][protocol]})\t(?:-|%{NUMBER:[zeek][connection][duration]:float})\t(?:-|%{INT:[zeek][connection][orig_bytes]:int})\t(?:-|%{INT:[zeek][connection][resp_bytes]:int})\t(?:-|%{BRO_DATA:[zeek][connection][state]})\t(?:-|%{BRO_BOOL:[zeek][connection][local_orig]})\t(?:(?:-|%{BRO_BOOL:[zeek][connection][local_resp]})\t)?(?:-|%{INT:[zeek][connection][missed_bytes]:int})\t(?:-|%{BRO_DATA:[zeek][connection][history]})\t(?:-|%{INT:[source][packets]:int})\t(?:-|%{INT:[source][bytes]:int})\t(?:-|%{INT:[destination][packets]:int})\t(?:-|%{INT:[destination][bytes]:int})\t(?:\(empty\)|%{BRO_DATA:[zeek][connection][tunnel_parents]}) 17 | # :long - %{INT:[zeek][connection][orig_bytes]:int} 18 | # :long - %{INT:[zeek][connection][resp_bytes]:int} 19 | # :long - %{INT:[zeek][connection][missed_bytes]:int} 20 | # :long - %{INT:[source][packets]:int} 21 | # :long - %{INT:[source][bytes]:int} 22 | # :long - %{INT:[destination][packets]:int} 23 | # :long - %{INT:[destination][bytes]:int} 24 | 25 | # files.log - old format 26 | BRO_FILES %{NUMBER:timestamp}\t%{NOTSPACE:[zeek][files][fuid]}\t(?:-|%{IP:[server][ip]})\t(?:-|%{IP:[client][ip]})\t(?:-|%{BRO_DATA:[zeek][files][session_ids]})\t(?:-|%{BRO_DATA:[zeek][files][source]})\t(?:-|%{INT:[zeek][files][depth]:int})\t(?:-|%{BRO_DATA:[zeek][files][analyzers]})\t(?:-|%{BRO_DATA:[file][mime_type]})\t(?:-|%{BRO_DATA:[file][name]})\t(?:-|%{NUMBER:[zeek][files][duration]:float})\t(?:-|%{BRO_DATA:[zeek][files][local_orig]})\t(?:-|%{BRO_BOOL:[zeek][files][is_orig]})\t(?:-|%{INT:[zeek][files][seen_bytes]:int})\t(?:-|%{INT:[file][size]:int})\t(?:-|%{INT:[zeek][files][missing_bytes]:int})\t(?:-|%{INT:[zeek][files][overflow_bytes]:int})\t(?:-|%{BRO_BOOL:[zeek][files][timedout]})\t(?:-|%{BRO_DATA:[zeek][files][parent_fuid]})\t(?:-|%{BRO_DATA:[file][hash][md5]})\t(?:-|%{BRO_DATA:[file][hash][sha1]})\t(?:-|%{BRO_DATA:[file][hash][sha256]})\t(?:-|%{BRO_DATA:[zeek][files][extracted]}) 27 | # :long - %{INT:[zeek][files][seen_bytes]:int} 28 | # :long - %{INT:[file][size]:int} 29 | # :long - %{INT:[zeek][files][missing_bytes]:int} 30 | # :long - %{INT:[zeek][files][overflow_bytes]:int} 31 | -------------------------------------------------------------------------------- /public/patterns/aws: -------------------------------------------------------------------------------- 1 | S3_REQUEST_LINE (?:%{WORD:[http][request][method]} %{NOTSPACE:[url][original]}(?: HTTP/%{NUMBER:[http][version]})?) 2 | 3 | S3_ACCESS_LOG %{WORD:[aws][s3access][bucket_owner]} %{NOTSPACE:[aws][s3access][bucket]} \[%{HTTPDATE:timestamp}\] (?:-|%{IP:[client][ip]}) (?:-|%{NOTSPACE:[client][user][id]}) %{NOTSPACE:[aws][s3access][request_id]} %{NOTSPACE:[aws][s3access][operation]} (?:-|%{NOTSPACE:[aws][s3access][key]}) (?:-|"%{S3_REQUEST_LINE:[aws][s3access][request_uri]}") (?:-|%{INT:[http][response][status_code]:int}) (?:-|%{NOTSPACE:[aws][s3access][error_code]}) (?:-|%{INT:[aws][s3access][bytes_sent]:int}) (?:-|%{INT:[aws][s3access][object_size]:int}) (?:-|%{INT:[aws][s3access][total_time]:int}) (?:-|%{INT:[aws][s3access][turn_around_time]:int}) "(?:-|%{DATA:[http][request][referrer]})" "(?:-|%{DATA:[user_agent][original]})" (?:-|%{NOTSPACE:[aws][s3access][version_id]})(?: (?:-|%{NOTSPACE:[aws][s3access][host_id]}) (?:-|%{NOTSPACE:[aws][s3access][signature_version]}) (?:-|%{NOTSPACE:[tls][cipher]}) (?:-|%{NOTSPACE:[aws][s3access][authentication_type]}) (?:-|%{NOTSPACE:[aws][s3access][host_header]}) (?:-|%{NOTSPACE:[aws][s3access][tls_version]}))? 4 | # :long - %{INT:[aws][s3access][bytes_sent]:int} 5 | # :long - %{INT:[aws][s3access][object_size]:int} 6 | 7 | ELB_URIHOST %{IPORHOST:[url][domain]}(?::%{POSINT:[url][port]:int})? 8 | ELB_URIPATHQUERY %{URIPATH:[url][path]}(?:\?%{URIQUERY:[url][query]})? 9 | # deprecated - old name: 10 | ELB_URIPATHPARAM %{ELB_URIPATHQUERY} 11 | ELB_URI %{URIPROTO:[url][scheme]}://(?:%{USER:[url][username]}(?::[^@]*)?@)?(?:%{ELB_URIHOST})?(?:%{ELB_URIPATHQUERY})? 12 | 13 | ELB_REQUEST_LINE (?:%{WORD:[http][request][method]} %{ELB_URI:[url][original]}(?: HTTP/%{NUMBER:[http][version]})?) 14 | 15 | # pattern supports 'regular' HTTP ELB format 16 | ELB_V1_HTTP_LOG %{TIMESTAMP_ISO8601:timestamp} %{NOTSPACE:[aws][elb][name]} %{IP:[source][ip]}:%{INT:[source][port]:int} (?:-|(?:%{IP:[aws][elb][backend][ip]}:%{INT:[aws][elb][backend][port]:int})) (?:-1|%{NUMBER:[aws][elb][request_processing_time][sec]:float}) (?:-1|%{NUMBER:[aws][elb][backend_processing_time][sec]:float}) (?:-1|%{NUMBER:[aws][elb][response_processing_time][sec]:float}) %{INT:[http][response][status_code]:int} (?:-|%{INT:[aws][elb][backend][http][response][status_code]:int}) %{INT:[http][request][body][bytes]:int} %{INT:[http][response][body][bytes]:int} "%{ELB_REQUEST_LINE}"(?: "(?:-|%{DATA:[user_agent][original]})" (?:-|%{NOTSPACE:[tls][cipher]}) (?:-|%{NOTSPACE:[aws][elb][ssl_protocol]}))? 17 | # :long - %{INT:[http][request][body][bytes]:int} 18 | # :long - %{INT:[http][response][body][bytes]:int} 19 | 20 | ELB_ACCESS_LOG %{ELB_V1_HTTP_LOG} 21 | 22 | # Each edge location is identified by a three-letter code and an arbitrarily assigned number. 23 | # The three-letter IATA code typically represents an airport near the edge location. 24 | # examples: "LHR62-C2", "SFO5-P1", ""IND6", "CPT50" 25 | CLOUDFRONT_EDGE_LOCATION [A-Z]{3}[0-9]{1,2}(?:-[A-Z0-9]{2})? 26 | 27 | # pattern used to match a shorted format, that's why we have the optional part (starting with *http.version*) at the end 28 | CLOUDFRONT_ACCESS_LOG (?%{YEAR}-%{MONTHNUM}-%{MONTHDAY}\t%{TIME})\t%{CLOUDFRONT_EDGE_LOCATION:[aws][cloudfront][x_edge_location]}\t(?:-|%{INT:[destination][bytes]:int})\t%{IPORHOST:[source][ip]}\t%{WORD:[http][request][method]}\t%{HOSTNAME:[url][domain]}\t%{NOTSPACE:[url][path]}\t(?:(?:000)|%{INT:[http][response][status_code]:int})\t(?:-|%{DATA:[http][request][referrer]})\t%{DATA:[user_agent][original]}\t(?:-|%{DATA:[url][query]})\t(?:-|%{DATA:[aws][cloudfront][http][request][cookie]})\t%{WORD:[aws][cloudfront][x_edge_result_type]}\t%{NOTSPACE:[aws][cloudfront][x_edge_request_id]}\t%{HOSTNAME:[aws][cloudfront][http][request][host]}\t%{URIPROTO:[network][protocol]}\t(?:-|%{INT:[source][bytes]:int})\t%{NUMBER:[aws][cloudfront][time_taken]:float}\t(?:-|%{IP:[network][forwarded_ip]})\t(?:-|%{DATA:[aws][cloudfront][ssl_protocol]})\t(?:-|%{NOTSPACE:[tls][cipher]})\t%{WORD:[aws][cloudfront][x_edge_response_result_type]}(?:\t(?:-|HTTP/%{NUMBER:[http][version]})\t(?:-|%{DATA:[aws][cloudfront][fle_status]})\t(?:-|%{DATA:[aws][cloudfront][fle_encrypted_fields]})\t%{INT:[source][port]:int}\t%{NUMBER:[aws][cloudfront][time_to_first_byte]:float}\t(?:-|%{DATA:[aws][cloudfront][x_edge_detailed_result_type]})\t(?:-|%{NOTSPACE:[http][request][mime_type]})\t(?:-|%{INT:[aws][cloudfront][http][request][size]:int})\t(?:-|%{INT:[aws][cloudfront][http][request][range][start]:int})\t(?:-|%{INT:[aws][cloudfront][http][request][range][end]:int}))? 29 | # :long - %{INT:[destination][bytes]:int} 30 | # :long - %{INT:[source][bytes]:int} 31 | # :long - %{INT:[aws][cloudfront][http][request][size]:int} 32 | # :long - %{INT:[aws][cloudfront][http][request][range][start]:int} 33 | # :long - %{INT:[aws][cloudfront][http][request][range][end]:int} 34 | -------------------------------------------------------------------------------- /src/components/MorePatternsModal.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { DownloadCloud, Trash2, X, XOctagon } from "react-feather"; 3 | 4 | export const MorePatternsModal = ({ setShowModal, collections, setCollections, patterns, setPatterns, groks }) => { 5 | const urlRegex = 6 | /(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; 7 | const titleRegex = /^[\w\d _-]{1,20}/; 8 | 9 | const [url, setUrl] = useState(""); 10 | const [title, setTitle] = useState(""); 11 | const [errorMessage, setErrorMessage] = useState(""); 12 | 13 | const handleSubmit = async (e) => { 14 | // Validation 15 | e.preventDefault(); 16 | setErrorMessage(""); 17 | if (!urlRegex.test(url)) return setErrorMessage("URL is not valid"); 18 | if (!titleRegex.test(title)) 19 | return setErrorMessage("Title can only contain letters, numbers, spaces, underscores, and dashes."); 20 | if (collections.map((c) => c.label).includes(title)) 21 | return setErrorMessage("This title is already assigned to a set. Choose another."); 22 | const random = (Math.random() + 1).toString(36).substring(7); 23 | 24 | // Attempt to load pattern 25 | try { 26 | const newPatterns = await groks.load(url).then((ids) => { 27 | return ids.map((id) => { 28 | return { id, collection: random }; 29 | }); 30 | }); 31 | if (!newPatterns.length) 32 | return setErrorMessage("Error loading pattern set. Make sure the url and format of set is correct."); 33 | setPatterns((patterns) => [...patterns, ...newPatterns.flat()]); 34 | const updatedCollection = [...collections, { value: random, label: title, url, active: true }].sort( 35 | (a, b) => a.value > b.value 36 | ); 37 | setCollections(updatedCollection); 38 | } catch (err) { 39 | console.log(err); 40 | setErrorMessage("Error loading pattern set"); 41 | } 42 | }; 43 | 44 | const handleDelete = (value) => { 45 | setCollections(collections.filter((c) => c.value !== value)); 46 | setPatterns(patterns.filter((p) => p.collection !== value)); 47 | }; 48 | 49 | return ( 50 |
51 |
52 |
53 |

Download Pattern Set from URL

54 | setShowModal(null)} /> 55 |
56 |
57 |

58 | This will make a request to the URL inputted below and attempt to load the patterns from the repsonse. See 59 | the 60 | 61 | {" "} 62 | pattern repository 63 | {" "} 64 | for example files. 65 |

66 |
67 | {errorMessage && ( 68 |
69 | 70 | {errorMessage} 71 |
72 | )} 73 | setUrl(e.target.value)} 80 | /> 81 | setTitle(e.target.value)} 89 | /> 90 |
91 |
92 | 96 |
97 | {!!collections.filter((c) => c.url).length && ( 98 | <> 99 |
100 |
101 |

Downloaded Sets

102 |
103 | {collections 104 | .filter((c) => c.url) 105 | .map((c) => { 106 | return ( 107 |
108 |
{c.label}
109 |
handleDelete(c.value)}> 110 | 111 |
112 |
113 | ); 114 | })} 115 |
116 |
117 | 118 | )} 119 |
120 |
121 |
122 | ); 123 | }; 124 | -------------------------------------------------------------------------------- /public/patterns/zeek: -------------------------------------------------------------------------------- 1 | # updated Zeek log matching, for legacy matching see the patters/ecs-v1/bro 2 | 3 | ZEEK_BOOL [TF] 4 | ZEEK_DATA [^\t]+ 5 | 6 | # http.log - the 'new' format (compared to BRO_HTTP) 7 | # has *version* and *origin* fields added and *filename* replaced with *orig_filenames* + *resp_filenames* 8 | ZEEK_HTTP %{NUMBER:timestamp}\t%{NOTSPACE:[zeek][session_id]}\t%{IP:[source][ip]}\t%{INT:[source][port]:int}\t%{IP:[destination][ip]}\t%{INT:[destination][port]:int}\t%{INT:[zeek][http][trans_depth]:int}\t(?:-|%{WORD:[http][request][method]})\t(?:-|%{ZEEK_DATA:[url][domain]})\t(?:-|%{ZEEK_DATA:[url][original]})\t(?:-|%{ZEEK_DATA:[http][request][referrer]})\t(?:-|%{NUMBER:[http][version]})\t(?:-|%{ZEEK_DATA:[user_agent][original]})\t(?:-|%{ZEEK_DATA:[zeek][http][origin]})\t(?:-|%{NUMBER:[http][request][body][bytes]:int})\t(?:-|%{NUMBER:[http][response][body][bytes]:int})\t(?:-|%{POSINT:[http][response][status_code]:int})\t(?:-|%{DATA:[zeek][http][status_msg]})\t(?:-|%{POSINT:[zeek][http][info_code]:int})\t(?:-|%{DATA:[zeek][http][info_msg]})\t(?:\(empty\)|%{ZEEK_DATA:[zeek][http][tags]})\t(?:-|%{ZEEK_DATA:[url][username]})\t(?:-|%{ZEEK_DATA:[url][password]})\t(?:-|%{ZEEK_DATA:[zeek][http][proxied]})\t(?:-|%{ZEEK_DATA:[zeek][http][orig_fuids]})\t(?:-|%{ZEEK_DATA:[zeek][http][orig_filenames]})\t(?:-|%{ZEEK_DATA:[http][request][mime_type]})\t(?:-|%{ZEEK_DATA:[zeek][http][resp_fuids]})\t(?:-|%{ZEEK_DATA:[zeek][http][resp_filenames]})\t(?:-|%{ZEEK_DATA:[http][response][mime_type]}) 9 | # :long - %{NUMBER:[http][request][body][bytes]:int} 10 | # :long - %{NUMBER:[http][response][body][bytes]:int} 11 | 12 | # dns.log - 'updated' BRO_DNS format (added *zeek.dns.rtt*) 13 | ZEEK_DNS %{NUMBER:timestamp}\t%{NOTSPACE:[zeek][session_id]}\t%{IP:[source][ip]}\t%{INT:[source][port]:int}\t%{IP:[destination][ip]}\t%{INT:[destination][port]:int}\t%{WORD:[network][transport]}\t(?:-|%{INT:[dns][id]:int})\t(?:-|%{NUMBER:[zeek][dns][rtt]:float})\t(?:-|%{ZEEK_DATA:[dns][question][name]})\t(?:-|%{INT:[zeek][dns][qclass]:int})\t(?:-|%{ZEEK_DATA:[zeek][dns][qclass_name]})\t(?:-|%{INT:[zeek][dns][qtype]:int})\t(?:-|%{ZEEK_DATA:[dns][question][type]})\t(?:-|%{INT:[zeek][dns][rcode]:int})\t(?:-|%{ZEEK_DATA:[dns][response_code]})\t%{ZEEK_BOOL:[zeek][dns][AA]}\t%{ZEEK_BOOL:[zeek][dns][TC]}\t%{ZEEK_BOOL:[zeek][dns][RD]}\t%{ZEEK_BOOL:[zeek][dns][RA]}\t%{NONNEGINT:[zeek][dns][Z]:int}\t(?:-|%{ZEEK_DATA:[zeek][dns][answers]})\t(?:-|%{DATA:[zeek][dns][TTLs]})\t(?:-|%{ZEEK_BOOL:[zeek][dns][rejected]}) 14 | 15 | # conn.log - the 'new' format (requires *zeek.connection.local_resp*, handles `(empty)` as `-` for tunnel_parents, and optional mac adresses) 16 | ZEEK_CONN %{NUMBER:timestamp}\t%{NOTSPACE:[zeek][session_id]}\t%{IP:[source][ip]}\t%{INT:[source][port]:int}\t%{IP:[destination][ip]}\t%{INT:[destination][port]:int}\t%{WORD:[network][transport]}\t(?:-|%{ZEEK_DATA:[network][protocol]})\t(?:-|%{NUMBER:[zeek][connection][duration]:float})\t(?:-|%{INT:[zeek][connection][orig_bytes]:int})\t(?:-|%{INT:[zeek][connection][resp_bytes]:int})\t(?:-|%{ZEEK_DATA:[zeek][connection][state]})\t(?:-|%{ZEEK_BOOL:[zeek][connection][local_orig]})\t(?:-|%{ZEEK_BOOL:[zeek][connection][local_resp]})\t(?:-|%{INT:[zeek][connection][missed_bytes]:int})\t(?:-|%{ZEEK_DATA:[zeek][connection][history]})\t(?:-|%{INT:[source][packets]:int})\t(?:-|%{INT:[source][bytes]:int})\t(?:-|%{INT:[destination][packets]:int})\t(?:-|%{INT:[destination][bytes]:int})\t(?:-|%{ZEEK_DATA:[zeek][connection][tunnel_parents]})(?:\t(?:-|%{COMMONMAC:[source][mac]})\t(?:-|%{COMMONMAC:[destination][mac]}))? 17 | # :long - %{INT:[zeek][connection][orig_bytes]:int} 18 | # :long - %{INT:[zeek][connection][resp_bytes]:int} 19 | # :long - %{INT:[zeek][connection][missed_bytes]:int} 20 | # :long - %{INT:[source][packets]:int} 21 | # :long - %{INT:[source][bytes]:int} 22 | # :long - %{INT:[destination][packets]:int} 23 | # :long - %{INT:[destination][bytes]:int} 24 | 25 | # files.log - updated BRO_FILES format (2 new fields added at the end) 26 | ZEEK_FILES_TX_HOSTS (?:-|%{IP:[server][ip]})|(?<[zeek][files][tx_hosts]>%{IP:[server][ip]}(?:[\s,]%{IP})+) 27 | ZEEK_FILES_RX_HOSTS (?:-|%{IP:[client][ip]})|(?<[zeek][files][rx_hosts]>%{IP:[client][ip]}(?:[\s,]%{IP})+) 28 | ZEEK_FILES %{NUMBER:timestamp}\t%{NOTSPACE:[zeek][files][fuid]}\t%{ZEEK_FILES_TX_HOSTS}\t%{ZEEK_FILES_RX_HOSTS}\t(?:-|%{ZEEK_DATA:[zeek][files][session_ids]})\t(?:-|%{ZEEK_DATA:[zeek][files][source]})\t(?:-|%{INT:[zeek][files][depth]:int})\t(?:-|%{ZEEK_DATA:[zeek][files][analyzers]})\t(?:-|%{ZEEK_DATA:[file][mime_type]})\t(?:-|%{ZEEK_DATA:[file][name]})\t(?:-|%{NUMBER:[zeek][files][duration]:float})\t(?:-|%{ZEEK_DATA:[zeek][files][local_orig]})\t(?:-|%{ZEEK_BOOL:[zeek][files][is_orig]})\t(?:-|%{INT:[zeek][files][seen_bytes]:int})\t(?:-|%{INT:[file][size]:int})\t(?:-|%{INT:[zeek][files][missing_bytes]:int})\t(?:-|%{INT:[zeek][files][overflow_bytes]:int})\t(?:-|%{ZEEK_BOOL:[zeek][files][timedout]})\t(?:-|%{ZEEK_DATA:[zeek][files][parent_fuid]})\t(?:-|%{ZEEK_DATA:[file][hash][md5]})\t(?:-|%{ZEEK_DATA:[file][hash][sha1]})\t(?:-|%{ZEEK_DATA:[file][hash][sha256]})\t(?:-|%{ZEEK_DATA:[zeek][files][extracted]})(?:\t(?:-|%{ZEEK_BOOL:[zeek][files][extracted_cutoff]})\t(?:-|%{INT:[zeek][files][extracted_size]:int}))? 29 | # :long - %{INT:[zeek][files][seen_bytes]:int} 30 | # :long - %{INT:[file][size]:int} 31 | # :long - %{INT:[zeek][files][missing_bytes]:int} 32 | # :long - %{INT:[zeek][files][overflow_bytes]:int} 33 | # :long - %{INT:[zeek][files][extracted_size]:int} 34 | -------------------------------------------------------------------------------- /public/patterns/grok-patterns: -------------------------------------------------------------------------------- 1 | USERNAME [a-zA-Z0-9._-]+ 2 | USER %{USERNAME} 3 | EMAILLOCALPART [a-zA-Z0-9!#$%&'*+\-/=?^_`{|}~]{1,64}(?:\.[a-zA-Z0-9!#$%&'*+\-/=?^_`{|}~]{1,62}){0,63} 4 | EMAILADDRESS %{EMAILLOCALPART}@%{HOSTNAME} 5 | INT (?:[+-]?(?:[0-9]+)) 6 | BASE10NUM (?[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+))) 7 | NUMBER (?:%{BASE10NUM}) 8 | BASE16NUM (?(?"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``)) 19 | UUID [A-Fa-f0-9]{8}-(?:[A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12} 20 | # URN, allowing use of RFC 2141 section 2.3 reserved characters 21 | URN urn:[0-9A-Za-z][0-9A-Za-z-]{0,31}:(?:%[0-9a-fA-F]{2}|[0-9A-Za-z()+,.:=@;$_!*'/?#-])+ 22 | 23 | # Networking 24 | MAC (?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC}) 25 | CISCOMAC (?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4}) 26 | WINDOWSMAC (?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2}) 27 | COMMONMAC (?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}) 28 | IPV6 ((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)? 29 | IPV4 (?[A-Za-z]+:|\\)(?:\\[^\\?*]*)+ 40 | URIPROTO [A-Za-z]([A-Za-z0-9+\-.]+)+ 41 | URIHOST %{IPORHOST}(?::%{POSINT})? 42 | # uripath comes loosely from RFC1738, but mostly from what Firefox doesn't turn into %XX 43 | URIPATH (?:/[A-Za-z0-9$.+!*'(){},~:;=@#%&_\-]*)+ 44 | URIQUERY [A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]<>]* 45 | # deprecated (kept due compatibility): 46 | URIPARAM \?%{URIQUERY} 47 | URIPATHPARAM %{URIPATH}(?:\?%{URIQUERY})? 48 | URI %{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATH}(?:\?%{URIQUERY})?)? 49 | 50 | # Months: January, Feb, 3, 03, 12, December 51 | MONTH \b(?:[Jj]an(?:uary|uar)?|[Ff]eb(?:ruary|ruar)?|[Mm](?:a|ä)?r(?:ch|z)?|[Aa]pr(?:il)?|[Mm]a(?:y|i)?|[Jj]un(?:e|i)?|[Jj]ul(?:y|i)?|[Aa]ug(?:ust)?|[Ss]ep(?:tember)?|[Oo](?:c|k)?t(?:ober)?|[Nn]ov(?:ember)?|[Dd]e(?:c|z)(?:ember)?)\b 52 | MONTHNUM (?:0?[1-9]|1[0-2]) 53 | MONTHNUM2 (?:0[1-9]|1[0-2]) 54 | MONTHDAY (?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9]) 55 | 56 | # Days: Monday, Tue, Thu, etc... 57 | DAY (?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?) 58 | 59 | # Years? 60 | YEAR (?>\d\d){1,2} 61 | HOUR (?:2[0123]|[01]?[0-9]) 62 | MINUTE (?:[0-5][0-9]) 63 | # '60' is a leap second in most time standards and thus is valid. 64 | SECOND (?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?) 65 | TIME (?!<[0-9])%{HOUR}:%{MINUTE}(?::%{SECOND})(?![0-9]) 66 | # datestamp is YYYY/MM/DD-HH:MM:SS.UUUU (or something like it) 67 | DATE_US %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR} 68 | DATE_EU %{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR} 69 | ISO8601_TIMEZONE (?:Z|[+-]%{HOUR}(?::?%{MINUTE})) 70 | ISO8601_SECOND %{SECOND} 71 | TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}? 72 | DATE %{DATE_US}|%{DATE_EU} 73 | DATESTAMP %{DATE}[- ]%{TIME} 74 | TZ (?:[APMCE][SD]T|UTC) 75 | DATESTAMP_RFC822 %{DAY} %{MONTH} %{MONTHDAY} %{YEAR} %{TIME} %{TZ} 76 | DATESTAMP_RFC2822 %{DAY}, %{MONTHDAY} %{MONTH} %{YEAR} %{TIME} %{ISO8601_TIMEZONE} 77 | DATESTAMP_OTHER %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{TZ} %{YEAR} 78 | DATESTAMP_EVENTLOG %{YEAR}%{MONTHNUM2}%{MONTHDAY}%{HOUR}%{MINUTE}%{SECOND} 79 | 80 | # Syslog Dates: Month Day HH:MM:SS 81 | SYSLOGTIMESTAMP %{MONTH} +%{MONTHDAY} %{TIME} 82 | PROG [\x21-\x5a\x5c\x5e-\x7e]+ 83 | SYSLOGPROG %{PROG:[process][name]}(?:\[%{POSINT:[process][pid]:int}\])? 84 | SYSLOGHOST %{IPORHOST} 85 | SYSLOGFACILITY <%{NONNEGINT:[log][syslog][facility][code]:int}.%{NONNEGINT:[log][syslog][priority]:int}> 86 | HTTPDATE %{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{INT} 87 | 88 | # Shortcuts 89 | QS %{QUOTEDSTRING} 90 | 91 | # Log formats 92 | SYSLOGBASE %{SYSLOGTIMESTAMP:timestamp} (?:%{SYSLOGFACILITY} )?%{SYSLOGHOST:[host][hostname]} %{SYSLOGPROG}: 93 | 94 | # Log Levels 95 | LOGLEVEL ([Aa]lert|ALERT|[Tt]race|TRACE|[Dd]ebug|DEBUG|[Nn]otice|NOTICE|[Ii]nfo?(?:rmation)?|INFO?(?:RMATION)?|[Ww]arn?(?:ing)?|WARN?(?:ING)?|[Ee]rr?(?:or)?|ERR?(?:OR)?|[Cc]rit?(?:ical)?|CRIT?(?:ICAL)?|[Ff]atal|FATAL|[Ss]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?) 96 | -------------------------------------------------------------------------------- /public/patterns/bacula: -------------------------------------------------------------------------------- 1 | BACULA_TIMESTAMP %{MONTHDAY}-%{MONTH}(?:-%{YEAR})? %{HOUR}:%{MINUTE} 2 | BACULA_HOST %{HOSTNAME} 3 | BACULA_VOLUME %{USER} 4 | BACULA_DEVICE %{USER} 5 | BACULA_DEVICEPATH %{UNIXPATH} 6 | BACULA_CAPACITY %{INT}{1,3}(,%{INT}{3})* 7 | BACULA_VERSION %{USER} 8 | BACULA_JOB %{USER} 9 | 10 | BACULA_LOG_MAX_CAPACITY User defined maximum volume capacity %{BACULA_CAPACITY:[bacula][volume][max_capacity]} exceeded on device \"%{BACULA_DEVICE:[bacula][volume][device]}\" \(%{BACULA_DEVICEPATH:[bacula][volume][path]}\).? 11 | BACULA_LOG_END_VOLUME End of medium on Volume \"%{BACULA_VOLUME:[bacula][volume][name]}\" Bytes=%{BACULA_CAPACITY:[bacula][volume][bytes]} Blocks=%{BACULA_CAPACITY:[bacula][volume][blocks]} at %{BACULA_TIMESTAMP:[bacula][timestamp]}. 12 | BACULA_LOG_NEW_VOLUME Created new Volume \"%{BACULA_VOLUME:[bacula][volume][name]}\" in catalog. 13 | BACULA_LOG_NEW_LABEL Labeled new Volume \"%{BACULA_VOLUME:[bacula][volume][name]}\" on (?:file )?device \"%{BACULA_DEVICE:[bacula][volume][device]}\" \(%{BACULA_DEVICEPATH:[bacula][volume][path]}\). 14 | BACULA_LOG_WROTE_LABEL Wrote label to prelabeled Volume \"%{BACULA_VOLUME:[bacula][volume][name]}\" on device \"%{BACULA_DEVICE:[bacula][volume][device]}\" \(%{BACULA_DEVICEPATH:[bacula][volume][path]}\) 15 | BACULA_LOG_NEW_MOUNT New volume \"%{BACULA_VOLUME:[bacula][volume][name]}\" mounted on device \"%{BACULA_DEVICE:[bacula][volume][device]}\" \(%{BACULA_DEVICEPATH:[bacula][volume][path]}\) at %{BACULA_TIMESTAMP:[bacula][timestamp]}. 16 | BACULA_LOG_NOOPEN \s*Cannot open %{DATA}: ERR=%{GREEDYDATA:[error][message]} 17 | BACULA_LOG_NOOPENDIR \s*Could not open directory \"?%{DATA:[file][path]}\"?: ERR=%{GREEDYDATA:[error][message]} 18 | BACULA_LOG_NOSTAT \s*Could not stat %{DATA:[file][path]}: ERR=%{GREEDYDATA:[error][message]} 19 | BACULA_LOG_NOJOBS There are no more Jobs associated with Volume \"%{BACULA_VOLUME:[bacula][volume][name]}\". Marking it purged. 20 | BACULA_LOG_ALL_RECORDS_PRUNED .*?All records pruned from Volume \"%{BACULA_VOLUME:[bacula][volume][name]}\"; marking it \"Purged\" 21 | BACULA_LOG_BEGIN_PRUNE_JOBS Begin pruning Jobs older than %{INT} month %{INT} days . 22 | BACULA_LOG_BEGIN_PRUNE_FILES Begin pruning Files. 23 | BACULA_LOG_PRUNED_JOBS Pruned %{INT} Jobs* for client %{BACULA_HOST:[bacula][client][name]} from catalog. 24 | BACULA_LOG_PRUNED_FILES Pruned Files from %{INT} Jobs* for client %{BACULA_HOST:[bacula][client][name]} from catalog. 25 | BACULA_LOG_ENDPRUNE End auto prune. 26 | BACULA_LOG_STARTJOB Start Backup JobId %{INT}, Job=%{BACULA_JOB:[bacula][job][name]} 27 | BACULA_LOG_STARTRESTORE Start Restore Job %{BACULA_JOB:[bacula][job][name]} 28 | BACULA_LOG_USEDEVICE Using Device \"%{BACULA_DEVICE:[bacula][volume][device]}\" 29 | BACULA_LOG_DIFF_FS \s*%{UNIXPATH} is a different filesystem. Will not descend from %{UNIXPATH} into it. 30 | BACULA_LOG_JOBEND Job write elapsed time = %{DATA:[bacula][job][elapsed_time]}, Transfer rate = %{NUMBER} (K|M|G)? Bytes/second 31 | BACULA_LOG_NOPRUNE_JOBS No Jobs found to prune. 32 | BACULA_LOG_NOPRUNE_FILES No Files found to prune. 33 | BACULA_LOG_VOLUME_PREVWRITTEN Volume \"?%{BACULA_VOLUME:[bacula][volume][name]}\"? previously written, moving to end of data. 34 | BACULA_LOG_READYAPPEND Ready to append to end of Volume \"%{BACULA_VOLUME:[bacula][volume][name]}\" size=%{INT:[bacula][volume][size]:int} 35 | # :long - %{INT:[bacula][volume][size]:int} 36 | BACULA_LOG_CANCELLING Cancelling duplicate JobId=%{INT:[bacula][job][other_id]}. 37 | BACULA_LOG_MARKCANCEL JobId %{INT:[bacula][job][id]}, Job %{BACULA_JOB:[bacula][job][name]} marked to be canceled. 38 | BACULA_LOG_CLIENT_RBJ shell command: run ClientRunBeforeJob \"%{GREEDYDATA:[bacula][job][client_run_before_command]}\" 39 | BACULA_LOG_VSS (Generate )?VSS (Writer)? 40 | BACULA_LOG_MAXSTART Fatal [eE]rror: Job canceled because max start delay time exceeded. 41 | BACULA_LOG_DUPLICATE Fatal [eE]rror: JobId %{INT:[bacula][job][other_id]} already running. Duplicate job not allowed. 42 | BACULA_LOG_NOJOBSTAT Fatal [eE]rror: No Job status returned from FD. 43 | BACULA_LOG_FATAL_CONN Fatal [eE]rror: bsock.c:133 Unable to connect to (Client: %{BACULA_HOST:[bacula][client][name]}|Storage daemon) on %{IPORHOST:[client][address]}:%{POSINT:[client][port]:int}. ERR=%{GREEDYDATA:[error][message]} 44 | BACULA_LOG_NO_CONNECT Warning: bsock.c:127 Could not connect to (Client: %{BACULA_HOST:[bacula][client][name]}|Storage daemon) on %{IPORHOST:[client][address]}:%{POSINT:[client][port]:int}. ERR=%{GREEDYDATA:[error][message]} 45 | BACULA_LOG_NO_AUTH Fatal error: Unable to authenticate with File daemon at \"?%{IPORHOST:[client][address]}(?::%{POSINT:[client][port]:int})?\"?. Possible causes: 46 | BACULA_LOG_NOSUIT No prior or suitable Full backup found in catalog. Doing FULL backup. 47 | BACULA_LOG_NOPRIOR No prior Full backup Job record found. 48 | 49 | BACULA_LOG_JOB (Error: )?Bacula %{BACULA_HOST} %{BACULA_VERSION} \(%{BACULA_VERSION}\): 50 | 51 | BACULA_LOG %{BACULA_TIMESTAMP:timestamp} %{BACULA_HOST:[host][hostname]}(?: JobId %{INT:[bacula][job][id]})?:? (%{BACULA_LOG_MAX_CAPACITY}|%{BACULA_LOG_END_VOLUME}|%{BACULA_LOG_NEW_VOLUME}|%{BACULA_LOG_NEW_LABEL}|%{BACULA_LOG_WROTE_LABEL}|%{BACULA_LOG_NEW_MOUNT}|%{BACULA_LOG_NOOPEN}|%{BACULA_LOG_NOOPENDIR}|%{BACULA_LOG_NOSTAT}|%{BACULA_LOG_NOJOBS}|%{BACULA_LOG_ALL_RECORDS_PRUNED}|%{BACULA_LOG_BEGIN_PRUNE_JOBS}|%{BACULA_LOG_BEGIN_PRUNE_FILES}|%{BACULA_LOG_PRUNED_JOBS}|%{BACULA_LOG_PRUNED_FILES}|%{BACULA_LOG_ENDPRUNE}|%{BACULA_LOG_STARTJOB}|%{BACULA_LOG_STARTRESTORE}|%{BACULA_LOG_USEDEVICE}|%{BACULA_LOG_DIFF_FS}|%{BACULA_LOG_JOBEND}|%{BACULA_LOG_NOPRUNE_JOBS}|%{BACULA_LOG_NOPRUNE_FILES}|%{BACULA_LOG_VOLUME_PREVWRITTEN}|%{BACULA_LOG_READYAPPEND}|%{BACULA_LOG_CANCELLING}|%{BACULA_LOG_MARKCANCEL}|%{BACULA_LOG_CLIENT_RBJ}|%{BACULA_LOG_VSS}|%{BACULA_LOG_MAXSTART}|%{BACULA_LOG_DUPLICATE}|%{BACULA_LOG_NOJOBSTAT}|%{BACULA_LOG_FATAL_CONN}|%{BACULA_LOG_NO_CONNECT}|%{BACULA_LOG_NO_AUTH}|%{BACULA_LOG_NOSUIT}|%{BACULA_LOG_JOB}|%{BACULA_LOG_NOPRIOR}) 52 | # old (deprecated) name : 53 | BACULA_LOGLINE %{BACULA_LOG} 54 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Work+Sans&display=swap"); 2 | @import "./codemirror/codemirror.css"; 3 | @import "../node_modules/codemirror/theme/material-darker.css"; 4 | @import "../node_modules/codemirror/addon/scroll/simplescrollbars.css"; 5 | 6 | :root { 7 | font-family: "Work Sans", sans-serif; 8 | color: #fff; 9 | --dark: #333; 10 | --light: #f0f0f0; 11 | } 12 | 13 | a { 14 | text-decoration: none; 15 | color: var(--light); 16 | } 17 | 18 | * { 19 | box-sizing: border-box; 20 | } 21 | 22 | body { 23 | padding: 0; 24 | margin: 0; 25 | background-color: #111; 26 | } 27 | 28 | h1, 29 | h2, 30 | h3, 31 | h4, 32 | h5 { 33 | margin: 0.5rem; 34 | padding: 0rem; 35 | display: block; 36 | } 37 | 38 | h3 { 39 | margin-right: 0; 40 | } 41 | 42 | td, 43 | th { 44 | height: 1rem; 45 | } 46 | 47 | ul { 48 | padding: 0 0.5rem; 49 | } 50 | 51 | li { 52 | list-style-type: none; 53 | } 54 | 55 | button { 56 | border: none; 57 | width: 100%; 58 | } 59 | 60 | input:disabled { 61 | border-color: rgba(0, 0, 0, 0.5); 62 | } 63 | 64 | .nav-links { 65 | display: flex; 66 | justify-content: flex-end; 67 | align-items: center; 68 | } 69 | 70 | .nav-links a { 71 | color: silver; 72 | margin: 0 0.5rem; 73 | padding: 0.25rem; 74 | display: flex; 75 | align-items: center; 76 | } 77 | 78 | .nav-links a:hover { 79 | color: var(--light); 80 | border-color: var(--light) !important; 81 | } 82 | 83 | .nav-links a span { 84 | margin: 0 0.25rem; 85 | } 86 | 87 | .container { 88 | display: grid; 89 | padding: 3rem 0 0 0; 90 | height: 100vh; 91 | grid-template-columns: 250px minmax(0, 4fr) minmax(0, 2fr); 92 | grid-template-areas: "menu main result"; 93 | } 94 | 95 | .menu { 96 | grid-area: "menu"; 97 | background-color: #222; 98 | padding: 0.5rem; 99 | box-shadow: 2px -2px rgba(0, 0, 0, 0.4); 100 | display: flex; 101 | flex-direction: column; 102 | justify-content: space-between; 103 | } 104 | 105 | .result { 106 | grid-area: "result"; 107 | overflow: hidden; 108 | padding: 0.5rem 0.25rem 1rem 0.25rem; 109 | } 110 | 111 | .main { 112 | grid-area: "main"; 113 | height: 100%; 114 | display: flex; 115 | flex-direction: column; 116 | position: relative; 117 | overflow: hidden; 118 | padding: 0.5rem 0.25rem 1rem 0.25rem; 119 | } 120 | 121 | .samples-wrapper { 122 | display: flex; 123 | flex-direction: column; 124 | position: relative; 125 | height: 100%; 126 | width: 100%; 127 | padding: 0.5rem 0.5rem 0 0.5rem; 128 | overflow: hidden; 129 | } 130 | 131 | .samples-wrapper > * { 132 | position: relative; 133 | overflow: hidden; 134 | } 135 | 136 | .output-top { 137 | display: flex; 138 | flex-direction: row; 139 | justify-content: space-between; 140 | align-items: center; 141 | padding-right: 0.5rem; 142 | } 143 | 144 | .counter { 145 | justify-self: flex-end; 146 | font-size: 1.2rem; 147 | display: flex; 148 | align-items: center; 149 | justify-content: center; 150 | } 151 | 152 | .counter.all-match { 153 | color: #93eea8; 154 | } 155 | 156 | .counter.no-match { 157 | color: #f78c6c; 158 | } 159 | 160 | /* MODAL */ 161 | 162 | .modal { 163 | background-color: rgba(255, 255, 255, 0.3); 164 | position: fixed; 165 | z-index: 3; 166 | display: flex; 167 | align-items: flex-start; 168 | justify-content: center; 169 | width: 100%; 170 | height: 100%; 171 | padding-top: 5vh; 172 | top: 0; 173 | left: 0; 174 | } 175 | 176 | .modal-container { 177 | background-color: #222; 178 | padding: 1rem; 179 | border: 1px solid siver; 180 | box-shadow: 3px 3px rgba(0, 0, 0, 0.6); 181 | display: flex; 182 | flex-direction: column; 183 | border-radius: 5px; 184 | width: 50vw; 185 | } 186 | 187 | .modal-header { 188 | margin-top: 0; 189 | margin-bottom: 1rem; 190 | padding-bottom: 0.5rem; 191 | border-bottom: 1px solid #444; 192 | display: flex; 193 | justify-content: space-between; 194 | align-items: flex-start; 195 | } 196 | 197 | .modal-header h3 { 198 | margin: 0 0 0 0.5rem; 199 | } 200 | 201 | .modal-header svg { 202 | color: silver; 203 | } 204 | 205 | .modal-header svg:hover { 206 | color: #fff; 207 | cursor: pointer; 208 | } 209 | 210 | .grid-body { 211 | max-height: 75vh; 212 | overflow-y: auto; 213 | } 214 | 215 | .modal-content input { 216 | border-radius: 5px; 217 | font-size: 1rem; 218 | padding: 0.5rem; 219 | width: 100%; 220 | } 221 | 222 | .modal-footer { 223 | margin-top: 1rem; 224 | } 225 | 226 | .notification { 227 | display: flex; 228 | align-items: center; 229 | background-color: salmon; 230 | box-shadow: 2px 2px rgba(0, 0, 0, 0.6); 231 | width: 100%; 232 | padding: 0.5rem; 233 | border-radius: 5px; 234 | margin-bottom: 1rem; 235 | } 236 | 237 | .notification span { 238 | margin-left: 0.5rem; 239 | } 240 | 241 | .error { 242 | background-color: salmon; 243 | color: #000; 244 | } 245 | 246 | .warn { 247 | background-color: palegoldenrod; 248 | color: #000; 249 | } 250 | 251 | .row div { 252 | display: block; 253 | text-overflow: ellipsis; 254 | white-space: nowrap; 255 | overflow: hidden; 256 | width: 100%; 257 | padding-top: 0.5rem; 258 | margin: 0 0.5rem; 259 | } 260 | 261 | .grid-headers div { 262 | display: flex; 263 | align-items: center; 264 | } 265 | 266 | .pattern-grid { 267 | background-color: #333; 268 | } 269 | 270 | .pattern-grid .grid-headers { 271 | font-weight: bold; 272 | color: #fff; 273 | background-color: #555; 274 | display: grid; 275 | grid-template-columns: 2fr 6fr 3rem 3rem; 276 | padding: 0.5rem; 277 | border: 1px solid #444; 278 | height: 3rem; 279 | width: 100%; 280 | } 281 | 282 | .pattern-grid .row { 283 | display: grid; 284 | padding: 0.5rem; 285 | grid-template-columns: 2fr 6fr 3rem 3rem; 286 | border: 1px solid #666; 287 | border-top: none; 288 | } 289 | 290 | .btn.delete { 291 | background-color: salmon; 292 | width: 2rem; 293 | height: 2rem; 294 | } 295 | 296 | .btn.edit { 297 | background-color: #89ddff; 298 | width: 2rem; 299 | height: 2rem; 300 | } 301 | 302 | .btn.success { 303 | background-color: #93eea8; 304 | } 305 | 306 | .btn.secondary { 307 | background-color: transparent; 308 | color: var(--light); 309 | border: 1px solid silver; 310 | } 311 | 312 | .btn.secondary:active { 313 | background-color: transparent; 314 | color: #89ddff; 315 | border: 1px solid #89ddff; 316 | } 317 | 318 | .btn > span { 319 | font-size: 1rem; 320 | } 321 | 322 | /* DONT TOUCH */ 323 | 324 | .pattern-wrapper { 325 | height: auto; 326 | display: flex; 327 | flex-direction: column; 328 | padding: 0.5rem 0.5rem 0rem 0.5rem; 329 | position: relative; 330 | } 331 | 332 | .input-menu { 333 | display: flex; 334 | align-items: center; 335 | } 336 | 337 | .input-menu svg { 338 | color: silver; 339 | margin-left: 1rem; 340 | } 341 | 342 | .input-menu svg:hover { 343 | color: #fff; 344 | cursor: pointer; 345 | } 346 | 347 | .input-menu svg:active { 348 | color: #89ddff; 349 | cursor: pointer; 350 | } 351 | 352 | .output-wrapper { 353 | padding: 0.5rem 0.5rem 0 0.5rem; 354 | height: 100%; 355 | display: flex; 356 | flex-direction: column; 357 | position: relative; 358 | overflow: hidden; 359 | } 360 | 361 | .output-wrapper > * { 362 | position: relative; 363 | overflow: hidden; 364 | } 365 | 366 | .collections-wrapper { 367 | padding: 1rem 0.5rem; 368 | } 369 | 370 | .collections-wrapper div a:hover { 371 | color: var(--light) !important; 372 | } 373 | 374 | .set-item { 375 | display: flex; 376 | align-items: center; 377 | justify-content: space-between; 378 | margin: 0rem 0.5rem; 379 | padding: 0.5rem; 380 | background-color: #333; 381 | border: 1px solid #666; 382 | } 383 | 384 | .react-codemirror2 { 385 | max-width: 100%; 386 | height: 100%; 387 | } 388 | 389 | .CodeMirror { 390 | border: 1px solid #666; 391 | } 392 | 393 | .CodeMirror-focused { 394 | border: 1px solid silver; 395 | } 396 | 397 | .btn { 398 | background-color: #89ddff; 399 | opacity: 0.9; 400 | padding: 0.5rem; 401 | border-radius: 5px; 402 | position: relative; 403 | color: var(--dark); 404 | display: flex; 405 | align-items: center; 406 | justify-content: center; 407 | box-shadow: 2px 2px rgba(0, 0, 0, 0.6); 408 | } 409 | 410 | button.btn :nth-child(1) { 411 | margin-right: 0.5rem; 412 | } 413 | 414 | .btn:hover { 415 | opacity: 1; 416 | cursor: pointer; 417 | } 418 | 419 | /* MULTI SELECT */ 420 | 421 | /* MEDIA QUERIES */ 422 | 423 | @media (max-width: 700px) { 424 | .navbar h1 { 425 | font-size: 1.5rem; 426 | } 427 | .navbar span.beta { 428 | display: none; 429 | } 430 | .nav-links span { 431 | display: none; 432 | } 433 | .nav-links svg { 434 | height: 1.2rem; 435 | width: 1.2rem; 436 | } 437 | .main { 438 | padding-bottom: 0; 439 | } 440 | .menu { 441 | display: none; 442 | } 443 | .container { 444 | grid-template-columns: auto; 445 | grid-template-rows: 1fr 1fr; 446 | grid-template-areas: "main" "result"; 447 | } 448 | } 449 | -------------------------------------------------------------------------------- /public/patterns/nagios: -------------------------------------------------------------------------------- 1 | ################################################################################## 2 | ################################################################################## 3 | # Chop Nagios log files to smithereens! 4 | # 5 | # A set of GROK filters to process logfiles generated by Nagios. 6 | # While it does not, this set intends to cover all possible Nagios logs. 7 | # 8 | # Some more work needs to be done to cover all External Commands: 9 | # http://old.nagios.org/developerinfo/externalcommands/commandlist.php 10 | # 11 | # If you need some support on these rules please contact: 12 | # Jelle Smet http://smetj.net 13 | # 14 | ################################################################################# 15 | ################################################################################# 16 | 17 | NAGIOSTIME \[%{NUMBER:timestamp}\] 18 | 19 | ############################################### 20 | ######## Begin nagios log types 21 | ############################################### 22 | NAGIOS_TYPE_CURRENT_SERVICE_STATE CURRENT SERVICE STATE 23 | NAGIOS_TYPE_CURRENT_HOST_STATE CURRENT HOST STATE 24 | 25 | NAGIOS_TYPE_SERVICE_NOTIFICATION SERVICE NOTIFICATION 26 | NAGIOS_TYPE_HOST_NOTIFICATION HOST NOTIFICATION 27 | 28 | NAGIOS_TYPE_SERVICE_ALERT SERVICE ALERT 29 | NAGIOS_TYPE_HOST_ALERT HOST ALERT 30 | 31 | NAGIOS_TYPE_SERVICE_FLAPPING_ALERT SERVICE FLAPPING ALERT 32 | NAGIOS_TYPE_HOST_FLAPPING_ALERT HOST FLAPPING ALERT 33 | 34 | NAGIOS_TYPE_SERVICE_DOWNTIME_ALERT SERVICE DOWNTIME ALERT 35 | NAGIOS_TYPE_HOST_DOWNTIME_ALERT HOST DOWNTIME ALERT 36 | 37 | NAGIOS_TYPE_PASSIVE_SERVICE_CHECK PASSIVE SERVICE CHECK 38 | NAGIOS_TYPE_PASSIVE_HOST_CHECK PASSIVE HOST CHECK 39 | 40 | NAGIOS_TYPE_SERVICE_EVENT_HANDLER SERVICE EVENT HANDLER 41 | NAGIOS_TYPE_HOST_EVENT_HANDLER HOST EVENT HANDLER 42 | 43 | NAGIOS_TYPE_EXTERNAL_COMMAND EXTERNAL COMMAND 44 | NAGIOS_TYPE_TIMEPERIOD_TRANSITION TIMEPERIOD TRANSITION 45 | ############################################### 46 | ######## End nagios log types 47 | ############################################### 48 | 49 | ############################################### 50 | ######## Begin external check types 51 | ############################################### 52 | NAGIOS_EC_DISABLE_SVC_CHECK DISABLE_SVC_CHECK 53 | NAGIOS_EC_ENABLE_SVC_CHECK ENABLE_SVC_CHECK 54 | NAGIOS_EC_DISABLE_HOST_CHECK DISABLE_HOST_CHECK 55 | NAGIOS_EC_ENABLE_HOST_CHECK ENABLE_HOST_CHECK 56 | NAGIOS_EC_PROCESS_SERVICE_CHECK_RESULT PROCESS_SERVICE_CHECK_RESULT 57 | NAGIOS_EC_PROCESS_HOST_CHECK_RESULT PROCESS_HOST_CHECK_RESULT 58 | NAGIOS_EC_SCHEDULE_SERVICE_DOWNTIME SCHEDULE_SERVICE_DOWNTIME 59 | NAGIOS_EC_SCHEDULE_HOST_DOWNTIME SCHEDULE_HOST_DOWNTIME 60 | NAGIOS_EC_DISABLE_HOST_SVC_NOTIFICATIONS DISABLE_HOST_SVC_NOTIFICATIONS 61 | NAGIOS_EC_ENABLE_HOST_SVC_NOTIFICATIONS ENABLE_HOST_SVC_NOTIFICATIONS 62 | NAGIOS_EC_DISABLE_HOST_NOTIFICATIONS DISABLE_HOST_NOTIFICATIONS 63 | NAGIOS_EC_ENABLE_HOST_NOTIFICATIONS ENABLE_HOST_NOTIFICATIONS 64 | NAGIOS_EC_DISABLE_SVC_NOTIFICATIONS DISABLE_SVC_NOTIFICATIONS 65 | NAGIOS_EC_ENABLE_SVC_NOTIFICATIONS ENABLE_SVC_NOTIFICATIONS 66 | ############################################### 67 | ######## End external check types 68 | ############################################### 69 | NAGIOS_WARNING Warning:%{SPACE}%{GREEDYDATA:message} 70 | 71 | NAGIOS_CURRENT_SERVICE_STATE %{NAGIOS_TYPE_CURRENT_SERVICE_STATE:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][name]};%{DATA:[service][state]};%{DATA:[nagios][log][state_type]};%{INT:[nagios][log][attempt]:int};%{GREEDYDATA:message} 72 | NAGIOS_CURRENT_HOST_STATE %{NAGIOS_TYPE_CURRENT_HOST_STATE:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][state]};%{DATA:[nagios][log][state_type]};%{INT:[nagios][log][attempt]:int};%{GREEDYDATA:message} 73 | 74 | NAGIOS_SERVICE_NOTIFICATION %{NAGIOS_TYPE_SERVICE_NOTIFICATION:[nagios][log][type]}: %{DATA:[user][name]};%{DATA:[host][hostname]};%{DATA:[service][name]};%{DATA:[service][state]};%{DATA:[nagios][log][notification_command]};%{GREEDYDATA:message} 75 | NAGIOS_HOST_NOTIFICATION %{NAGIOS_TYPE_HOST_NOTIFICATION:[nagios][log][type]}: %{DATA:[user][name]};%{DATA:[host][hostname]};%{DATA:[service][state]};%{DATA:[nagios][log][notification_command]};%{GREEDYDATA:message} 76 | 77 | NAGIOS_SERVICE_ALERT %{NAGIOS_TYPE_SERVICE_ALERT:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][name]};%{DATA:[service][state]};%{DATA:[nagios][log][state_type]};%{INT:[nagios][log][attempt]:int};%{GREEDYDATA:message} 78 | NAGIOS_HOST_ALERT %{NAGIOS_TYPE_HOST_ALERT:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][state]};%{DATA:[nagios][log][state_type]};%{INT:[nagios][log][attempt]:int};%{GREEDYDATA:message} 79 | 80 | NAGIOS_SERVICE_FLAPPING_ALERT %{NAGIOS_TYPE_SERVICE_FLAPPING_ALERT:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][name]};%{DATA:[service][state]};%{GREEDYDATA:message} 81 | NAGIOS_HOST_FLAPPING_ALERT %{NAGIOS_TYPE_HOST_FLAPPING_ALERT:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][state]};%{GREEDYDATA:message} 82 | 83 | NAGIOS_SERVICE_DOWNTIME_ALERT %{NAGIOS_TYPE_SERVICE_DOWNTIME_ALERT:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][name]};%{DATA:[service][state]};%{GREEDYDATA:[nagios][log][comment]} 84 | NAGIOS_HOST_DOWNTIME_ALERT %{NAGIOS_TYPE_HOST_DOWNTIME_ALERT:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][state]};%{GREEDYDATA:[nagios][log][comment]} 85 | 86 | NAGIOS_PASSIVE_SERVICE_CHECK %{NAGIOS_TYPE_PASSIVE_SERVICE_CHECK:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][name]};%{DATA:[service][state]};%{GREEDYDATA:[nagios][log][comment]} 87 | NAGIOS_PASSIVE_HOST_CHECK %{NAGIOS_TYPE_PASSIVE_HOST_CHECK:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][state]};%{GREEDYDATA:[nagios][log][comment]} 88 | 89 | NAGIOS_SERVICE_EVENT_HANDLER %{NAGIOS_TYPE_SERVICE_EVENT_HANDLER:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][name]};%{DATA:[service][state]};%{DATA:[nagios][log][state_type]};%{DATA:[nagios][log][event_handler_name]} 90 | NAGIOS_HOST_EVENT_HANDLER %{NAGIOS_TYPE_HOST_EVENT_HANDLER:[nagios][log][type]}: %{DATA:[host][hostname]};%{DATA:[service][state]};%{DATA:[nagios][log][state_type]};%{DATA:[nagios][log][event_handler_name]} 91 | 92 | NAGIOS_TIMEPERIOD_TRANSITION %{NAGIOS_TYPE_TIMEPERIOD_TRANSITION:[nagios][log][type]}: %{DATA:[service][name]};%{NUMBER:[nagios][log][period_from]:int};%{NUMBER:[nagios][log][period_to]:int} 93 | 94 | #################### 95 | #### External checks 96 | #################### 97 | 98 | #Disable host & service check 99 | NAGIOS_EC_LINE_DISABLE_SVC_CHECK %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_DISABLE_SVC_CHECK:[nagios][log][command]};%{DATA:[host][hostname]};%{DATA:[service][name]} 100 | NAGIOS_EC_LINE_DISABLE_HOST_CHECK %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_DISABLE_HOST_CHECK:[nagios][log][command]};%{DATA:[host][hostname]} 101 | 102 | #Enable host & service check 103 | NAGIOS_EC_LINE_ENABLE_SVC_CHECK %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_ENABLE_SVC_CHECK:[nagios][log][command]};%{DATA:[host][hostname]};%{DATA:[service][name]} 104 | NAGIOS_EC_LINE_ENABLE_HOST_CHECK %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_ENABLE_HOST_CHECK:[nagios][log][command]};%{DATA:[host][hostname]} 105 | 106 | #Process host & service check 107 | NAGIOS_EC_LINE_PROCESS_SERVICE_CHECK_RESULT %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_PROCESS_SERVICE_CHECK_RESULT:[nagios][log][command]};%{DATA:[host][hostname]};%{DATA:[service][name]};%{DATA:[service][state]};%{GREEDYDATA:[nagios][log][check_result]} 108 | NAGIOS_EC_LINE_PROCESS_HOST_CHECK_RESULT %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_PROCESS_HOST_CHECK_RESULT:[nagios][log][command]};%{DATA:[host][hostname]};%{DATA:[service][state]};%{GREEDYDATA:[nagios][log][check_result]} 109 | 110 | #Disable host & service notifications 111 | NAGIOS_EC_LINE_DISABLE_HOST_SVC_NOTIFICATIONS %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_DISABLE_HOST_SVC_NOTIFICATIONS:[nagios][log][command]};%{GREEDYDATA:[host][hostname]} 112 | NAGIOS_EC_LINE_DISABLE_HOST_NOTIFICATIONS %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_DISABLE_HOST_NOTIFICATIONS:[nagios][log][command]};%{GREEDYDATA:[host][hostname]} 113 | NAGIOS_EC_LINE_DISABLE_SVC_NOTIFICATIONS %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_DISABLE_SVC_NOTIFICATIONS:[nagios][log][command]};%{DATA:[host][hostname]};%{GREEDYDATA:[service][name]} 114 | 115 | #Enable host & service notifications 116 | NAGIOS_EC_LINE_ENABLE_HOST_SVC_NOTIFICATIONS %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_ENABLE_HOST_SVC_NOTIFICATIONS:[nagios][log][command]};%{GREEDYDATA:[host][hostname]} 117 | NAGIOS_EC_LINE_ENABLE_HOST_NOTIFICATIONS %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_ENABLE_HOST_NOTIFICATIONS:[nagios][log][command]};%{GREEDYDATA:[host][hostname]} 118 | NAGIOS_EC_LINE_ENABLE_SVC_NOTIFICATIONS %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_ENABLE_SVC_NOTIFICATIONS:[nagios][log][command]};%{DATA:[host][hostname]};%{GREEDYDATA:[service][name]} 119 | 120 | #Schedule host & service downtime 121 | NAGIOS_EC_LINE_SCHEDULE_HOST_DOWNTIME %{NAGIOS_TYPE_EXTERNAL_COMMAND:[nagios][log][type]}: %{NAGIOS_EC_SCHEDULE_HOST_DOWNTIME:[nagios][log][command]};%{DATA:[host][hostname]};%{NUMBER:[nagios][log][start_time]};%{NUMBER:[nagios][log][end_time]};%{NUMBER:[nagios][log][fixed]};%{NUMBER:[nagios][log][trigger_id]};%{NUMBER:[nagios][log][duration]:int};%{DATA:[user][name]};%{DATA:[nagios][log][comment]} 122 | 123 | #End matching line 124 | NAGIOSLOGLINE %{NAGIOSTIME} (?:%{NAGIOS_WARNING}|%{NAGIOS_CURRENT_SERVICE_STATE}|%{NAGIOS_CURRENT_HOST_STATE}|%{NAGIOS_SERVICE_NOTIFICATION}|%{NAGIOS_HOST_NOTIFICATION}|%{NAGIOS_SERVICE_ALERT}|%{NAGIOS_HOST_ALERT}|%{NAGIOS_SERVICE_FLAPPING_ALERT}|%{NAGIOS_HOST_FLAPPING_ALERT}|%{NAGIOS_SERVICE_DOWNTIME_ALERT}|%{NAGIOS_HOST_DOWNTIME_ALERT}|%{NAGIOS_PASSIVE_SERVICE_CHECK}|%{NAGIOS_PASSIVE_HOST_CHECK}|%{NAGIOS_SERVICE_EVENT_HANDLER}|%{NAGIOS_HOST_EVENT_HANDLER}|%{NAGIOS_TIMEPERIOD_TRANSITION}|%{NAGIOS_EC_LINE_DISABLE_SVC_CHECK}|%{NAGIOS_EC_LINE_ENABLE_SVC_CHECK}|%{NAGIOS_EC_LINE_DISABLE_HOST_CHECK}|%{NAGIOS_EC_LINE_ENABLE_HOST_CHECK}|%{NAGIOS_EC_LINE_PROCESS_HOST_CHECK_RESULT}|%{NAGIOS_EC_LINE_PROCESS_SERVICE_CHECK_RESULT}|%{NAGIOS_EC_LINE_SCHEDULE_HOST_DOWNTIME}|%{NAGIOS_EC_LINE_DISABLE_HOST_SVC_NOTIFICATIONS}|%{NAGIOS_EC_LINE_ENABLE_HOST_SVC_NOTIFICATIONS}|%{NAGIOS_EC_LINE_DISABLE_HOST_NOTIFICATIONS}|%{NAGIOS_EC_LINE_ENABLE_HOST_NOTIFICATIONS}|%{NAGIOS_EC_LINE_DISABLE_SVC_NOTIFICATIONS}|%{NAGIOS_EC_LINE_ENABLE_SVC_NOTIFICATIONS}) 125 | -------------------------------------------------------------------------------- /public/patterns/postfix: -------------------------------------------------------------------------------- 1 | # Version: 1.0.0 2 | 3 | # common postfix patterns 4 | POSTFIX_QUEUEID ([0-9A-F]{6,}|[0-9a-zA-Z]{12,}|NOQUEUE) 5 | POSTFIX_CLIENT_INFO %{HOSTNAME:postfix_client_hostname}?\[%{IP:postfix_client_ip}\](:%{INT:postfix_client_port})? 6 | POSTFIX_RELAY_INFO %{HOSTNAME:postfix_relay_hostname}?\[(%{IP:postfix_relay_ip}|%{DATA:postfix_relay_service})\](:%{INT:postfix_relay_port})?|%{WORD:postfix_relay_service} 7 | POSTFIX_SMTP_STAGE (CONNECT|HELO|EHLO|STARTTLS|AUTH|MAIL( FROM)?|RCPT( TO)?|(end of )?DATA|RSET|UNKNOWN|END-OF-MESSAGE|VRFY|\.) 8 | POSTFIX_ACTION (accept|defer|discard|filter|header-redirect|reject|reject_warning) 9 | POSTFIX_STATUS_CODE \d{3} 10 | POSTFIX_STATUS_CODE_ENHANCED \d\.\d+\.\d+ 11 | POSTFIX_DNSBL_MESSAGE Service unavailable; .* \[%{GREEDYDATA:postfix_status_data}\] %{GREEDYDATA:postfix_status_message}; 12 | POSTFIX_PS_ACCESS_ACTION (DISCONNECT|BLACKLISTED|WHITELISTED|WHITELIST VETO|PASS NEW|PASS OLD) 13 | POSTFIX_PS_VIOLATION (BARE NEWLINE|COMMAND (TIME|COUNT|LENGTH) LIMIT|COMMAND PIPELINING|DNSBL|HANGUP|NON-SMTP COMMAND|PREGREET) 14 | POSTFIX_TIME_UNIT %{NUMBER}[smhd] 15 | POSTFIX_KEYVALUE_DATA [\w-]+=[^;]* 16 | POSTFIX_KEYVALUE %{POSTFIX_QUEUEID:postfix_queueid}: %{POSTFIX_KEYVALUE_DATA:postfix_keyvalue_data} 17 | POSTFIX_WARNING_LEVEL (warning|fatal|info) 18 | 19 | POSTFIX_TLSCONN (Anonymous|Trusted|Untrusted|Verified) TLS connection established (to %{POSTFIX_RELAY_INFO}|from %{POSTFIX_CLIENT_INFO}): %{DATA:postfix_tls_version} with cipher %{DATA:postfix_tls_cipher} \(%{DATA:postfix_tls_cipher_size} bits\) 20 | POSTFIX_TLSVERIFICATION certificate verification failed for %{POSTFIX_RELAY_INFO}: %{GREEDYDATA:postfix_tls_error} 21 | 22 | POSTFIX_DELAYS %{NUMBER:postfix_delay_before_qmgr}/%{NUMBER:postfix_delay_in_qmgr}/%{NUMBER:postfix_delay_conn_setup}/%{NUMBER:postfix_delay_transmission} 23 | POSTFIX_LOSTCONN (Connection timed out|No route to host|Connection refused|Network is unreachable|lost connection|timeout|SSL_accept error|-1) 24 | POSTFIX_LOSTCONN_REASONS (receiving the initial server greeting|sending message body|sending end of data -- message may be sent more than once) 25 | POSTFIX_PROXY_MESSAGE (%{POSTFIX_STATUS_CODE:postfix_proxy_status_code} )?(%{POSTFIX_STATUS_CODE_ENHANCED:postfix_proxy_status_code_enhanced})?.* 26 | POSTFIX_COMMAND_COUNTER_DATA (helo=(%{INT:postfix_cmd_helo_accepted}/)?%{INT:postfix_cmd_helo} )?(ehlo=(%{INT:postfix_cmd_ehlo_accepted}/)?%{INT:postfix_cmd_ehlo} )?(starttls=(%{INT:postfix_cmd_starttls_accepted}/)?%{INT:postfix_cmd_starttls} )?(auth=(%{INT:postfix_cmd_auth_accepted}/)?%{INT:postfix_cmd_auth} )?(mail=(%{INT:postfix_cmd_mail_accepted}/)?%{INT:postfix_cmd_mail} )?(rcpt=(%{INT:postfix_cmd_rcpt_accepted}/)?%{INT:postfix_cmd_rcpt} )?(data=(%{INT:postfix_cmd_data_accepted}/)?%{INT:postfix_cmd_data} )?(rset=(%{INT:postfix_cmd_rset_accepted}/)?%{INT:postfix_cmd_rset} )?(quit=(%{INT:postfix_cmd_quit_accepted}/)?%{INT:postfix_cmd_quit} )?(unknown=(%{INT:postfix_cmd_unknown_accepted}/)?%{INT:postfix_cmd_unknown} )?commands=(%{INT:postfix_cmd_count_accepted}/)?%{INT:postfix_cmd_count} 27 | 28 | # helper patterns 29 | GREEDYDATA_NO_COLON [^:]* 30 | GREEDYDATA_NO_SEMICOLON [^;]* 31 | GREEDYDATA_NO_BRACKET [^<>]* 32 | STATUS_WORD [\w-]* 33 | 34 | # warning patterns 35 | POSTFIX_WARNING_WITH_KV (%{POSTFIX_QUEUEID:postfix_queueid}: )?%{POSTFIX_WARNING_LEVEL:postfix_message_level}: (%{POSTFIX_CLIENT_INFO}: )?%{GREEDYDATA:postfix_message}; %{POSTFIX_KEYVALUE_DATA:postfix_keyvalue_data} 36 | POSTFIX_WARNING_WITHOUT_KV (%{POSTFIX_QUEUEID:postfix_queueid}: )?%{POSTFIX_WARNING_LEVEL:postfix_message_level}: (%{POSTFIX_CLIENT_INFO}: )?%{GREEDYDATA:postfix_message} 37 | POSTFIX_WARNING %{POSTFIX_WARNING_WITH_KV}|%{POSTFIX_WARNING_WITHOUT_KV} 38 | 39 | # smtpd patterns 40 | POSTFIX_SMTPD_CONNECT connect from %{POSTFIX_CLIENT_INFO} 41 | POSTFIX_SMTPD_DISCONNECT disconnect from %{POSTFIX_CLIENT_INFO}( %{GREEDYDATA:postfix_command_counter_data})? 42 | POSTFIX_SMTPD_LOSTCONN %{POSTFIX_LOSTCONN:postfix_smtpd_lostconn_data}( after %{POSTFIX_SMTP_STAGE:postfix_smtp_stage}( \(%{INT} bytes\))?)? from %{POSTFIX_CLIENT_INFO}(: %{GREEDYDATA:postfix_smtpd_lostconn_reason})? 43 | POSTFIX_SMTPD_NOQUEUE %{POSTFIX_QUEUEID:postfix_queueid}: %{POSTFIX_ACTION:postfix_action}: %{POSTFIX_SMTP_STAGE:postfix_smtp_stage} from %{POSTFIX_CLIENT_INFO}:( %{POSTFIX_STATUS_CODE:postfix_status_code} %{POSTFIX_STATUS_CODE_ENHANCED:postfix_status_code_enhanced})?( <%{DATA:postfix_status_data}>:)? (%{POSTFIX_DNSBL_MESSAGE}|%{GREEDYDATA:postfix_status_message};) %{POSTFIX_KEYVALUE_DATA:postfix_keyvalue_data} 44 | POSTFIX_SMTPD_PIPELINING improper command pipelining after %{POSTFIX_SMTP_STAGE:postfix_smtp_stage} from %{POSTFIX_CLIENT_INFO}: %{GREEDYDATA:postfix_improper_pipelining_data} 45 | POSTFIX_SMTPD_PROXY proxy-%{POSTFIX_ACTION:postfix_proxy_result}: (%{POSTFIX_SMTP_STAGE:postfix_proxy_smtp_stage}): %{POSTFIX_PROXY_MESSAGE:postfix_proxy_message}; %{POSTFIX_KEYVALUE_DATA:postfix_keyvalue_data} 46 | 47 | # cleanup patterns 48 | POSTFIX_CLEANUP_MILTER %{POSTFIX_QUEUEID:postfix_queueid}: milter-%{POSTFIX_ACTION:postfix_milter_result}: %{GREEDYDATA:postfix_milter_message}; %{GREEDYDATA_NO_COLON:postfix_keyvalue_data}(: %{GREEDYDATA:postfix_milter_data})? 49 | POSTFIX_CLEANUP_PREPEND_TYPE (header|body) 50 | POSTFIX_CLEANUP_PREPEND %{POSTFIX_QUEUEID:postfix_queueid}: prepend: %{POSTFIX_CLEANUP_PREPEND_TYPE:postfix_prepend_type} %{GREEDYDATA:postfix_prepend_trigger} from %{POSTFIX_CLIENT_INFO}; %{GREEDYDATA_NO_COLON:postfix_keyvalue_data}: %{GREEDYDATA:postfix_prepend_value} 51 | POSTFIX_CLEANUP_MESSAGEID %{POSTFIX_QUEUEID:postfix_queueid}: message-id=? 52 | 53 | # qmgr patterns 54 | POSTFIX_QMGR_REMOVED %{POSTFIX_QUEUEID:postfix_queueid}: removed 55 | POSTFIX_QMGR_ACTIVE %{POSTFIX_QUEUEID:postfix_queueid}: %{POSTFIX_KEYVALUE_DATA:postfix_keyvalue_data} \(queue active\) 56 | POSTFIX_QMGR_EXPIRED %{POSTFIX_QUEUEID:postfix_queueid}: from=<%{DATA:postfix_from}>, status=%{STATUS_WORD:postfix_status}, returned to sender 57 | 58 | # pipe patterns 59 | POSTFIX_PIPE_ANY %{POSTFIX_QUEUEID:postfix_queueid}: %{POSTFIX_KEYVALUE_DATA:postfix_keyvalue_data}, status=%{STATUS_WORD:postfix_status} \(%{GREEDYDATA:postfix_pipe_response}\) 60 | 61 | # error patterns 62 | POSTFIX_ERROR_ANY %{POSTFIX_QUEUEID:postfix_queueid}: %{POSTFIX_KEYVALUE_DATA:postfix_keyvalue_data}, status=%{STATUS_WORD:postfix_status} \(%{GREEDYDATA:postfix_error_response}\) 63 | 64 | # discard patterns 65 | POSTFIX_DISCARD_ANY %{POSTFIX_QUEUEID:postfix_queueid}: %{POSTFIX_KEYVALUE_DATA:postfix_keyvalue_data} status=%{STATUS_WORD:postfix_status} %{GREEDYDATA} 66 | 67 | # postsuper patterns 68 | POSTFIX_POSTSUPER_ACTIONS (removed|requeued|placed on hold|released from hold) 69 | POSTFIX_POSTSUPER_ACTION %{POSTFIX_QUEUEID:postfix_queueid}: %{POSTFIX_POSTSUPER_ACTIONS:postfix_postsuper_action} 70 | POSTFIX_POSTSUPER_SUMMARY_ACTIONS (Deleted|Requeued|Placed on hold|Released from hold) 71 | POSTFIX_POSTSUPER_SUMMARY %{POSTFIX_POSTSUPER_SUMMARY_ACTIONS:postfix_postsuper_summary_action}: %{NUMBER:postfix_postsuper_summary_count} messages? 72 | 73 | # postscreen patterns 74 | POSTFIX_PS_CONNECT CONNECT from %{POSTFIX_CLIENT_INFO} to \[%{IP:postfix_server_ip}\]:%{INT:postfix_server_port} 75 | POSTFIX_PS_ACCESS %{POSTFIX_PS_ACCESS_ACTION:postfix_postscreen_access} %{POSTFIX_CLIENT_INFO} 76 | POSTFIX_PS_NOQUEUE %{POSTFIX_SMTPD_NOQUEUE} 77 | POSTFIX_PS_TOOBUSY NOQUEUE: reject: CONNECT from %{POSTFIX_CLIENT_INFO}: %{GREEDYDATA:postfix_postscreen_toobusy_data} 78 | POSTFIX_PS_DNSBL %{POSTFIX_PS_VIOLATION:postfix_postscreen_violation} rank %{INT:postfix_postscreen_dnsbl_rank} for %{POSTFIX_CLIENT_INFO} 79 | POSTFIX_PS_CACHE cache %{DATA} full cleanup: retained=%{NUMBER:postfix_postscreen_cache_retained} dropped=%{NUMBER:postfix_postscreen_cache_dropped} entries 80 | POSTFIX_PS_VIOLATIONS %{POSTFIX_PS_VIOLATION:postfix_postscreen_violation}( %{INT})?( after %{NUMBER:postfix_postscreen_violation_time})? from %{POSTFIX_CLIENT_INFO}(( after %{POSTFIX_SMTP_STAGE:postfix_smtp_stage})?(: %{GREEDYDATA:postfix_postscreen_data})?| in tests (after|before) SMTP handshake) 81 | 82 | # dnsblog patterns 83 | POSTFIX_DNSBLOG_LISTING addr %{IP:postfix_client_ip} listed by domain %{HOSTNAME:postfix_dnsbl_domain} as %{IP:postfix_dnsbl_result} 84 | 85 | # tlsproxy patterns 86 | POSTFIX_TLSPROXY_CONN (DIS)?CONNECT( from)? %{POSTFIX_CLIENT_INFO} 87 | 88 | # anvil patterns 89 | POSTFIX_ANVIL_CONN_RATE statistics: max connection rate %{NUMBER:postfix_anvil_conn_rate}/%{POSTFIX_TIME_UNIT:postfix_anvil_conn_period} for \(%{DATA:postfix_service}:%{IP:postfix_client_ip}\) at %{SYSLOGTIMESTAMP:postfix_anvil_timestamp} 90 | POSTFIX_ANVIL_CONN_CACHE statistics: max cache size %{NUMBER:postfix_anvil_cache_size} at %{SYSLOGTIMESTAMP:postfix_anvil_timestamp} 91 | POSTFIX_ANVIL_CONN_COUNT statistics: max connection count %{NUMBER:postfix_anvil_conn_count} for \(%{DATA:postfix_service}:%{IP:postfix_client_ip}\) at %{SYSLOGTIMESTAMP:postfix_anvil_timestamp} 92 | 93 | # smtp patterns 94 | POSTFIX_SMTP_DELIVERY %{POSTFIX_KEYVALUE} status=%{STATUS_WORD:postfix_status}( \(%{GREEDYDATA:postfix_smtp_response}\))? 95 | POSTFIX_SMTP_CONNERR connect to %{POSTFIX_RELAY_INFO}: %{POSTFIX_LOSTCONN:postfix_smtp_lostconn_data} 96 | POSTFIX_SMTP_SSLCONNERR SSL_connect error to %{POSTFIX_RELAY_INFO}: %{POSTFIX_LOSTCONN:postfix_smtp_lostconn_data} 97 | POSTFIX_SMTP_LOSTCONN %{POSTFIX_QUEUEID:postfix_queueid}: %{POSTFIX_LOSTCONN:postfix_smtp_lostconn_data} with %{POSTFIX_RELAY_INFO}( while %{POSTFIX_LOSTCONN_REASONS:postfix_smtp_lostconn_reason})? 98 | POSTFIX_SMTP_TIMEOUT %{POSTFIX_QUEUEID:postfix_queueid}: conversation with %{POSTFIX_RELAY_INFO} timed out( while %{POSTFIX_LOSTCONN_REASONS:postfix_smtp_lostconn_reason})? 99 | POSTFIX_SMTP_RELAYERR %{POSTFIX_QUEUEID:postfix_queueid}: host %{POSTFIX_RELAY_INFO} said: %{GREEDYDATA:postfix_smtp_response} \(in reply to %{POSTFIX_SMTP_STAGE:postfix_smtp_stage} command\) 100 | POSTFIX_SMTP_UTF8 host %{POSTFIX_RELAY_INFO} offers SMTPUTF8 support, but not 8BITMIME 101 | POSTFIX_SMTP_PIX %{POSTFIX_QUEUEID:postfix_queueid}: enabling PIX workarounds: %{DATA:postfix_pix_workaround} for %{POSTFIX_RELAY_INFO} 102 | 103 | # master patterns 104 | POSTFIX_MASTER_START (daemon started|reload) -- version %{DATA:postfix_version}, configuration %{PATH:postfix_config_path} 105 | POSTFIX_MASTER_EXIT terminating on signal %{INT:postfix_termination_signal} 106 | 107 | # bounce patterns 108 | POSTFIX_BOUNCE_NOTIFICATION %{POSTFIX_QUEUEID:postfix_queueid}: sender (non-delivery|delivery status|delay) notification: %{POSTFIX_QUEUEID:postfix_bounce_queueid} 109 | 110 | # scache patterns 111 | POSTFIX_SCACHE_LOOKUPS statistics: (address|domain) lookup hits=%{INT:postfix_scache_hits} miss=%{INT:postfix_scache_miss} success=%{INT:postfix_scache_success}% 112 | POSTFIX_SCACHE_SIMULTANEOUS statistics: max simultaneous domains=%{INT:postfix_scache_domains} addresses=%{INT:postfix_scache_addresses} connection=%{INT:postfix_scache_connection} 113 | POSTFIX_SCACHE_TIMESTAMP statistics: start interval %{SYSLOGTIMESTAMP:postfix_scache_timestamp} 114 | 115 | # aggregate all patterns 116 | POSTFIX_SMTPD %{POSTFIX_SMTPD_CONNECT}|%{POSTFIX_SMTPD_DISCONNECT}|%{POSTFIX_SMTPD_LOSTCONN}|%{POSTFIX_SMTPD_NOQUEUE}|%{POSTFIX_SMTPD_PIPELINING}|%{POSTFIX_TLSCONN}|%{POSTFIX_WARNING}|%{POSTFIX_SMTPD_PROXY}|%{POSTFIX_KEYVALUE} 117 | POSTFIX_CLEANUP %{POSTFIX_CLEANUP_MESSAGEID}|%{POSTFIX_CLEANUP_MILTER}|%{POSTFIX_CLEANUP_PREPEND}|%{POSTFIX_WARNING}|%{POSTFIX_KEYVALUE} 118 | POSTFIX_QMGR %{POSTFIX_QMGR_REMOVED}|%{POSTFIX_QMGR_ACTIVE}|%{POSTFIX_QMGR_EXPIRED}|%{POSTFIX_WARNING} 119 | POSTFIX_PIPE %{POSTFIX_PIPE_ANY} 120 | POSTFIX_POSTSCREEN %{POSTFIX_PS_CONNECT}|%{POSTFIX_PS_ACCESS}|%{POSTFIX_PS_NOQUEUE}|%{POSTFIX_PS_TOOBUSY}|%{POSTFIX_PS_CACHE}|%{POSTFIX_PS_DNSBL}|%{POSTFIX_PS_VIOLATIONS}|%{POSTFIX_WARNING} 121 | POSTFIX_DNSBLOG %{POSTFIX_DNSBLOG_LISTING}|%{POSTFIX_WARNING} 122 | POSTFIX_ANVIL %{POSTFIX_ANVIL_CONN_RATE}|%{POSTFIX_ANVIL_CONN_CACHE}|%{POSTFIX_ANVIL_CONN_COUNT} 123 | POSTFIX_SMTP %{POSTFIX_SMTP_DELIVERY}|%{POSTFIX_SMTP_CONNERR}|%{POSTFIX_SMTP_SSLCONNERR}|%{POSTFIX_SMTP_LOSTCONN}|%{POSTFIX_SMTP_TIMEOUT}|%{POSTFIX_SMTP_RELAYERR}|%{POSTFIX_TLSCONN}|%{POSTFIX_WARNING}|%{POSTFIX_SMTP_UTF8}|%{POSTFIX_TLSVERIFICATION}|%{POSTFIX_SMTP_PIX} 124 | POSTFIX_DISCARD %{POSTFIX_DISCARD_ANY}|%{POSTFIX_WARNING} 125 | POSTFIX_LMTP %{POSTFIX_SMTP} 126 | POSTFIX_PICKUP %{POSTFIX_KEYVALUE} 127 | POSTFIX_TLSPROXY %{POSTFIX_TLSPROXY_CONN}|%{POSTFIX_WARNING} 128 | POSTFIX_MASTER %{POSTFIX_MASTER_START}|%{POSTFIX_MASTER_EXIT}|%{POSTFIX_WARNING} 129 | POSTFIX_BOUNCE %{POSTFIX_BOUNCE_NOTIFICATION} 130 | POSTFIX_SENDMAIL %{POSTFIX_WARNING} 131 | POSTFIX_POSTDROP %{POSTFIX_WARNING} 132 | POSTFIX_SCACHE %{POSTFIX_SCACHE_LOOKUPS}|%{POSTFIX_SCACHE_SIMULTANEOUS}|%{POSTFIX_SCACHE_TIMESTAMP} 133 | POSTFIX_TRIVIAL_REWRITE %{POSTFIX_WARNING} 134 | POSTFIX_TLSMGR %{POSTFIX_WARNING} 135 | POSTFIX_LOCAL %{POSTFIX_KEYVALUE}|%{POSTFIX_WARNING} 136 | POSTFIX_VIRTUAL %{POSTFIX_SMTP_DELIVERY} 137 | POSTFIX_ERROR %{POSTFIX_ERROR_ANY} 138 | POSTFIX_POSTSUPER %{POSTFIX_POSTSUPER_ACTION}|%{POSTFIX_POSTSUPER_SUMMARY} -------------------------------------------------------------------------------- /src/codemirror/codemirror.css: -------------------------------------------------------------------------------- 1 | /* BASICS */ 2 | 3 | .CodeMirror { 4 | /* Set height, width, borders, and global font properties here */ 5 | font-family: monospace; 6 | min-height: 100%; 7 | color: black; 8 | direction: ltr; 9 | font-size: 1.25rem; 10 | height: 100%; 11 | } 12 | 13 | /* PADDING */ 14 | 15 | .CodeMirror-lines { 16 | padding: 4px 0; /* Vertical padding around content */ 17 | } 18 | .CodeMirror pre.CodeMirror-line, 19 | .CodeMirror pre.CodeMirror-line-like { 20 | padding: 0 4px; /* Horizontal padding of content */ 21 | } 22 | 23 | .CodeMirror-scrollbar-filler, 24 | .CodeMirror-gutter-filler { 25 | background-color: white; /* The little square between H and V scrollbars */ 26 | } 27 | 28 | /* GUTTER */ 29 | 30 | .CodeMirror-gutters { 31 | border-right: 1px solid #ddd; 32 | background-color: #f7f7f7; 33 | white-space: nowrap; 34 | } 35 | .CodeMirror-linenumbers { 36 | } 37 | .CodeMirror-linenumber { 38 | padding: 0 3px 0 5px; 39 | min-width: 20px; 40 | text-align: right; 41 | color: #999; 42 | white-space: nowrap; 43 | } 44 | 45 | .CodeMirror-guttermarker { 46 | color: black; 47 | } 48 | .CodeMirror-guttermarker-subtle { 49 | color: #999; 50 | } 51 | 52 | /* CURSOR */ 53 | 54 | .CodeMirror-cursor { 55 | border-left: 1px solid black; 56 | border-right: none; 57 | width: 0; 58 | } 59 | /* Shown when moving in bi-directional text */ 60 | .CodeMirror div.CodeMirror-secondarycursor { 61 | border-left: 1px solid silver; 62 | } 63 | .cm-fat-cursor .CodeMirror-cursor { 64 | width: auto; 65 | border: 0 !important; 66 | background: #7e7; 67 | } 68 | .cm-fat-cursor div.CodeMirror-cursors { 69 | z-index: 1; 70 | } 71 | .cm-fat-cursor-mark { 72 | background-color: rgba(20, 255, 20, 0.5); 73 | -webkit-animation: blink 1.06s steps(1) infinite; 74 | -moz-animation: blink 1.06s steps(1) infinite; 75 | animation: blink 1.06s steps(1) infinite; 76 | } 77 | .cm-animate-fat-cursor { 78 | width: auto; 79 | border: 0; 80 | -webkit-animation: blink 1.06s steps(1) infinite; 81 | -moz-animation: blink 1.06s steps(1) infinite; 82 | animation: blink 1.06s steps(1) infinite; 83 | background-color: #7e7; 84 | } 85 | @-moz-keyframes blink { 86 | 0% { 87 | } 88 | 50% { 89 | background-color: transparent; 90 | } 91 | 100% { 92 | } 93 | } 94 | @-webkit-keyframes blink { 95 | 0% { 96 | } 97 | 50% { 98 | background-color: transparent; 99 | } 100 | 100% { 101 | } 102 | } 103 | @keyframes blink { 104 | 0% { 105 | } 106 | 50% { 107 | background-color: transparent; 108 | } 109 | 100% { 110 | } 111 | } 112 | 113 | /* Can style cursor different in overwrite (non-insert) mode */ 114 | .CodeMirror-overwrite .CodeMirror-cursor { 115 | } 116 | 117 | .cm-tab { 118 | display: inline-block; 119 | text-decoration: inherit; 120 | } 121 | 122 | .CodeMirror-rulers { 123 | position: absolute; 124 | left: 0; 125 | right: 0; 126 | top: -50px; 127 | bottom: 0; 128 | overflow: hidden; 129 | } 130 | .CodeMirror-ruler { 131 | border-left: 1px solid #ccc; 132 | top: 0; 133 | bottom: 0; 134 | position: absolute; 135 | } 136 | 137 | /* DEFAULT THEME */ 138 | 139 | .cm-s-default .cm-header { 140 | color: blue; 141 | } 142 | .cm-s-default .cm-quote { 143 | color: #090; 144 | } 145 | .cm-negative { 146 | color: #d44; 147 | } 148 | .cm-positive { 149 | color: #292; 150 | } 151 | .cm-header, 152 | .cm-strong { 153 | font-weight: bold; 154 | } 155 | .cm-em { 156 | font-style: italic; 157 | } 158 | .cm-link { 159 | text-decoration: underline; 160 | } 161 | .cm-strikethrough { 162 | text-decoration: line-through; 163 | } 164 | 165 | .cm-s-default .cm-keyword { 166 | color: #708; 167 | } 168 | .cm-s-default .cm-atom { 169 | color: #219; 170 | } 171 | .cm-s-default .cm-number { 172 | color: #164; 173 | } 174 | .cm-s-default .cm-def { 175 | color: #00f; 176 | } 177 | .cm-s-default .cm-variable, 178 | .cm-s-default .cm-punctuation, 179 | .cm-s-default .cm-property, 180 | .cm-s-default .cm-operator { 181 | } 182 | .cm-s-default .cm-variable-2 { 183 | color: #05a; 184 | } 185 | .cm-s-default .cm-variable-3, 186 | .cm-s-default .cm-type { 187 | color: #085; 188 | } 189 | .cm-s-default .cm-comment { 190 | color: #a50; 191 | } 192 | .cm-s-default .cm-string { 193 | color: #a11; 194 | } 195 | .cm-s-default .cm-string-2 { 196 | color: #f50; 197 | } 198 | .cm-s-default .cm-meta { 199 | color: #555; 200 | } 201 | .cm-s-default .cm-qualifier { 202 | color: #555; 203 | } 204 | .cm-s-default .cm-builtin { 205 | color: #30a; 206 | } 207 | .cm-s-default .cm-bracket { 208 | color: #997; 209 | } 210 | .cm-s-default .cm-tag { 211 | color: #170; 212 | } 213 | .cm-s-default .cm-attribute { 214 | color: #00c; 215 | } 216 | .cm-s-default .cm-hr { 217 | color: #999; 218 | } 219 | .cm-s-default .cm-link { 220 | color: #00c; 221 | } 222 | 223 | .cm-s-default .cm-error { 224 | color: #f00; 225 | } 226 | .cm-invalidchar { 227 | color: #f00; 228 | } 229 | 230 | .CodeMirror-composing { 231 | border-bottom: 2px solid; 232 | } 233 | 234 | /* Default styles for common addons */ 235 | 236 | div.CodeMirror span.CodeMirror-matchingbracket { 237 | color: #0b0; 238 | } 239 | div.CodeMirror span.CodeMirror-nonmatchingbracket { 240 | color: #a22; 241 | } 242 | .CodeMirror-matchingtag { 243 | background: rgba(255, 150, 0, 0.3); 244 | } 245 | .CodeMirror-activeline-background { 246 | background: #e8f2ff; 247 | } 248 | 249 | /* STOP */ 250 | 251 | /* The rest of this file contains styles related to the mechanics of 252 | the editor. You probably shouldn't touch them. */ 253 | 254 | .CodeMirror { 255 | position: relative; 256 | overflow: hidden; 257 | background: white; 258 | } 259 | 260 | .CodeMirror-scroll { 261 | overflow: scroll !important; /* Things will break if this is overridden */ 262 | /* 50px is the magic margin used to hide the element's real scrollbars */ 263 | /* See overflow: hidden in .CodeMirror */ 264 | margin-bottom: -50px; 265 | margin-right: -50px; 266 | padding-bottom: 50px; 267 | height: 100%; 268 | outline: none; /* Prevent dragging from highlighting the element */ 269 | position: relative; 270 | } 271 | .CodeMirror-sizer { 272 | position: relative; 273 | border-right: 50px solid transparent; 274 | } 275 | 276 | /* The fake, visible scrollbars. Used to force redraw during scrolling 277 | before actual scrolling happens, thus preventing shaking and 278 | flickering artifacts. */ 279 | .CodeMirror-vscrollbar, 280 | .CodeMirror-hscrollbar, 281 | .CodeMirror-scrollbar-filler, 282 | .CodeMirror-gutter-filler { 283 | position: absolute; 284 | z-index: 6; 285 | display: none; 286 | outline: none; 287 | } 288 | .CodeMirror-vscrollbar { 289 | right: 0; 290 | top: 0; 291 | overflow-x: hidden; 292 | overflow-y: scroll; 293 | } 294 | .CodeMirror-hscrollbar { 295 | bottom: 0; 296 | left: 0; 297 | overflow-y: hidden; 298 | overflow-x: scroll; 299 | } 300 | .CodeMirror-scrollbar-filler { 301 | right: 0; 302 | bottom: 0; 303 | } 304 | .CodeMirror-gutter-filler { 305 | left: 0; 306 | bottom: 0; 307 | } 308 | 309 | .CodeMirror-gutters { 310 | position: absolute; 311 | left: 0; 312 | top: 0; 313 | min-height: 100%; 314 | z-index: 3; 315 | } 316 | .CodeMirror-gutter { 317 | white-space: normal; 318 | height: 100%; 319 | display: inline-block; 320 | vertical-align: top; 321 | margin-bottom: -50px; 322 | } 323 | .CodeMirror-gutter-wrapper { 324 | position: absolute; 325 | z-index: 4; 326 | background: none !important; 327 | border: none !important; 328 | } 329 | .CodeMirror-gutter-background { 330 | position: absolute; 331 | top: 0; 332 | bottom: 0; 333 | z-index: 4; 334 | } 335 | .CodeMirror-gutter-elt { 336 | position: absolute; 337 | cursor: default; 338 | z-index: 4; 339 | } 340 | .CodeMirror-gutter-wrapper ::selection { 341 | background-color: transparent; 342 | } 343 | .CodeMirror-gutter-wrapper ::-moz-selection { 344 | background-color: transparent; 345 | } 346 | 347 | .CodeMirror-lines { 348 | cursor: text; 349 | min-height: 1px; /* prevents collapsing before first draw */ 350 | } 351 | .CodeMirror pre.CodeMirror-line, 352 | .CodeMirror pre.CodeMirror-line-like { 353 | /* Reset some styles that the rest of the page might have set */ 354 | -moz-border-radius: 0; 355 | -webkit-border-radius: 0; 356 | border-radius: 0; 357 | border-width: 0; 358 | background: transparent; 359 | font-family: inherit; 360 | font-size: inherit; 361 | margin: 0; 362 | white-space: pre; 363 | word-wrap: normal; 364 | line-height: inherit; 365 | color: inherit; 366 | z-index: 2; 367 | position: relative; 368 | overflow: visible; 369 | -webkit-tap-highlight-color: transparent; 370 | -webkit-font-variant-ligatures: contextual; 371 | font-variant-ligatures: contextual; 372 | } 373 | .CodeMirror-wrap pre.CodeMirror-line, 374 | .CodeMirror-wrap pre.CodeMirror-line-like { 375 | word-wrap: break-word; 376 | white-space: pre-wrap; 377 | word-break: normal; 378 | } 379 | 380 | .CodeMirror-linebackground { 381 | position: absolute; 382 | left: 0; 383 | right: 0; 384 | top: 0; 385 | bottom: 0; 386 | z-index: 0; 387 | } 388 | 389 | .CodeMirror-linewidget { 390 | position: relative; 391 | z-index: 2; 392 | padding: 0.1px; /* Force widget margins to stay inside of the container */ 393 | } 394 | 395 | .CodeMirror-widget { 396 | } 397 | 398 | .CodeMirror-rtl pre { 399 | direction: rtl; 400 | } 401 | 402 | .CodeMirror-code { 403 | outline: none; 404 | } 405 | 406 | /* Force content-box sizing for the elements where we expect it */ 407 | .CodeMirror-scroll, 408 | .CodeMirror-sizer, 409 | .CodeMirror-gutter, 410 | .CodeMirror-gutters, 411 | .CodeMirror-linenumber { 412 | -moz-box-sizing: content-box; 413 | box-sizing: content-box; 414 | } 415 | 416 | .CodeMirror-measure { 417 | position: absolute; 418 | width: 100%; 419 | height: 0; 420 | overflow: hidden; 421 | visibility: hidden; 422 | } 423 | 424 | .CodeMirror-cursor { 425 | position: absolute; 426 | pointer-events: none; 427 | } 428 | .CodeMirror-measure pre { 429 | position: static; 430 | } 431 | 432 | div.CodeMirror-cursors { 433 | visibility: hidden; 434 | position: relative; 435 | z-index: 3; 436 | } 437 | div.CodeMirror-dragcursors { 438 | visibility: visible; 439 | } 440 | 441 | .CodeMirror-focused div.CodeMirror-cursors { 442 | visibility: visible; 443 | } 444 | 445 | .CodeMirror-selected { 446 | background: #d9d9d9; 447 | } 448 | .CodeMirror-focused .CodeMirror-selected { 449 | background: #d7d4f0; 450 | } 451 | .CodeMirror-crosshair { 452 | cursor: crosshair; 453 | } 454 | .CodeMirror-line::selection, 455 | .CodeMirror-line > span::selection, 456 | .CodeMirror-line > span > span::selection { 457 | background: #d7d4f0; 458 | } 459 | .CodeMirror-line::-moz-selection, 460 | .CodeMirror-line > span::-moz-selection, 461 | .CodeMirror-line > span > span::-moz-selection { 462 | background: #d7d4f0; 463 | } 464 | 465 | .cm-searching { 466 | background-color: #ffa; 467 | background-color: rgba(255, 255, 0, 0.4); 468 | } 469 | 470 | /* Used to force a border model for a node */ 471 | .cm-force-border { 472 | padding-right: 0.1px; 473 | } 474 | 475 | @media print { 476 | /* Hide the cursor when printing */ 477 | .CodeMirror div.CodeMirror-cursors { 478 | visibility: hidden; 479 | } 480 | } 481 | 482 | /* See issue #2901 */ 483 | .cm-tab-wrap-hack:after { 484 | content: ''; 485 | } 486 | 487 | /* Help users use markselection to safely style text background */ 488 | span.CodeMirror-selectedtext { 489 | background: none; 490 | } 491 | 492 | .cm-s-material.CodeMirror { 493 | background-color: #263238; 494 | color: #eeffff; 495 | } 496 | 497 | .cm-s-material .CodeMirror-gutters { 498 | background: #263238; 499 | color: #546e7a; 500 | border: none; 501 | } 502 | 503 | .cm-s-material .CodeMirror-guttermarker, 504 | .cm-s-material .CodeMirror-guttermarker-subtle, 505 | .cm-s-material .CodeMirror-linenumber { 506 | color: #546e7a; 507 | } 508 | 509 | .cm-s-material .CodeMirror-cursor { 510 | border-left: 1px solid #ffcc00; 511 | } 512 | 513 | .cm-s-material div.CodeMirror-selected { 514 | background: rgba(128, 203, 196, 0.2); 515 | } 516 | 517 | .cm-s-material.CodeMirror-focused div.CodeMirror-selected { 518 | background: rgba(128, 203, 196, 0.2); 519 | } 520 | 521 | .cm-s-material .CodeMirror-line::selection, 522 | .cm-s-material .CodeMirror-line > span::selection, 523 | .cm-s-material .CodeMirror-line > span > span::selection { 524 | background: rgba(128, 203, 196, 0.2); 525 | } 526 | 527 | .cm-s-material .CodeMirror-line::-moz-selection, 528 | .cm-s-material .CodeMirror-line > span::-moz-selection, 529 | .cm-s-material .CodeMirror-line > span > span::-moz-selection { 530 | background: rgba(128, 203, 196, 0.2); 531 | } 532 | 533 | .cm-s-material .CodeMirror-activeline-background { 534 | background: rgba(0, 0, 0, 0.5); 535 | } 536 | 537 | .cm-s-material .cm-keyword { 538 | color: #c792ea; 539 | } 540 | 541 | .cm-s-material .cm-operator { 542 | color: #89ddff; 543 | } 544 | 545 | .cm-s-material .cm-variable-2 { 546 | color: #eeffff; 547 | } 548 | 549 | .cm-s-material .cm-variable-3, 550 | .cm-s-material .cm-type { 551 | color: #f07178; 552 | } 553 | 554 | .cm-s-material .cm-builtin { 555 | color: #ffcb6b; 556 | } 557 | 558 | .cm-s-material .cm-atom { 559 | color: #f78c6c; 560 | } 561 | 562 | .cm-s-material .cm-number { 563 | color: #ff5370; 564 | } 565 | 566 | .cm-s-material .cm-def { 567 | color: #82aaff; 568 | } 569 | 570 | .cm-s-material .cm-string { 571 | color: #c3e88d; 572 | } 573 | 574 | .cm-s-material .cm-string-2 { 575 | color: #f07178; 576 | } 577 | 578 | .cm-s-material .cm-comment { 579 | color: #546e7a; 580 | } 581 | 582 | .cm-s-material .cm-variable { 583 | color: #f07178; 584 | } 585 | 586 | .cm-s-material .cm-tag { 587 | color: #ff5370; 588 | } 589 | 590 | .cm-s-material .cm-meta { 591 | color: #ffcb6b; 592 | } 593 | 594 | .cm-s-material .cm-attribute { 595 | color: #c792ea; 596 | } 597 | 598 | .cm-s-material .cm-property { 599 | color: #c792ea; 600 | } 601 | 602 | .cm-s-material .cm-qualifier { 603 | color: #decb6b; 604 | } 605 | 606 | .cm-s-material .cm-variable-3, 607 | .cm-s-material .cm-type { 608 | color: #decb6b; 609 | } 610 | 611 | .cm-s-material .cm-error { 612 | color: rgba(255, 255, 255, 1); 613 | background-color: #ff5370; 614 | } 615 | 616 | .cm-s-material .CodeMirror-matchingbracket { 617 | text-decoration: underline; 618 | color: white !important; 619 | } 620 | 621 | .CodeMirror-hints { 622 | position: absolute; 623 | z-index: 10; 624 | overflow: hidden; 625 | list-style: none; 626 | 627 | margin: 0; 628 | padding: 2px; 629 | 630 | -webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2); 631 | -moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2); 632 | box-shadow: 2px 3px 5px rgba(0, 0, 0, 0.2); 633 | border-radius: 3px; 634 | border: 1px solid white; 635 | 636 | background: #555; 637 | font-size: 1rem; 638 | font-family: monospace; 639 | 640 | max-height: 30em; 641 | overflow-y: auto; 642 | } 643 | 644 | .CodeMirror-hint { 645 | margin: 0; 646 | padding: 0 4px; 647 | border-radius: 2px; 648 | white-space: pre; 649 | color: #fff; 650 | cursor: pointer; 651 | } 652 | 653 | li.CodeMirror-hint-active { 654 | background: #08f; 655 | color: white; 656 | } 657 | -------------------------------------------------------------------------------- /public/patterns/firewalls: -------------------------------------------------------------------------------- 1 | # NetScreen firewall logs 2 | NETSCREENSESSIONLOG %{SYSLOGTIMESTAMP:timestamp} %{IPORHOST:[observer][hostname]} %{NOTSPACE:[observer][name]}: (?<[observer][product]>NetScreen) device_id=%{WORD:[netscreen][device_id]} .*?(system-\w+-%{NONNEGINT:[event][code]}\(%{WORD:[netscreen][session][type]}\))?: start_time="%{DATA:[netscreen][session][start_time]}" duration=%{INT:[netscreen][session][duration]:int} policy_id=%{INT:[netscreen][policy_id]} service=%{DATA:[netscreen][service]} proto=%{INT:[netscreen][protocol_number]:int} src zone=%{WORD:[observer][ingress][zone]} dst zone=%{WORD:[observer][egress][zone]} action=%{WORD:[event][action]} sent=%{INT:[source][bytes]:int} rcvd=%{INT:[destination][bytes]:int} src=%{IPORHOST:[source][address]} dst=%{IPORHOST:[destination][address]}(?: src_port=%{INT:[source][port]:int} dst_port=%{INT:[destination][port]:int})?(?: src-xlated ip=%{IP:[source][nat][ip]} port=%{INT:[source][nat][port]:int} dst-xlated ip=%{IP:[destination][nat][ip]} port=%{INT:[destination][nat][port]:int})?(?: session_id=%{INT:[netscreen][session][id]} reason=%{GREEDYDATA:[netscreen][session][reason]})? 3 | # :long - %{INT:[source][bytes]:int} 4 | # :long - %{INT:[destination][bytes]:int} 5 | 6 | #== Cisco ASA == 7 | CISCO_TAGGED_SYSLOG ^<%{POSINT:[log][syslog][priority]:int}>%{CISCOTIMESTAMP:timestamp}( %{SYSLOGHOST:[host][hostname]})? ?: %%{CISCOTAG:[cisco][asa][tag]}: 8 | CISCOTIMESTAMP %{MONTH} +%{MONTHDAY}(?: %{YEAR})? %{TIME} 9 | CISCOTAG [A-Z0-9]+-%{INT}-(?:[A-Z0-9_]+) 10 | # Common Particles 11 | CISCO_ACTION Built|Teardown|Deny|Denied|denied|requested|permitted|denied by ACL|discarded|est-allowed|Dropping|created|deleted 12 | CISCO_REASON Duplicate TCP SYN|Failed to locate egress interface|Invalid transport field|No matching connection|DNS Response|DNS Query|(?:%{WORD}\s*)* 13 | CISCO_DIRECTION Inbound|inbound|Outbound|outbound 14 | CISCO_INTERVAL first hit|%{INT}-second interval 15 | CISCO_XLATE_TYPE static|dynamic 16 | # helpers 17 | CISCO_HITCOUNT_INTERVAL hit-cnt %{INT:[cisco][asa][hit_count]:int} (?:first hit|%{INT:[cisco][asa][interval]:int}-second interval) 18 | CISCO_SRC_IP_USER %{NOTSPACE:[observer][ingress][interface][name]}:%{IP:[source][ip]}(?:\(%{DATA:[source][user][name]}\))? 19 | CISCO_DST_IP_USER %{NOTSPACE:[observer][egress][interface][name]}:%{IP:[destination][ip]}(?:\(%{DATA:[destination][user][name]}\))? 20 | CISCO_SRC_HOST_PORT_USER %{NOTSPACE:[observer][ingress][interface][name]}:(?:(?:%{IP:[source][ip]})|(?:%{HOSTNAME:[source][address]}))(?:/%{INT:[source][port]:int})?(?:\(%{DATA:[source][user][name]}\))? 21 | CISCO_DST_HOST_PORT_USER %{NOTSPACE:[observer][egress][interface][name]}:(?:(?:%{IP:[destination][ip]})|(?:%{HOSTNAME:[destination][address]}))(?:/%{INT:[destination][port]:int})?(?:\(%{DATA:[destination][user][name]}\))? 22 | # ASA-1-104001 23 | CISCOFW104001 \((?:Primary|Secondary)\) Switching to ACTIVE - %{GREEDYDATA:[event][reason]} 24 | # ASA-1-104002 25 | CISCOFW104002 \((?:Primary|Secondary)\) Switching to STANDBY - %{GREEDYDATA:[event][reason]} 26 | # ASA-1-104003 27 | CISCOFW104003 \((?:Primary|Secondary)\) Switching to FAILED\. 28 | # ASA-1-104004 29 | CISCOFW104004 \((?:Primary|Secondary)\) Switching to OK\. 30 | # ASA-1-105003 31 | CISCOFW105003 \((?:Primary|Secondary)\) Monitoring on [Ii]nterface %{NOTSPACE:[network][interface][name]} waiting 32 | # ASA-1-105004 33 | CISCOFW105004 \((?:Primary|Secondary)\) Monitoring on [Ii]nterface %{NOTSPACE:[network][interface][name]} normal 34 | # ASA-1-105005 35 | CISCOFW105005 \((?:Primary|Secondary)\) Lost Failover communications with mate on [Ii]nterface %{NOTSPACE:[network][interface][name]} 36 | # ASA-1-105008 37 | CISCOFW105008 \((?:Primary|Secondary)\) Testing [Ii]nterface %{NOTSPACE:[network][interface][name]} 38 | # ASA-1-105009 39 | CISCOFW105009 \((?:Primary|Secondary)\) Testing on [Ii]nterface %{NOTSPACE:[network][interface][name]} (?:Passed|Failed) 40 | # ASA-2-106001 41 | CISCOFW106001 %{CISCO_DIRECTION:[cisco][asa][network][direction]} %{WORD:[cisco][asa][network][transport]} connection %{CISCO_ACTION:[cisco][asa][outcome]} from %{IP:[source][ip]}/%{INT:[source][port]:int} to %{IP:[destination][ip]}/%{INT:[destination][port]:int} flags %{DATA:[cisco][asa][tcp_flags]} on interface %{NOTSPACE:[observer][egress][interface][name]} 42 | # ASA-2-106006, ASA-2-106007, ASA-2-106010 43 | CISCOFW106006_106007_106010 %{CISCO_ACTION:[cisco][asa][outcome]} %{CISCO_DIRECTION:[cisco][asa][network][direction]} %{WORD:[cisco][asa][network][transport]} (?:from|src) %{IP:[source][ip]}/%{INT:[source][port]:int}(?:\(%{DATA:[source][user][name]}\))? (?:to|dst) %{IP:[destination][ip]}/%{INT:[destination][port]:int}(?:\(%{DATA:[destination][user][name]}\))? (?:(?:on interface %{NOTSPACE:[observer][egress][interface][name]})|(?:due to %{CISCO_REASON:[event][reason]})) 44 | # ASA-3-106014 45 | CISCOFW106014 %{CISCO_ACTION:[cisco][asa][outcome]} %{CISCO_DIRECTION:[cisco][asa][network][direction]} %{WORD:[cisco][asa][network][transport]} src %{CISCO_SRC_IP_USER} dst %{CISCO_DST_IP_USER}\s?\(type %{INT:[cisco][asa][icmp_type]:int}, code %{INT:[cisco][asa][icmp_code]:int}\) 46 | # ASA-6-106015 47 | CISCOFW106015 %{CISCO_ACTION:[cisco][asa][outcome]} %{WORD:[cisco][asa][network][transport]} \(%{DATA:[cisco][asa][rule_name]}\) from %{IP:[source][ip]}/%{INT:[source][port]:int} to %{IP:[destination][ip]}/%{INT:[destination][port]:int} flags %{DATA:[cisco][asa][tcp_flags]} on interface %{NOTSPACE:[observer][egress][interface][name]} 48 | # ASA-1-106021 49 | CISCOFW106021 %{CISCO_ACTION:[cisco][asa][outcome]} %{WORD:[cisco][asa][network][transport]} reverse path check from %{IP:[source][ip]} to %{IP:[destination][ip]} on interface %{NOTSPACE:[observer][egress][interface][name]} 50 | # ASA-4-106023 51 | CISCOFW106023 %{CISCO_ACTION:[cisco][asa][outcome]}(?: protocol)? %{WORD:[cisco][asa][network][transport]} src %{CISCO_SRC_HOST_PORT_USER} dst %{CISCO_DST_HOST_PORT_USER}( \(type %{INT:[cisco][asa][icmp_type]:int}, code %{INT:[cisco][asa][icmp_code]:int}\))? by access-group "?%{DATA:[cisco][asa][rule_name]}"? \[%{DATA:[@metadata][cisco][asa][hashcode1]}, %{DATA:[@metadata][cisco][asa][hashcode2]}\] 52 | # ASA-4-106100, ASA-4-106102, ASA-4-106103 53 | CISCOFW106100_2_3 access-list %{NOTSPACE:[cisco][asa][rule_name]} %{CISCO_ACTION:[cisco][asa][outcome]} %{WORD:[cisco][asa][network][transport]} for user '%{DATA:[user][name]}' %{DATA:[observer][ingress][interface][name]}/%{IP:[source][ip]}\(%{INT:[source][port]:int}\) -> %{DATA:[observer][egress][interface][name]}/%{IP:[destination][ip]}\(%{INT:[destination][port]:int}\) %{CISCO_HITCOUNT_INTERVAL} \[%{DATA:[@metadata][cisco][asa][hashcode1]}, %{DATA:[@metadata][cisco][asa][hashcode2]}\] 54 | # ASA-5-106100 55 | CISCOFW106100 access-list %{NOTSPACE:[cisco][asa][rule_name]} %{CISCO_ACTION:[cisco][asa][outcome]} %{WORD:[cisco][asa][network][transport]} %{DATA:[observer][ingress][interface][name]}/%{IP:[source][ip]}\(%{INT:[source][port]:int}\)(?:\(%{DATA:[source][user][name]}\))? -> %{DATA:[observer][egress][interface][name]}/%{IP:[destination][ip]}\(%{INT:[destination][port]:int}\)(?:\(%{DATA:[source][user][name]}\))? hit-cnt %{INT:[cisco][asa][hit_count]:int} %{CISCO_INTERVAL} \[%{DATA:[@metadata][cisco][asa][hashcode1]}, %{DATA:[@metadata][cisco][asa][hashcode2]}\] 56 | # ASA-5-304001 57 | CISCOFW304001 %{IP:[source][ip]}(?:\(%{DATA:[source][user][name]}\))? Accessed URL %{IP:[destination][ip]}:%{GREEDYDATA:[url][original]} 58 | # ASA-6-110002 59 | CISCOFW110002 %{CISCO_REASON:[event][reason]} for %{WORD:[cisco][asa][network][transport]} from %{DATA:[observer][ingress][interface][name]}:%{IP:[source][ip]}/%{INT:[source][port]:int} to %{IP:[destination][ip]}/%{INT:[destination][port]:int} 60 | # ASA-6-302010 61 | CISCOFW302010 %{INT:[cisco][asa][connections][in_use]:int} in use, %{INT:[cisco][asa][connections][most_used]:int} most used 62 | # ASA-6-302013, ASA-6-302014, ASA-6-302015, ASA-6-302016 63 | CISCOFW302013_302014_302015_302016 %{CISCO_ACTION:[cisco][asa][outcome]}(?: %{CISCO_DIRECTION:[cisco][asa][network][direction]})? %{WORD:[cisco][asa][network][transport]} connection %{INT:[cisco][asa][connection_id]} for %{NOTSPACE:[observer][ingress][interface][name]}:%{IP:[source][ip]}/%{INT:[source][port]:int}(?: \(%{IP:[source][nat][ip]}/%{INT:[source][nat][port]:int}\))?(?:\(%{DATA:[source][user][name]}\))? to %{NOTSPACE:[observer][egress][interface][name]}:%{IP:[destination][ip]}/%{INT:[destination][port]:int}( \(%{IP:[destination][nat][ip]}/%{INT:[destination][nat][port]:int}\))?(?:\(%{DATA:[destination][user][name]}\))?( duration %{TIME:[cisco][asa][duration]} bytes %{INT:[network][bytes]:int})?(?: %{CISCO_REASON:[event][reason]})?(?: \(%{DATA:[user][name]}\))? 64 | # :long - %{INT:[network][bytes]:int} 65 | # ASA-6-302020, ASA-6-302021 66 | CISCOFW302020_302021 %{CISCO_ACTION:[cisco][asa][outcome]}(?: %{CISCO_DIRECTION:[cisco][asa][network][direction]})? %{WORD:[cisco][asa][network][transport]} connection for faddr %{IP:[destination][ip]}/%{INT:[cisco][asa][icmp_seq]:int}(?:\(%{DATA:[destination][user][name]}\))? gaddr %{IP:[source][nat][ip]}/%{INT:[cisco][asa][icmp_type]:int} laddr %{IP:[source][ip]}/%{INT}(?: \(%{DATA:[source][user][name]}\))? 67 | # ASA-6-305011 68 | CISCOFW305011 %{CISCO_ACTION:[cisco][asa][outcome]} %{CISCO_XLATE_TYPE} %{WORD:[cisco][asa][network][transport]} translation from %{DATA:[observer][ingress][interface][name]}:%{IP:[source][ip]}(/%{INT:[source][port]:int})?(?:\(%{DATA:[source][user][name]}\))? to %{DATA:[observer][egress][interface][name]}:%{IP:[destination][ip]}/%{INT:[destination][port]:int} 69 | # ASA-3-313001, ASA-3-313004, ASA-3-313008 70 | CISCOFW313001_313004_313008 %{CISCO_ACTION:[cisco][asa][outcome]} %{WORD:[cisco][asa][network][transport]} type=%{INT:[cisco][asa][icmp_type]:int}, code=%{INT:[cisco][asa][icmp_code]:int} from %{IP:[source][ip]} on interface %{NOTSPACE:[observer][egress][interface][name]}(?: to %{IP:[destination][ip]})? 71 | # ASA-4-313005 72 | CISCOFW313005 %{CISCO_REASON:[event][reason]} for %{WORD:[cisco][asa][network][transport]} error message: %{WORD} src %{CISCO_SRC_IP_USER} dst %{CISCO_DST_IP_USER} \(type %{INT:[cisco][asa][icmp_type]:int}, code %{INT:[cisco][asa][icmp_code]:int}\) on %{NOTSPACE} interface\.\s+Original IP payload: %{WORD:[cisco][asa][original_ip_payload][network][transport]} src %{IP:[cisco][asa][original_ip_payload][source][ip]}/%{INT:[cisco][asa][original_ip_payload][source][port]:int}(?:\(%{DATA:[cisco][asa][original_ip_payload][source][user][name]}\))? dst %{IP:[cisco][asa][original_ip_payload][destination][ip]}/%{INT:[cisco][asa][original_ip_payload][destination][port]:int}(?:\(%{DATA:[cisco][asa][original_ip_payload][destination][user][name]}\))? 73 | # ASA-5-321001 74 | CISCOFW321001 Resource '%{DATA:[cisco][asa][resource][name]}' limit of %{POSINT:[cisco][asa][resource][limit]:int} reached for system 75 | # ASA-4-402117 76 | CISCOFW402117 %{WORD:[cisco][asa][network][type]}: Received a non-IPSec packet \(protocol=\s?%{WORD:[cisco][asa][network][transport]}\) from %{IP:[source][ip]} to %{IP:[destination][ip]}\.? 77 | # ASA-4-402119 78 | CISCOFW402119 %{WORD:[cisco][asa][network][type]}: Received an %{WORD:[cisco][asa][ipsec][protocol]} packet \(SPI=\s?%{DATA:[cisco][asa][ipsec][spi]}, sequence number=\s?%{DATA:[cisco][asa][ipsec][seq_num]}\) from %{IP:[source][ip]} \(user=\s?%{DATA:[source][user][name]}\) to %{IP:[destination][ip]} that failed anti-replay checking\.? 79 | # ASA-4-419001 80 | CISCOFW419001 %{CISCO_ACTION:[cisco][asa][outcome]} %{WORD:[cisco][asa][network][transport]} packet from %{NOTSPACE:[observer][ingress][interface][name]}:%{IP:[source][ip]}/%{INT:[source][port]:int} to %{NOTSPACE:[observer][egress][interface][name]}:%{IP:[destination][ip]}/%{INT:[destination][port]:int}, reason: %{GREEDYDATA:[event][reason]} 81 | # ASA-4-419002 82 | CISCOFW419002 %{CISCO_REASON:[event][reason]} from %{DATA:[observer][ingress][interface][name]}:%{IP:[source][ip]}/%{INT:[source][port]:int} to %{DATA:[observer][egress][interface][name]}:%{IP:[destination][ip]}/%{INT:[destination][port]:int} with different initial sequence number 83 | # ASA-4-500004 84 | CISCOFW500004 %{CISCO_REASON:[event][reason]} for protocol=%{WORD:[cisco][asa][network][transport]}, from %{IP:[source][ip]}/%{INT:[source][port]:int} to %{IP:[destination][ip]}/%{INT:[destination][port]:int} 85 | # ASA-6-602303, ASA-6-602304 86 | CISCOFW602303_602304 %{WORD:[cisco][asa][network][type]}: An %{CISCO_DIRECTION:[cisco][asa][network][direction]} %{DATA:[cisco][asa][ipsec][tunnel_type]} SA \(SPI=\s?%{DATA:[cisco][asa][ipsec][spi]}\) between %{IP:[source][ip]} and %{IP:[destination][ip]} \(user=\s?%{DATA:[source][user][name]}\) has been %{CISCO_ACTION:[cisco][asa][outcome]} 87 | # ASA-7-710001, ASA-7-710002, ASA-7-710003, ASA-7-710005, ASA-7-710006 88 | CISCOFW710001_710002_710003_710005_710006 %{WORD:[cisco][asa][network][transport]} (?:request|access) %{CISCO_ACTION:[cisco][asa][outcome]} from %{IP:[source][ip]}/%{INT:[source][port]:int} to %{DATA:[observer][egress][interface][name]}:%{IP:[destination][ip]}/%{INT:[destination][port]:int} 89 | # ASA-6-713172 90 | CISCOFW713172 Group = %{DATA:[cisco][asa][source][group]}, IP = %{IP:[source][ip]}, Automatic NAT Detection Status:\s+Remote end\s*%{DATA:[@metadata][cisco][asa][remote_nat]}\s*behind a NAT device\s+This\s+end\s*%{DATA:[@metadata][cisco][asa][local_nat]}\s*behind a NAT device 91 | # ASA-4-733100 92 | CISCOFW733100 \[\s*%{DATA:[cisco][asa][burst][object]}\s*\] drop %{DATA:[cisco][asa][burst][id]} exceeded. Current burst rate is %{INT:[cisco][asa][burst][current_rate]:int} per second, max configured rate is %{INT:[cisco][asa][burst][configured_rate]:int}; Current average rate is %{INT:[cisco][asa][burst][avg_rate]:int} per second, max configured rate is %{INT:[cisco][asa][burst][configured_avg_rate]:int}; Cumulative total count is %{INT:[cisco][asa][burst][cumulative_count]:int} 93 | #== End Cisco ASA == 94 | 95 | 96 | IPTABLES_TCP_FLAGS (CWR |ECE |URG |ACK |PSH |RST |SYN |FIN )* 97 | IPTABLES_TCP_PART (?:SEQ=%{INT:[iptables][tcp][seq]:int}\s+)?(?:ACK=%{INT:[iptables][tcp][ack]:int}\s+)?WINDOW=%{INT:[iptables][tcp][window]:int}\s+RES=0x%{BASE16NUM:[iptables][tcp_reserved_bits]}\s+%{IPTABLES_TCP_FLAGS:[iptables][tcp][flags]} 98 | 99 | IPTABLES4_FRAG (?:(?<= )(?:CE|DF|MF))* 100 | IPTABLES4_PART SRC=%{IPV4:[source][ip]}\s+DST=%{IPV4:[destination][ip]}\s+LEN=(?:%{INT:[iptables][length]:int})?\s+TOS=(?:0|0x%{BASE16NUM:[iptables][tos]})?\s+PREC=(?:0x%{BASE16NUM:[iptables][precedence_bits]})?\s+TTL=(?:%{INT:[iptables][ttl]:int})?\s+ID=(?:%{INT:[iptables][id]})?\s+(?:%{IPTABLES4_FRAG:[iptables][fragment_flags]})?(?:\s+FRAG: %{INT:[iptables][fragment_offset]:int})? 101 | IPTABLES6_PART SRC=%{IPV6:[source][ip]}\s+DST=%{IPV6:[destination][ip]}\s+LEN=(?:%{INT:[iptables][length]:int})?\s+TC=(?:0|0x%{BASE16NUM:[iptables][tos]})?\s+HOPLIMIT=(?:%{INT:[iptables][ttl]:int})?\s+FLOWLBL=(?:%{INT:[iptables][flow_label]})? 102 | 103 | IPTABLES IN=(?:%{NOTSPACE:[observer][ingress][interface][name]})?\s+OUT=(?:%{NOTSPACE:[observer][egress][interface][name]})?\s+(?:MAC=(?:%{COMMONMAC:[destination][mac]})?(?::%{COMMONMAC:[source][mac]})?(?::[A-Fa-f0-9]{2}:[A-Fa-f0-9]{2})?\s+)?(:?%{IPTABLES4_PART}|%{IPTABLES6_PART}).*?PROTO=(?:%{WORD:[network][transport]})?\s+SPT=(?:%{INT:[source][port]:int})?\s+DPT=(?:%{INT:[destination][port]:int})?\s+(?:%{IPTABLES_TCP_PART})? 104 | 105 | # Shorewall firewall logs 106 | SHOREWALL (?:%{SYSLOGTIMESTAMP:timestamp}) (?:%{WORD:[observer][hostname]}) .*Shorewall:(?:%{WORD:[shorewall][firewall][type]})?:(?:%{WORD:[shorewall][firewall][action]})?.*%{IPTABLES} 107 | #== End Shorewall 108 | #== SuSE Firewall 2 == 109 | SFW2_LOG_PREFIX SFW2\-INext\-%{NOTSPACE:[suse][firewall][action]} 110 | SFW2 ((?:%{SYSLOGTIMESTAMP:timestamp})|(?:%{TIMESTAMP_ISO8601:timestamp}))\s*%{HOSTNAME:[observer][hostname]}.*?%{SFW2_LOG_PREFIX:[suse][firewall][log_prefix]}\s*%{IPTABLES} 111 | #== End SuSE == 112 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState, useRef } from "react"; 2 | import { GrokCollection } from "grok-js"; 3 | import { Navbar } from "./components/Navbar"; 4 | import { UnControlled as CodeMirrorTextarea } from "react-codemirror2"; 5 | import { Book, Copy, Share2, Trash2, Check, PlusSquare, DownloadCloud, ExternalLink } from "react-feather"; 6 | import CodeMirror from "codemirror"; 7 | import "codemirror/addon/mode/simple"; 8 | import "codemirror/addon/hint/show-hint"; 9 | import "codemirror/mode/javascript/javascript"; 10 | import "codemirror/addon/selection/mark-selection"; 11 | import "codemirror/addon/scroll/simplescrollbars"; 12 | import grokMode from "./codemirror/grok"; 13 | import { LoadModal } from "./components/LoadModal"; 14 | import { ShareModal } from "./components/ShareModal"; 15 | import { Ad } from "./components/Ad"; 16 | import { CustomPatternModal } from "./components/CustomPatternModal"; 17 | import Select from "react-select"; 18 | import useLocalStorage from "./hooks/useLocalStorage"; 19 | import { MorePatternsModal } from "./components/MorePatternsModal"; 20 | 21 | function App() { 22 | CodeMirror.defineSimpleMode("grokMode", grokMode); 23 | 24 | const urlSearchParams = new URLSearchParams(window.location.search); 25 | const qsParams = Object.fromEntries(urlSearchParams.entries()); 26 | 27 | const [groks] = useState(new GrokCollection()); 28 | let [pattern, setPattern] = useLocalStorage("gd-pattern", ""); 29 | let [sample, setSample] = useLocalStorage( 30 | "gd-sample", 31 | "Your sample logs go here\nStart typing a pattern above for suggestions, e.g. %{WORD:word}\nNamed capture groups work too, e.g. (?pattern)" 32 | ); 33 | let [result, setResult] = useState(""); 34 | let [samplesEditor, setSamplesEditor] = useState(); 35 | let [patterns, setPatterns] = useState([]); 36 | let [customPatterns, setCustomPatterns] = useLocalStorage("gd-custom", []); 37 | let [showModal, setShowModal] = useState(null); 38 | let [matchCount, setMatchCount] = useState(0); 39 | let [sampleCount, setSampleCount] = useState(0); 40 | 41 | const defaultCollections = [ 42 | { value: "custom", label: "Custom", active: true }, 43 | { value: "aws", label: "AWS", active: false }, 44 | { value: "bacula", label: "Bacula", active: false }, 45 | { value: "bind", label: "BIND", active: false }, 46 | { value: "bro", label: "Bro", active: false }, 47 | { value: "exim", label: "Exim", active: false }, 48 | { value: "firewalls", label: "Firewalls", active: false }, 49 | { value: "grok-patterns", label: "Grok Patterns", active: true }, 50 | { value: "haproxy", label: "HAProxy", active: false }, 51 | { value: "httpd", label: "Httpd", active: false }, 52 | { value: "java", label: "Java", active: false }, 53 | { value: "junos", label: "Junos", active: false }, 54 | { value: "linux-syslog", label: "Syslog", active: false }, 55 | { value: "maven", label: "Maven", active: false }, 56 | { value: "mcollective", label: "MCollective", active: false }, 57 | { value: "mongodb", label: "MongoDB", active: false }, 58 | { value: "nagios", label: "Nagios", active: false }, 59 | { value: "postfix", label: "Postfix", active: false }, 60 | { value: "postgresql", label: "PostgreSQL", active: false }, 61 | { value: "rails", label: "Rails", active: false }, 62 | { value: "redis", label: "Redis", active: false }, 63 | { value: "ruby", label: "Ruby", active: false }, 64 | { value: "squid", label: "Squid", active: false }, 65 | { value: "zeek", label: "Zeek", active: false }, 66 | ]; 67 | 68 | let [collections, setCollections] = useLocalStorage("gd-collections", defaultCollections); 69 | 70 | const firstUpdate = useRef(true); 71 | 72 | const loadExternalPatterns = async () => { 73 | await Promise.all( 74 | collections.filter((c) => c.active && c.value !== "custom").map((c) => loadCollection(c.value, c.label, c.url)) 75 | ); 76 | }; 77 | 78 | const loadCustomPatterns = async () => { 79 | customPatterns.map((p) => { 80 | groks.createPattern(p.pattern, p.id); 81 | }); 82 | }; 83 | 84 | useEffect(() => { 85 | setPatterns((patterns) => [ 86 | ...patterns, 87 | ...customPatterns.map((p) => { 88 | return { id: p.id, collection: "custom" }; 89 | }), 90 | ]); 91 | }, [customPatterns]); 92 | 93 | const onLoad = async () => { 94 | // load query string parameters (if there are any) 95 | if (qsParams.pattern) setPattern(qsParams.pattern); 96 | if (qsParams.sample) setSample(qsParams.sample); 97 | await loadExternalPatterns(); 98 | await loadCustomPatterns(); 99 | 100 | // add any collections in default that user does not have in localstorage store 101 | const newCollections = defaultCollections.filter((d) => { 102 | return !collections.map((c) => c.value).includes(d.value); 103 | }); 104 | if (newCollections.length) { 105 | setCollections((collections) => [...collections, ...newCollections]); 106 | } 107 | }; 108 | 109 | const loadCollection = async (value, label, url) => { 110 | if (patterns.find((p) => p.collection === value)) return; 111 | label = label || value; 112 | url = url || "/patterns/" + value; 113 | try { 114 | const newPatterns = await groks.load(url).then((ids) => { 115 | return ids.map((id) => { 116 | if (patterns.includes({ id, collection: value })) return; 117 | return { id, collection: value }; 118 | }); 119 | }); 120 | setPatterns((patterns) => [...patterns, ...newPatterns.flat()]); 121 | const updatedCollection = [...collections].map((c) => { 122 | if (c.value == value) { 123 | return { ...c, active: true }; 124 | } else { 125 | return c; 126 | } 127 | }); 128 | setCollections(updatedCollection); 129 | } catch (err) { 130 | console.log(err); 131 | } 132 | }; 133 | 134 | const parseSample = async (lineNumber) => { 135 | try { 136 | let p = groks.createPattern(pattern); 137 | let sampleLine = samplesEditor.getLine(lineNumber); 138 | let result = await p.parse(sampleLine); 139 | if (!result) return null; 140 | let matches = p.regexp.searchSync(sampleLine).filter((m) => m.length > 0); 141 | matches.forEach((m, i) => { 142 | let bgColor = i === 0 ? "rgb(230, 180, 50, 0.3)" : "rgb(127, 191, 63, 0.4)"; 143 | samplesEditor.markText( 144 | { line: lineNumber, ch: m.start }, 145 | { line: lineNumber, ch: m.end }, 146 | { css: "background-color: " + bgColor + " !important" } 147 | ); 148 | }); 149 | let data = {}; 150 | Object.keys(result).map((key, i) => { 151 | data[key] = +result[key] === 0 ? 0 : +result[key] || result[key]; 152 | }); 153 | return data; 154 | } catch (error) { 155 | console.error(error); 156 | } 157 | }; 158 | 159 | const handleParse = async () => { 160 | try { 161 | let output = []; 162 | const lines = samplesEditor.lineCount() - 1; 163 | for (let i = 0; i <= lines; i++) { 164 | samplesEditor.markText( 165 | { line: i, ch: 0 }, 166 | { line: i, ch: Infinity }, 167 | { css: "background-color: transparent !important" } 168 | ); 169 | let data = await parseSample(i); 170 | output.push(data); 171 | } 172 | setMatchCount(output.reduce((acc, val) => (acc += +(val !== null)), 0)); 173 | setSampleCount(output.length); 174 | setResult(JSON.stringify(output, null, 2)); 175 | } catch (error) { 176 | console.error(error); 177 | } 178 | }; 179 | 180 | useEffect(() => { 181 | onLoad(); 182 | }, []); 183 | 184 | useEffect(() => { 185 | if (firstUpdate.current) { 186 | firstUpdate.current = false; 187 | return; 188 | } 189 | let timeout = setTimeout(() => handleParse(), 250); 190 | return () => clearTimeout(timeout); 191 | }, [pattern, sample, patterns]); 192 | 193 | const handleChangePattern = (editor, data, value) => { 194 | setPattern(value); 195 | }; 196 | 197 | const handleSelectAction = async (newValue, actionMeta) => { 198 | const { action, option } = actionMeta; 199 | let newCollections = [...collections]; 200 | switch (action) { 201 | case "select-option": 202 | if (patterns.find((p) => p.collection === option.value)) { 203 | newCollections = newCollections.map((c) => { 204 | if (c.value === option.value) { 205 | return { ...c, active: true }; 206 | } else { 207 | return c; 208 | } 209 | }); 210 | setCollections(newCollections); 211 | } else { 212 | loadCollection(option.value, option.label, option.url); 213 | } 214 | break; 215 | case "remove-value": 216 | newCollections = newCollections.map((c) => 217 | newValue.map((nv) => nv.value).includes(c.value) ? { ...c, active: true } : { ...c, active: false } 218 | ); 219 | setCollections(newCollections); 220 | break; 221 | case "clear": 222 | newCollections = newCollections.map((c) => { 223 | return { ...c, active: false }; 224 | }); 225 | setCollections(newCollections); 226 | break; 227 | default: 228 | break; 229 | } 230 | }; 231 | 232 | const copyToClipboard = (text) => { 233 | navigator.clipboard.writeText(text); 234 | }; 235 | 236 | return ( 237 |
238 | 239 |
240 |
241 |
242 |
243 | 265 |
266 | 274 |
275 | 279 |
280 |
281 | 282 |
283 |
284 |
285 |
286 |

Grok Pattern

287 |
288 | copyToClipboard(pattern)} /> 289 |
290 |
291 | setShowModal("CUSTOM_PATTERN")} /> 292 |
293 |
294 | setShowModal("LOAD")} /> 295 |
296 |
297 | setShowModal("SHARE")} /> 298 |
299 |
300 | { 313 | let cursorPos = editor.getDoc().getCursor(); 314 | let lastTokenRegex = /%{([^:}]*)$/g; 315 | let keyword = lastTokenRegex.exec(pattern.substr(0, cursorPos.ch)); 316 | if (keyword !== null) { 317 | const activeCollections = collections.filter((c) => c.active).map((c) => c.value); 318 | return { 319 | from: { ...cursorPos, ch: cursorPos.ch - keyword[1].length }, 320 | to: cursorPos, 321 | list: patterns 322 | .filter((p) => activeCollections.includes(p.collection)) 323 | .filter((p) => RegExp(keyword[1], "i").test(p.id)) 324 | .map((p) => p.id), 325 | }; 326 | } 327 | }, 328 | }, 329 | }} 330 | onInputRead={(editor, change) => { 331 | CodeMirror.showHint(editor); 332 | }} 333 | value={pattern} 334 | onChange={handleChangePattern} 335 | autoCursor={false} 336 | /> 337 |
338 |
339 |
340 |

Samples

341 |
342 | copyToClipboard(sample)} /> 343 |
344 |
345 | setSample()} /> 346 |
347 |
348 | setSample(value)} 360 | autoCursor={false} 361 | editorDidMount={(editor) => { 362 | setSamplesEditor(editor); 363 | }} 364 | /> 365 |
366 |
367 |
368 |
369 |
370 |
371 |

Output

372 |
373 | copyToClipboard(result)} /> 374 |
375 |
376 |
377 | {!sampleCount ? <> : matchCount === sampleCount ? : <>} 378 | {matchCount} 379 | {"/"} 380 | {sampleCount} 381 |
382 |
383 | 394 |
395 |
396 | { 397 | { 398 | LOAD: ( 399 | 405 | ), 406 | SHARE: , 407 | CUSTOM_PATTERN: ( 408 | 417 | ), 418 | MORE_PATTERNS: ( 419 | 427 | ), 428 | }[showModal] 429 | } 430 |
431 |
432 | ); 433 | } 434 | 435 | export default App; 436 | --------------------------------------------------------------------------------