{"id":36419734,"url":"https://github.com/structlogging/structlogger","last_synced_at":"2026-01-11T17:05:18.661Z","repository":{"id":57723418,"uuid":"99340588","full_name":"structlogging/structlogger","owner":"structlogging","description":"framework for structured logging in Java","archived":false,"fork":false,"pushed_at":"2018-05-15T08:43:53.000Z","size":432,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-26T01:00:10.763Z","etag":null,"topics":["java","json","log-statements","master-thesis","structured-logging","variable-context"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/structlogging.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}},"created_at":"2017-08-04T12:24:50.000Z","updated_at":"2024-01-16T19:04:30.000Z","dependencies_parsed_at":"2022-08-26T12:33:16.444Z","dependency_job_id":null,"html_url":"https://github.com/structlogging/structlogger","commit_stats":null,"previous_names":["tantalor93/structlogger"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/structlogging/structlogger","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/structlogging%2Fstructlogger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/structlogging%2Fstructlogger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/structlogging%2Fstructlogger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/structlogging%2Fstructlogger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/structlogging","download_url":"https://codeload.github.com/structlogging/structlogger/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/structlogging%2Fstructlogger/sbom","scorecard":{"id":855709,"data":{"date":"2025-08-11","repo":{"name":"github.com/structlogging/structlogger","commit":"1fcca4e962ef53cbdb94bd72cb556de7f5f9469f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 2-Clause \"Simplified\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T23:51:20.906Z","repository_id":57723418,"created_at":"2025-08-23T23:51:20.906Z","updated_at":"2025-08-23T23:51:20.906Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28314264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"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":["java","json","log-statements","master-thesis","structured-logging","variable-context"],"created_at":"2026-01-11T17:05:18.586Z","updated_at":"2026-01-11T17:05:18.641Z","avatar_url":"https://github.com/structlogging.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Project status\n\n[![Build Status](https://travis-ci.org/structlogging/structlogger.svg?branch=master)](https://travis-ci.org/structlogging/structlogger)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central//com.github.structlogging/structlogger/badge.svg?style=plastic)](https://maven-badges.herokuapp.com/maven-central/com.github.structlogging/structlogger)\n[![Javadocs](http://javadoc.io/badge/com.github.structlogging/structlogger.svg)](http://javadoc.io/doc/com.github.structlogging/structlogger)\n\n## What?\nThis is master thesis project at Masaryk University [Faculty of Informatics](https://fi.muni.cz/index.html.en) under supervision of Daniel Tovarňák ([xdanos](https://github.com/xdanos)).\nThis project is based on project [ngmon-structlog-java-fal](https://github.com/lasaris/ngmon-structlog-java-fal), which supports structured logging in Java using so-called Variable Contexts (see [Daniel's dissertation thesis, Chapter 3](https://is.muni.cz/th/172673/fi_d/)).\n\n## How to use this project\nadd dependency to your project \n```\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.structlogging\u003c/groupId\u003e\n    \u003cartifactId\u003estructlogger\u003c/artifactId\u003e\n    \u003cversion\u003e${structlogger.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nthen you should set compiler argument `schemasRoot` in order to set path where schemas are generated, also you can set package (namespace) for auto generated events using compiler argument `generatedEventsPackage`, which takes qualified package (dot notation, e.g. com.github.structlogging). You can set compiler arguments using maven-compiler-plugin\n\n```\n\u003cplugin\u003e\n                \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n                \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n                \u003cversion\u003e3.6.1\u003c/version\u003e\n                \u003cconfiguration\u003e\n                    \u003csource\u003e1.8\u003c/source\u003e\n                    \u003ctarget\u003e1.8\u003c/target\u003e\n                    \u003cshowWarnings\u003etrue\u003c/showWarnings\u003e\n                    \u003ccompilerArgs\u003e\n                        \u003carg\u003e-AschemasRoot=${project.basedir}\u003c/arg\u003e\n                        \u003carg\u003e-AgeneratedEventsPackage=${generatedEventsPackage}\u003c/arg\u003e\n                    \u003c/compilerArgs\u003e\n                \u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\nin your java code you can then declare fields like this:\n```\n@LoggerContext(context = DefaultContext.class)\nprivate static StructLogger\u003cDefaultContext\u003e logger = new StructLogger\u003c\u003e(new Slf4jLoggingCallback(LoggerFactory.getLogger(\"LOGGER\")));\n```\n\nStructLogger takes implementation of LoggingCallback, which implements basic logging operations, for example here we use [Slf4jLoggingCallback](structlogger/src/main/java/com/github/structlogging/slf4j/Slf4jLoggingCallback.java), which encapsulates SLF4j logger and all it does is it serializes incoming events as string and pass them to SLF4j logger, or you can implement your own [LoggingCallback](structlogger/src/main/java/com/github/structlogging/LoggingCallback.java)\n\nStructLogger field has to be annotated with `@LoggerContext` in order to structured logging to work, you have to also specify extension of [VariableContext](structlogger/src/main/java/com/github/structlogging/VariableContext.java) as annotation parameter (this parameter must be same as generic argument of StructLogger otherwise you will encounter undefined behaviour). Variable context provides logging variables. You can create your own VariableContext like [BlockCacheContext](structlogger-example/src/main/java/com/github/structlogging/BlockCacheContext.java). Please see *Creating your own Variable context* section of README. \n\nthis declared logger can then be used for logging in structured way like this:\n\n```\nlogger.info(\"Event with double={} and boolean={}\")\n      .varDouble(1.2)\n      .varBoolean(false)\n      .log();\n```\n\nthis structured log statement will generate json like this:\n```json\n{\n  \"type\":\"auto.Event677947de\",\n  \"timestamp\":1524037512388,\n  \"context\":{\n    \"message\":\"Event with double=1.2 and boolean=false\",\n    \"sourceFile\":\"com.github.structlogging.Example\",\n    \"lineNumber\":66,\n    \"sid\":1,\n    \"logLevel\":\"INFO\"\n  },\n  \"varDouble\":1.2,\n  \"varBoolean\":false\n}\n```\n\nor you can choose your own name of generated event by passing String literal as argument to log method like this:\n```\nlogger.info(\"Event with double={} and boolean={}\")\n      .varDouble(1.2)\n      .varBoolean(false)\n      .log(\"edu.TestEvent\");\n```\nBeware that you cannot pass String containing white spaces or new lines, such String will generate compilation error. This String literal has to be in format FQDN in Java (for example `edu.TestEvent`, `cz.muni.TestEvent`, `TestEvent`, ...)  \n\nthis will generate event like this:\n```json\n{\n  \"type\":\"edu.TestEvent\",\n  \"timestamp\":1524037512388,\n  \"context\":{\n    \"message\":\"Event with double=1.2 and boolean=false\",\n    \"sourceFile\":\"com.github.structlogging.Example\",\n    \"lineNumber\":71,\n    \"sid\":2,\n    \"logLevel\":\"INFO\"\n  },\n  \"varDouble\":1.2,\n  \"varBoolean\":false\n}\n```\nLogging events such as these are send to the specified `LoggingCallback` implementation to correct method representing log level\non which event was send (in this example it is `INFO`)\n## Event json schemas\nFor each generated structured logging event there is corresponding json schema created during compilation on path specified by compiler argument `schemasRoot` in folder `schemas/events` and each event with namespace is nested in corresponding folder,\n\nFor example:\n```\nlogger.info(\"Event with double={} and boolean={}\")\n      .varDouble(1.2)\n      .varBoolean(false)\n      .log(\"edu.TestEvent\");\n``` \nwill create json schema `${schemasRoot}/schemas/events/edu/TestEvent.json`\n```\n{\n  \"type\" : \"object\",\n  \"id\" : \"urn:jsonschema:edu:TestEvent\",\n  \"$schema\" : \"http://json-schema.org/draft-04/schema#\",\n  \"description\" : \"Event with double={} and boolean={}\",\n  \"title\" : \"edu.TestEvent\",\n  \"properties\" : {\n    \"type\" : {\n      \"type\" : \"string\"\n    },\n    \"timestamp\" : {\n      \"type\" : \"integer\"\n    },\n    \"context\" : {\n      \"type\" : \"object\",\n      \"id\" : \"urn:jsonschema:com:github:structlogging:LoggingEventContext\",\n      \"properties\" : {\n        \"message\" : {\n          \"type\" : \"string\"\n        },\n        \"sourceFile\" : {\n          \"type\" : \"string\"\n        },\n        \"lineNumber\" : {\n          \"type\" : \"integer\"\n        },\n        \"sid\" : {\n          \"type\" : \"integer\"\n        },\n        \"logLevel\" : {\n          \"type\" : \"string\"\n        }\n      }\n    },\n    \"varDouble\" : {\n      \"type\" : \"number\"\n    },\n    \"varBoolean\" : {\n      \"type\" : \"boolean\"\n    }\n  }\n}\n```\nsee [example](structlogger-example) where schemas are created after compilation in root of this module\n\n\nIf `schemasRoot` compiler argument is not specified, no schemas will be created!\n## Creating your own Variable context provider\nVariable context is interface which provides parameters to be used in structured logging by [StructLogger](structlogger/src/main/java/com/github/structlogging/StructLogger.java). To implement your own VariableContext,\ncreate new interface which extends [VariableContext](structlogger/src/main/java/com/github/structlogging/VariableContext.java) and only extends this interface, \nannotate your interface with [@VarContextProvider](structlogger/src/main/java/com/github/structlogging/annotation/VarContextProvider.java), then add methods annotated with [@Var](structlogger/src/main/java/com/github/structlogging/annotation/Var.java),\nthese methods should all have return type your Interface and accept single parameter, please not that method overloading is not supported.\nalso these method names are prohibited: `info`, `debug`, `error`, `warn`, `trace`, `audit`, `infoEvent`, `debugEvent`, `errorEvent`, `warnEvent`, `traceEvent`, `auditEvent`,`log`,`context`, `timestamp` ,`type`.\n\nFor example of custom Variable context see [BlockCacheContext](structlogger-example/src/main/java/com/github/structlogging/BlockCacheContext.java).\n\nAlso note that your custom VariableContext is checked whether it is valid only *lazily*, when it is used.\n\n### Log message parametrization\n[@VarContextProvider](structlogger/src/main/java/com/github/structlogging/annotation/VarContextProvider.java) has parameter called `parametrization`, which when set to `true` forces constraints on log message such that log message (String in `info`,`debug`,... method) must contain `{}` placeholders same count as parameters used in given log statement, for example\n```\nlogger.info(\"test {} string literal {}\")\n      .varDouble(1.2)\n      .varBoolean(false)\n      .log();\n``` \n\nmust contain two `{}` placeholders, because we are using two parameters here `varDouble` and `varBoolean`, these placeholders are at runtime replaced with values passed as argument to log parameters, so here it will create event message will look like this `test 1.2 string literal false`.\n\nIf `parametrization` is set to false, no placeholder `{}` is replaced in log message and no placeholders are enforced in log message during compilation\n\n## Usage restrictions\nThere are some restrictions due to the way this library is implemented.\nPlease note that:\n * **StructLogger should not be declared and cannot be used as local variable** \n * **StructLogger field should be only referenced within class where it is declared** \n * **StructLogger field should be referenced directly (not via some access method or something like that)**.\n * **StructLogger field name should not be shadowed by any local variable**\n\n\n## Structlogger tests\ntests of structlogger API and annotation processor are located in [structlogger-tests](structlogger-tests) module\n\n## Structlogger kafka support \nYou can use [EventTypeAwareKafkaCallback](structlogger/src/main/java/com/github/structlogging/kafka/EventTypeAwareKafkaCallback.java) to send events asynchronously to topics using provided Producer, just provide in your project dependency on `kafka-clients`, for example like this:\n\n```\n \u003cdependency\u003e\n            \u003cgroupId\u003eorg.apache.kafka\u003c/groupId\u003e\n            \u003cartifactId\u003ekafka-clients\u003c/artifactId\u003e\n            \u003cversion\u003e1.0.0\u003c/version\u003e\n \u003c/dependency\u003e\n```\nEvents are send with keys corresponding to system time in milliseconds, events are send to topics based on event type.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstructlogging%2Fstructlogger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstructlogging%2Fstructlogger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstructlogging%2Fstructlogger/lists"}