{"id":13808129,"url":"https://github.com/romanpierson/vertx-web-accesslog","last_synced_at":"2025-08-28T05:05:39.203Z","repository":{"id":203775726,"uuid":"51703094","full_name":"romanpierson/vertx-web-accesslog","owner":"romanpierson","description":"An access log implementation to be used in vert web routes - inspired by apache / tomcat access log configuration","archived":false,"fork":false,"pushed_at":"2025-05-15T08:54:10.000Z","size":803,"stargazers_count":29,"open_issues_count":3,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-15T09:38:22.655Z","etag":null,"topics":["accesslog","elasticsearch","logging","vertx","vertx-web"],"latest_commit_sha":null,"homepage":"","language":"Java","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/romanpierson.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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,"zenodo":null}},"created_at":"2016-02-14T16:46:28.000Z","updated_at":"2025-03-02T19:51:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"66c7b59b-9610-4c51-9210-9e4ed1e44d5d","html_url":"https://github.com/romanpierson/vertx-web-accesslog","commit_stats":null,"previous_names":["romanpierson/vertx-web-accesslog"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/romanpierson/vertx-web-accesslog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanpierson%2Fvertx-web-accesslog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanpierson%2Fvertx-web-accesslog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanpierson%2Fvertx-web-accesslog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanpierson%2Fvertx-web-accesslog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/romanpierson","download_url":"https://codeload.github.com/romanpierson/vertx-web-accesslog/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romanpierson%2Fvertx-web-accesslog/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272442791,"owners_count":24935843,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-28T02:00:10.768Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["accesslog","elasticsearch","logging","vertx","vertx-web"],"created_at":"2024-08-04T01:01:35.684Z","updated_at":"2025-08-28T05:05:39.196Z","avatar_url":"https://github.com/romanpierson.png","language":"Java","funding_links":[],"categories":["Utilities"],"sub_categories":[],"readme":"[![Build Status (5.x)](https://github.com/romanpierson/vertx-web-accesslog/actions/workflows/ci-vert.x-5.x.yml/badge.svg)](https://github.com/romanpierson/vertx-web-accesslog/actions/workflows/ci-vert.x-5.x.yml)\n[![Build Status (4.x)](https://github.com/romanpierson/vertx-web-accesslog/actions/workflows/ci-vert.x-4.x.yml/badge.svg)](https://github.com/romanpierson/vertx-web-accesslog/actions/workflows/ci-vert.x-4.x.yml)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=romanpierson_vertx-web-accesslog\u0026metric=coverage)](https://sonarcloud.io/dashboard?id=romanpierson_vertx-web-accesslog)\n[![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/vert-x3/vertx-awesome)\n\n# vertx-web-accesslog\n\nAn access log implementation to be used in vertx web routes.\n\nInspired and with intention to be compliant with\n\n* Apache HTTP Server mod_log_config module (http://httpd.apache.org/docs/2.4/en/mod/mod_log_config.html)\n\n* W3C Extended Log File Format (http://www.w3.org/TR/WD-logfile.html)\n\nThe main idea is to have an event based logging, with the possibility (but not enforcing you to do so) to directly export a log event natively to a target system, and not having to first write and persist it to a file and then read and parse it again from there like eg ELK is doing it. The drawback that those kind of solutions have is performance but even more issues like recognizing complete stacktraces etc.\nThe ElasticSearch Appender is the only appender for now that takes advantage of those benefits.\nHowever you are free of course to use a traditional ELK setup style and just write your output to either console or a specific logfile - and let eg logstash take over from there.\n\n## Key facts\n\n* Zero dependencies (apart of vertx-web obviously)\n* Easily extensible and customizable\n* Small memory footprint\n\n\n## Technical Usage\n\nThe artefact is published on maven central.\n\nJust add it as a dependency to your project (gradle example)\n\n```xml\ndependencies {\n\tcompile 'com.romanpierson:vertx-web-accesslog:2.7.0'\n}\n```\n\n## Compatibility with Vert.x core\n\nSince introduction of `vert.x 5` due to some architectural changes the master contains `vert.5` compatible version and its `vert.x 4` compatible counterpart continues on branch `vert.x-4.x`. \n\nThose two versions are functional equivalent and you should just be able to switch to `vert.5` without any code changes. The plan is also to keep the two versions with same functionality.\n\nTherefore minor version will stay identical but major version will identify if the library is targeted to be used with `vert.x 4` (1) or `vert.x 5` (2)\n\nAccesslog version 4.x / 5.x | Vertx version\n----|------\n1.7.0 / 2.7.0  | 4.5.1 \u003e / 5.0.0 \u003e\n1.6.0 / - | 4.3.0 \u003e / -\n1.5.0 / - | 4.2.0 \u003e / -\n1.4.0 / - | 4.0.0 - 4.1.x / -\n1.3.1 / - | 3.3.0 - 3.7.0 / -\n1.2.0 / - | 3.3.0 - 3.7.0 / -\n\nPrevious versions are listed for completeness only and not supported anymore.\n\n## Access Log Pattern Configuration\n\nThe logger supports mixing of both log formats and is also designed to easily add custom log elements\n\n### Define your custom AccessLogElement\n\nYou can easily create your custom implementation of `AccessLogElement` by creating your own element class implementing `AccessLogElement` interface. The available `AccessLogElement` types are discovered by ServiceLoader, so just add to your resources a file like this and inside list your `AccessLogElement` classes\n\n```xml\nMETA-INF\n services\n  com.romanpierson.vertx.web.accesslogger.configuration.element.AccessLogElement\n```\n\nAs ServiceLoader SPI is intented to work with objects unfortunately your AccessLogElement implementation requires a parameter less constructor.\n\nIn order that the pattern resolver is able to resolve your new element against a pattern you have to implement your resolving condition by implementing `findInRawPatternInternal(rawPattern)` method.\n\nTo facility this and to avoid boilerplate code there are static helpers in PatternResolver that simplifies that a lot.\n\nMethod | Resolves pattern | Remarks | Examples\n----|------|--|----\nextractBestPositionFromFixPatternIfApplicable | `\u003cVALUE\u003e` | Whatever value is matched and resolved | `%b` `cs-uri`\nextractBestPositionFromFixPatternsIfApplicable | `\u003cVALUE\u003e` | Like above but you can pass a list of values to be matched | `%b` `cs-uri`\nextractBestPositionFromPostfixPatternIfApplicable | `%{\u003cCONFIGURATION\u003e}POSTFIX` |  Searches for a postfixed pattern and extracts a configuration string that is passed later to your defined function  | `%{msec}t`\nextractBestPositionFromPostfixPatternAndAdditionalCheckIfApplicable | `%{\u003cCONFIGURATION\u003e}POSTFIX` | Like above but let you define an additional function that checks if the found configuration value is valid for your element to be handled  | `%{msec}t`\n\n### Redefine existing elements with your custom one\n\nBy defining your custom element using same pattern as an existing one shipped with this library it will have preference over the predefined one. \n\n\n## Appenders\n\nAppenders are basically a way to send the log data to one (or multiple) backends. This ships with a set of (hopefully) useful appenders but you can create your custom appenders in a very easy way.\n\n### Available Appenders\n\nAppender | Description\n----|------\nConsole Appender | Embedded - main purpose for testing\nEventBus Appender | Embedded - simple way to forward access events to a configurable address on the event bus\n[Logging Appender](https://github.com/romanpierson/vertx-web-accesslog/blob/master/LA_README.md) | Embedded - Using common logging functionality (logback, slf4j, etc)\n[ElasticSearch Appender](https://github.com/romanpierson/vertx-web-accesslog/blob/master/ES_README.md) | Embedded - Experimental appender that writes data to ElasticSearch (For usage eg in kibana)  Requires [Vertx ElasticSearch Indexer](https://github.com/romanpierson/vertx-elasticsearch-indexer)\n\n\n\n### Custom Appenders\n\nYou can easily write your own appender doing \n\nWrite your own CustomAppender class that must\n* implement `Appender` Interface\n* have a public constructor taking a `JsonObject` instance holding the configuration\n\n## AccessLoggerProducerVerticle\n\nThis verticle is responsible for receiving the raw data, formatting it based on the AccessLogElements configured and forwards the resulting data to the registered Appenders (by calling `Appender.push`). \n\nThere is one worker instance of `AccessLoggerProducerVerticle` per vertx context started if you put configuration value `isAutoDeployProducerVerticle` to `true` (by default it is). If you prefer to manage the deployment of that verticle byself set the property to `false`.\n\n## Usage\n\nThis describes the basic usage. More specific info eg about the different appenders can be found on the links.\n\n### Configure route\n\nJust put an instance of AccessLogHandler as first route handler.\n\n```java\nRouter router = Router.router(vertx);\n\nJsonObject config = .... load or create your configuration json\n\nrouter.route().handler(AccessLoggerHandler.create(config));\n\n```\n\nAs configuration is now done by plain JsonObject its very simple to use and inject configuration eg by yaml, see as an example `ServerSetupStarter`\n\n```yaml\nconfigurations:\n  - identifier: accesslog-formatted\n    logPattern: '%{}t %D \"cs-uri\"'\n    appenders:\n      - appenderClassName : com.romanpierson.vertx.web.accesslogger.appender.console.impl.ConsoleAppender\n  - identifier: accesslog-plain\n    logPattern: \"%{msec}t %D cs-uri\"\n    appenders:\n      - appenderClassName : com.romanpierson.vertx.web.accesslogger.appender.console.impl.ConsoleAppender\n```\n\n## Supported log elements\n\nCurrently those elements are supported\n\nElement | Apache | W3C | Remarks\n----|------|------------| --------\nMethod | %m  | cs-method | |\nStatus | %s  | sc-status | |\nDuration s | %T  | - |  |\nDuration ms | %D  | - | |\nRemote Host | %h  | - |  |\nLocal Host | %v  | - |  |\nLocal port | %p  | - |  |\nBytes Written v1 | %B | - | Zero Bytes written as 0 |\nBytes Written v2 | %b | - | Zero Bytes written as - |\nFirst line of request | %r  | - | |\nURI path only | %U | cs-uri-stem | |\nQuery only | %q | cs-uri-query | |\nURI path incl query | - | cs-uri | |\nVersion / Protocol | %H | - | |\nDatetime Apache | %t | - | Logs by default the request timestamp using format 'EEE, dd MMM yyyy HH:mm:ss zzz', Locale English and Timezone GMT  |\nDatetime Apache Timeunit | %t{msec} | - | Currently only milliseconds is supported  |\n| Datetime Apache Configurable v1 | %{PATTERN}t | - | Specify the format pattern, by default it is used Locale English and Timezone GMT |\n| Datetime Apache Configurable v2 | %{PATTERN\\|TIMEZONE\\|LANGUAGE}t | - | Specify format pattern, timezone and language |\nIncoming Headers | %{IDENTIFIER}i  | - |  |\nOutgoing Response Headers | %{IDENTIFIER}o  | - |  |\nCookie | %{IDENTIFIER}C  | - | Request cookies only |\nStatic value | %{IDENTIFIER}static  | - |  |\nEnvironment Variable value | %{IDENTIFIER}env  | - |  |\n\n### Static values\n\nFor static values you should prefer to use the %{value}static element. In case you have an appender like `ConsoleAppender` or `LoggingAppender` that writes its output via the resolved pattern you can also put such static values directly into the logpattern as it will just stay as non resolved. However for other appenders like `ElasticSearchAppender` one you need to explicitly define the element.\n\n### Empty behavior\n\nThe default way for elements where no actual value can be evaluated is to return a `NULL` value. This way the appender is able to translate this into an empty string or eg skip the value if we index towards a solution like ElasticSearch.\n\n## Changelog\n\nDetailed changelog can be found [here](https://github.com/romanpierson/vertx-web-accesslog/blob/master/CHANGELOG.md).\n\n## Demo Playground\n\nA sample project that shows usage of this (and other related features) can be found [here](https://github.com/romanpierson/vertx-logging-playground).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromanpierson%2Fvertx-web-accesslog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fromanpierson%2Fvertx-web-accesslog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromanpierson%2Fvertx-web-accesslog/lists"}