{"id":34195941,"url":"https://github.com/jackbister/logsuck","last_synced_at":"2026-03-11T07:02:25.519Z","repository":{"id":44763620,"uuid":"243616206","full_name":"JackBister/logsuck","owner":"JackBister","description":"Easy log aggregation, indexing and searching","archived":false,"fork":false,"pushed_at":"2025-08-01T09:28:12.000Z","size":1011,"stargazers_count":170,"open_issues_count":10,"forks_count":7,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-12-18T18:07:40.137Z","etag":null,"topics":["logging","logs","monitoring"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JackBister.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-27T21:02:54.000Z","updated_at":"2025-10-07T07:20:56.000Z","dependencies_parsed_at":"2024-01-05T17:30:30.909Z","dependency_job_id":"21a0f5ec-631e-4dbf-9368-d8340c69e2bf","html_url":"https://github.com/JackBister/logsuck","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/JackBister/logsuck","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JackBister%2Flogsuck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JackBister%2Flogsuck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JackBister%2Flogsuck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JackBister%2Flogsuck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JackBister","download_url":"https://codeload.github.com/JackBister/logsuck/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JackBister%2Flogsuck/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30373509,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T06:09:32.197Z","status":"ssl_error","status_checked_at":"2026-03-11T06:09:17.086Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["logging","logs","monitoring"],"created_at":"2025-12-15T17:02:43.203Z","updated_at":"2026-03-11T07:02:25.513Z","avatar_url":"https://github.com/JackBister.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Logsuck\n\n![CI Status](https://img.shields.io/github/actions/workflow/status/jackbister/logsuck/ci.yml?branch=master)\n![Apache License 2.0](https://img.shields.io/github/license/jackbister/logsuck)\n\nLogsuck is a program that makes it easier for you to deal with your logs. It serves a similar purpose to Splunk or the ELK stack. You can use it to search your logs, correlate logs from different log files with each other and set up alerts and dashboards based on your logs. On top of that, Logsuck is extremely simple to deploy, and is free.\n\nLogsuck does not currently aim to be able to ingest millions of events per second or to have every enterprise feature you can imagine. The target audience for Logsuck is smaller development teams or solo developers who need a powerful tool that is simple to set up and keep running.\n\nLogsuck is currently pre-1.0. This means that there may be changes made to the database schemas used internally by Logsuck which could cause incompatibilities between versions. If that occurs, you will need to delete your `logsuck.db` file before you can use the new version, which will result in your existing search index being deleted. You can work around this by running the new version in parallel with the old version for a while, until you feel like the data that is only in the old database is old enough to be irrelevant. After 1.0, if a schema change is made, a migration will be provided to handle the upgrade gracefully to the extent that it is possible.\n\n![a screenshot of the Logsuck GUI](https://jackbister.com/content/logsuck_v0_gui_mantine.png)\n\n- [Logsuck](#logsuck)\n  - [Getting started](#getting-started)\n    - [Single mode](#single-mode)\n    - [Forwarder/Recipient mode](#forwarderrecipient-mode)\n  - [Configuration](#configuration)\n    - [Command line options](#command-line-options)\n    - [JSON configuration](#json-configuration)\n  - [Search syntax](#search-syntax)\n    - [`[search]`](#search)\n      - [Fragments](#fragments)\n      - [Fields](#fields)\n    - [Commands](#commands)\n      - [`| rex [field=\u003cfield\u003e] \"\u003cregex\u003e\"`](#-rex-fieldfield-regex)\n      - [`| search startTime=\"\u003ctime\u003e\" endTime=\"\u003ctime\u003e\" \"\u003csearch\u003e\"`](#-search-starttimetime-endtimetime-search)\n      - [`| surrounding [count=\u003cnumber\u003e] eventId=\u003cid\u003e`](#-surrounding-countnumber-eventidid)\n      - [`| table \"\u003cfield1\u003e,\u003cfield2\u003e,...\"`](#-table-field1field2)\n      - [`| where \u003cfield1\u003e=\u003cvalue1\u003e \u003cfield2\u003e=\u003cvalue2\u003e...`](#-where-field1value1-field2value2)\n  - [Need help?](#need-help)\n  - [Building](#building)\n  - [Customizing using plugins](#customizing-using-plugins)\n  - [Upcoming features](#upcoming-features)\n\n## Getting started\n\nGetting started with Logsuck is easy. Logsuck can be ran in two different modes: Single mode or forwarder/recipient mode.\n\nSingle mode means you run Logsuck on a server which will both handle reading your log files and serving the Logsuck GUI. This is useful if you are running all of your applications on a single server, or you can even use it to run Logsuck locally to read logs while developing.\n\nForwarder/recipient mode means you have one recipient instance which will receive events over the network from several forwarder instances. The recipient will also serve the Logsuck GUI. This is useful if you have your applications spread out across multiple servers but want to be able to search them all in one central place.\n\nNote that the different modes of Logsuck do not require different builds of Logsuck. All Logsuck executables are capable of running in single mode, or running as forwarders or recipients.\n\nThe guides below assume that you are using a Linux distribution, but Logsuck executables are available for Windows as well.\n\n### Single mode\n\nTo run Logsuck in single mode, start off by downloading the Logsuck executable to the server:\n\n```sh\nwget https://github.com/JackBister/logsuck/releases/download/v0.6.0/logsuck-v0_6_0-x64-linux.zip\nunzip logsuck-v0_6_0-x64-linux.zip\n```\n\nNow you can run Logsuck and tell it to read its own logs:\n\n```sh\n./logsuck logsuck.txt 2\u003e logsuck.txt\n```\n\nLogsuck is now running. Navigate to http://localhost:8080 and you should see the GUI. Try pressing the search button while leaving the search field empty and you should find some events. Congratulations, you are now running Logsuck in single mode! Continue reading to learn more about configuring Logsuck.\n\n### Forwarder/Recipient mode\n\nSetting up Logsuck in forwarder/recipient mode is slightly more complicated. Lets again start off by downloading the Logsuck executable:\n\n```sh\nwget https://github.com/JackBister/logsuck/releases/download/v0.6.0/logsuck-v0_6_0-x64-linux.zip\nunzip logsuck-v0_6_0-x64-linux.zip\n```\n\nThis time, we will create two different directories which will be the working directories for each of the two Logsuck instances we need to run.\n\nStart the recipient:\n\n```sh\n./logsuck -hostname \"RECIPIENT\" -recipient \":8081\" logsuck-forwarder.txt 2\u003e logsuck-recipient.txt\n```\n\nNote that we tell the recipient to index the file `logsuck-forwarder.txt` because the recipient will tell the forwarder what files to index when it connects.\n\nOpen a new shell and start the forwarder:\n\n```sh\n./logsuck -forwarder \"http://localhost:8081\" -hostname \"FORWARDER\" 2\u003e logsuck-forwarder.txt\n```\n\nYou should now be able to navigate to http://localhost:8080 in the browser and see the GUI served by the recipient instance. If you leave the search field empty and press the search button, you should see events show up. If you look at the \"host\" field underneath the events, you should see that it is always \"FORWARDER\", confirming that they were sent by the forwarder. You are now running Logsuck in forwarder/recipient mode! Continue reading to learn more about configuring Logsuck.\n\n## Configuration\n\n### Command line options\n\nThere are a few configuration options available on the command line when running Logsuck. It is recommended that you use JSON configuration for production usage of Logsuck, but these options may be useful when running Logsuck locally on a single file.\n\n`-config \u003cfilename\u003e`\nThe name of the file containing the configuration for Logsuck. If a config file exists, all other command line configuration will be ignored. (default \"logsuck.json\")\n\n`-dbfile \u003cfilename\u003e`\nThe name of the file in which Logsuck will store its data. If the name ':memory:' is used, no file will be created and everything will be stored in memory. If the file does not exist, a new file will be created. (default \"logsuck.db\")\n\n`-delimiter \u003cregex\u003e`\nThe delimiter between events in the log. Usually \\n. (default \"\\n\")\n\n`-fieldextractor \u003cregex\u003e`\nA regular expression which will be used to extract field values from events. Can be given in two variants:\n\n1. An expression containing any number of named capture groups. The names of the capture groups will be used as the field names and the captured strings will be used as the values.\n2. An expression with two unnamed capture groups. The first capture group will be used as the field name and the second group as the value.\n\nIf a field with the name '\\_time' is extracted and matches the given timelayout, it will be used as the timestamp of the event. Otherwise the time the event was read will be used.\n\nMultiple extractors can be specified by using the fieldextractor flag multiple times. (defaults \"(\\w+)=(\\w+)\" and \"(?P\u003c\\_time\u003e\\d\\d\\d\\d/\\d\\d/\\d\\d \\d\\d:\\d\\d:\\d\\d.\\d\\d\\d\\d\\d\\d)\")\n\n`-forceStaticConfig \u003cboolean\u003e`\nEnables \"static config\" mode. In this mode, you cannot modify the configuration of Logsuck using the GUI. All configuration must be made through the command line or the JSON configuration file. By default, this is disabled.\n\n`-forwarder \u003caddress\u003e` Sets Logsuck to run in forwarder mode, with the recipient expected to run at the given address. By default, this is disabled.\n\n`-help`\nPrint information about command line options and quit.\n\n`-json` Parse the given files as JSON instead of using Regex to parse. The fieldextractor flag will be ignored. Disabled by default.\n\n`-recipient \u003caddress\u003e` Sets Logsuck to run in recipient mode and receives events on the given address. By default, this is disabled.\n\n`-schema` Print configuration schema and exit.\n\n`-timefield \u003cstring\u003e` The name of the field which will contain the timestamp of the event. Default '\\_time'.\n\n`-timelayout \u003cstring\u003e`\nThe layout of the timestamp which will be extracted in the \\_time field. For more information on how to write a timelayout and examples, see https://golang.org/pkg/time/#Parse and https://golang.org/pkg/time/#pkg-constants. There are also the special timelayouts \"UNIX\", \"UNIX_MILLIS\", and \"UNIX_DECIMAL_NANOS\". \"UNIX\" expects the \\_time field to contain the number of seconds since the Unix epoch, \"UNIX_MILLIS\" expects it to contain the number of milliseconds since the Unix epoch, and UNIX_DECIMAL_NANOS expects it to contain a string of the form `\u003cUNIX\u003e.\u003cNANOS\u003e` where `\u003cUNIX\u003e` is the number of seconds since the Unix epoch and `\u003cNANOS\u003e` is the number of elapsed nanoseconds in that second. (default \"2006/01/02 15:04:05\")\n\n`-version`\nPrint version info and quit.\n\n`-webaddr \u003cstring\u003e`\nThe address on which the search GUI will be exposed. (default \":8080\")\n\n### JSON configuration\n\nJSON is the recommended way of configuring Logsuck for more complex usage. By default, Logsuck will look in its working directory for a `logsuck.json` file which will contain the configuration. If the file is found, all command line options will be ignored. There is a JSON schema which documents the configuration file available [here](https://github.com/JackBister/logsuck/blob/master/logsuck-config.schema.json).\n\nRead [docs/Configuration.md](docs/Configuration.md) for indepth information on configuring Logsuck.\n\nAlso read [docs/Tasks.md](docs/Tasks.md) to learn about configuring tasks.\n\n## Search syntax\n\nSearch queries in Logsuck generally look like this:\n\n```\n[search] [| \u003ccommand type\u003e \u003coption\u003e=\u003cvalue\u003e \"value\"]...\n```\n\n### `[search]`\n\nThis part of the query may contain any combination of the following:\n\n- `\u003cfragment\u003e`\n- `NOT \u003cfragment\u003e`\n- `\u003cfield\u003e=\u003cfragment\u003e`\n- `\u003cfield\u003e!=\u003cfragment\u003e`\n- `\u003cfield\u003e IN (\u003cfragment1\u003e, \u003cfragment2\u003e...)`\n- `\u003cfield\u003e NOT IN (\u003cfragment1\u003e, \u003cfragment2\u003e...)`\n\n#### Fragments\n\nA fragment is the Logsuck term for an unquoted or quoted string which should be searched for among the log events. For example, if you search for `\"hello world\"` only events containing the string \"hello world\" (case insensitive) will be matched.\n\nIf you specify multiple fragments without any surrounding quotes, they will be matched independently of their order in the event. For example, `hello world` will match both events containing \"hello world\" and events containing \"world hello\".\n\nYou can use `*` as a wildcard character in fragments. For example, searching for `ab*` will match the strings \"abc\", \"abcd\", etc.\n\nBy prepending a fragment with `NOT `, you can filter out all events containing that fragment.\n\n#### Fields\n\nA field is a piece of data that is extracted from an event and associated with a key.\n\nThere are a few fields that are extracted from all events: `_time`, `source`, and `host`. You can also extract other fields using the `fieldExtractors` property in the configuration.\n\nThere are two ways you can use fields in your searches: You can either filter against one value using `\u003cfield\u003e=\u003cfragment\u003e` or `\u003cfield\u003e!=\u003cfragment\u003e`, or you can filter against multiple values using `\u003cfield\u003e IN (\u003cfragment1\u003e, \u003cfragment2\u003e...)` or `\u003cfield\u003e NOT IN (\u003cfragment1\u003e, \u003cfragment2\u003e...)`.\n\nFor example, you might use `source=*access*` to get all events from log files that contain \"access\" in the file name, or `source IN (*access*, *error*)` to get all events from log files containing \"access\" or \"error\" in their file names.\n\n### Commands\n\nCommands are processing steps which are applied to the results of the search up to that point.\n\nThe following commands are available:\n\n#### `| rex [field=\u003cfield\u003e] \"\u003cregex\u003e\"`\n\nThe rex command is used to extract new fields from existing fields using a regular expression.\n\nThe regular expression is treated the same as a field extractor in the configuration, meaning that it should either specify a single named capture group or two unnamed capture groups.\n\nIf the regular expression matches and contains a named capture group, a new field with the same name as the capture group will be created with the value of the match inside the capture group.\n\nIf the regular expression matches and contains two unnamed capture groups, the value of the first capture group will be used as the field name and the value of the second capture group will be used as the field value.\n\nThe `field` option allows you to specify which field the regular expression should be ran against. By default it is ran against the raw event string.\n\n#### `| search startTime=\"\u003ctime\u003e\" endTime=\"\u003ctime\u003e\" \"\u003csearch\u003e\"`\n\nThe search command starts a new search. It ignores all previous results and instead sends its own results forward.\n\n#### `| surrounding [count=\u003cnumber\u003e] eventId=\u003cid\u003e`\n\nShows the events that have the same source as the given event and which were close to the event in the log file. This is used when clicking \"View context\" on an event. This is useful if you are finding results from many different files and want to drill down into a specific file.\n\n#### `| table \"\u003cfield1\u003e,\u003cfield2\u003e,...\"`\n\nCreates a table containing the values of the specified fields.\n\n#### `| where \u003cfield1\u003e=\u003cvalue1\u003e \u003cfield2\u003e=\u003cvalue2\u003e...`\n\nThe where command filters events by field value. The benefit of having this as a separate command instead of using the field=value syntax in the search command is that `| where` can act on fields that are extracted later in the pipeline, such as fields extracted by `| rex`.\n\nFor example you might use a search like `userId | rex \"userId (?P\u003cuserId\u003e\\d+)\" | where userId=123` to find events containing the string \"userId\", extract the number following userId in the event, and then filter to only include events where the userId is 123.\n\n## Need help?\n\nIf you have any questions about using Logsuck after reading the documentation, please [create an issue](https://github.com/JackBister/logsuck/issues/new) on this repository! There are no stupid questions here. You asking a question will help improve the documentation for everyone, so it is very much appreciated!\n\n## Building\n\nIn order to build Logsuck, you will need a recent version of Go (1.21 is used when building in CI), as well as a fairly recent Node/npm installation.\n\nBecause Logsuck uses CGO, if you are building on Linux, you need to have `gcc` installed and available on your `PATH`.\n\nIf cross compiling for Windows, you need [gcc-mingw-w64](http://mingw-w64.org/doku.php/download).\n\nLogsuck consists of two parts: A Go application for the backend and a [preact](https://preactjs.com/) GUI for the frontend. When the Go application is built, the frontend is bundled into the executable using [the embed package](https://golang.org/pkg/embed). This bundling step allows Logsuck to be deployed as a single executable.\n\nSince the frontend is necessary to build the backend, start off by building the frontend. All frontend code is contained in the `./internal/web/static` directory.\n\n```sh\ncd internal/web/static\nnpm ci \u0026\u0026 npm run build\n```\n\nThis will build the frontend and put it in the `./internal/web/static/dist` directory. Time to build the backend.\n\nIt is easier to build the backend on Linux than it is on Windows. If using Windows, I would recommend using Windows Subsystem for Linux and cross compiling to a Windows executable instead of trying to build directly on Windows. The official release builds for Windows are cross compiled from an Ubuntu installation.\n\nIf compiling for Linux, all you need to do is:\n\n```sh\nCGO_ENABLED=1 go build ./cmd/logsuck/main.go\n```\n\nto create a `./main` file you can run.\n\nIf cross compiling for Windows, try the following instead:\n\n```sh\nGOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build ./cmd/logsuck/main.go\n```\n\nand you should have a `./main.exe` file.\n\nIf you are working on the frontend, you can do the following things to make your life easier:\n\n1. Run webpack in watch mode by running `npm run watch` in `./internal/web/static`\n2. Add `{ \"web\": { \"usePackagedFiles\": \"false\" } }` to your `./logsuck.json`. This will make it so that Logsuck will read the files off the filesystem instead of using the files that were bundled into the executable.\n\nWith those two steps done, you don't need to restart Logsuck to see the changes you've made to the frontend, and your changes will be compiled when you save. You just need to refresh your browser after making a change to see it in action.\n\n## Customizing using plugins\n\nLogsuck can be customized at build time using plugins. Read [docs/Plugins.md](docs/Plugins.md) for more information, or check out the included plugins in the [plugins](plugins directory).\n\n## Upcoming features\n\nLogsuck is still heavily in development, so there are many features still being worked on.\n\n- [x] Glob patterns for finding log files\n- [x] Retention setting to delete old events after a certain period of time\n- [x] \"Show source\" / \"Show context\" button to view events from the same source that are close in time to the selected event\n- [x] Ability to search via time spans that are not relative to the current time, such as \"All events between 2020-01-01 and 2020-01-05\"\n- [x] Ad hoc field extraction using pipes in the search command (equivalent to Splunk's \"| rex\")\n- [ ] E-mail alerts\n- [ ] Authentication and authorization\n- [x] Plugins\n- [ ] Creating tables and charts from searches\n- [ ] Dashboards\n- [ ] Advanced search commands like dedup, eval, transaction, etc.\n- [Your favorite feature](https://github.com/JackBister/logsuck/issues/new)\n- ... And many more great things!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackbister%2Flogsuck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjackbister%2Flogsuck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackbister%2Flogsuck/lists"}