{"id":19543136,"url":"https://github.com/tanvd/jetaudit","last_synced_at":"2025-07-08T08:06:13.802Z","repository":{"id":90982404,"uuid":"85105117","full_name":"TanVD/JetAudit","owner":"TanVD","description":"Clickhouse Logging Library","archived":false,"fork":false,"pushed_at":"2024-04-16T14:36:01.000Z","size":3492,"stargazers_count":2,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-04T16:42:30.631Z","etag":null,"topics":["audit","clickhouse","kotlin","logging"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TanVD.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2017-03-15T18:04:47.000Z","updated_at":"2021-10-07T08:21:08.000Z","dependencies_parsed_at":"2024-04-16T15:53:38.113Z","dependency_job_id":"c0d5ca84-132d-4902-8d58-6dcb2c72521d","html_url":"https://github.com/TanVD/JetAudit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TanVD%2FJetAudit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TanVD%2FJetAudit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TanVD%2FJetAudit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TanVD%2FJetAudit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TanVD","download_url":"https://codeload.github.com/TanVD/JetAudit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251025938,"owners_count":21524881,"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","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":["audit","clickhouse","kotlin","logging"],"created_at":"2024-11-11T03:17:27.413Z","updated_at":"2025-04-26T17:31:43.294Z","avatar_url":"https://github.com/TanVD.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JetAudit\n\nJetAudit is library for business process audit. It uses ClickHouse as a data storage for audit events.\n\nBasically, it is an interface to save and load different events and do it under heavy load and very fast.\n\n## Events\n\nEvents, in terms of JetAudit, are lists of objects and some information relevant to them. Mostly, it suits for business-process audit needs.\n\nFor example, you have an object of type \"Contract\" and object of type \"Customer\". You can save following event:\n\n```\nAudit.save(customer, \"paid for\", contract);\n```\n\nEvery object will be mapped in accordance with it's type (see [type systems paragraph](#type-system) ) and asynchronously saved to ClickHouse.\n\n## Setup\n\nTo use JetAudit you'll need ClickHouse installation (we recommend to use replicated cluster in production).\n\nSetup properties file in accordance with a documentation of AuditApi class. Once it is done, you can try to save your first audit record. Note, that by default JetAudit type system initialized only with primitive types.\n\n## How to\n\nFirst of all you'll need to define your own set of types. Consult [type systems paragraph](#type-system) paragraph for how to.\n\nOnce it is done, you'll need to create AuditAPI object (it is strongly recommended instantiate it as singleton). \n\nOnce AuditAPI object is created, it will start AuditWorkers, which are used to asynchronously save records.\n\nAfter it you can save records:\n\n`AuditAPI.save(customer, \"have bought\", 15, \"boats\", \"from\", seller)`\n\nor even\n\n`AuditAPI.save(customer, SellEvent.buy, boats, seller)` (we assume that `boats: List\u003cBoat\u003e`) \n\nIt all depends on your type system!\n\nAlso you can load records.\n\n`AuditAPI.load((Customer.id eq 15) and (SellEvent.type eq SellEvent.buy.name) and (Seller.id eq 21))`\n\nNote, that format of loaded records depends on your type definitions. You can enable deserialization and add deserializers to every ObjectType and then you'll get exactly the data you've been saving (of course, if your deserializers works right).\n \nOtherwise, you can disable serialization, and you'll get back only saved state of each audit record object. In that case you'll have no overhead on deserialization and will load records very fast.\n\nDepending on a situation one or another load format may suit your needs. \n\n## Type system\n\nEvery object saved using JetAudit should be added to it's type system. There are 2 general types - ObjectType and InformationType.\n\n### Object type\n\nObjectType should be used for objects, that can occur more than one time in audit record. For example, it is customers (one customer may buy something from another). Every ObjectPresenter (presenters implements logic of ObjectType and works as interface for load of events) may have few serializers and appropriate StateTypes. When event is saved, serializers are invoked on an object, and their results are saved into ClickHouse, each to defined by StateType column.\n\nLet's see it working:\n\n```\ndata class TestClass(val id: String, val name: String)\n\nobject TestClassPresenter : ObjectPresenter\u003cTestClass\u003e() {\n    override val useDeserialization: Boolean = true\n\n    override val entityName: String = \"TestClassString\"\n\n    val id = string(\"Id\") { it.id }\n    val name = string(\"Name\") { it.name }\n\n    override val deserializer: (ObjectState) -\u003e TestClass? = { (stateList) -\u003e\n        if (stateList[id] == null) null else TestClass(stateList[id] as String, stateList[name] as String)\n    }\n}\n\nAudit.addObjectType(ObjectType(TestClass::class, TestClassPresenter))\n```\n\nHere is a simple example. When object of type TestClass will be saved, as part of audit event, JetAudit will find corresponding ObjectType in type system (TestClassPresenter implements it) and will serialize it to 2 fields - \"TestClass_Id\" with value from id field, and \"TestClass_Name\" with value from name field. Here `val id` and `val name` are StateTypes with serializers, and TestClassPresenter is an object implementing all the logic for TestClass ObjectType.\n\nNote, that \"TestClass_Id\" and \"TestClass_Name\" will be also columns used in ClickHouse to save objects of this ObjectType. Columns will be of type `Array(String)`.\n\n### Information type\n\nInformation type should be used for objects, that may occur only once in audit record. For example, it is a timestamp of record itself. \n\nInformationTypes are very simple, cause their values maps right into columns of Clickhouse.\n\nHere is a definition of a simple information type:\n\n`object LongInf : InformationType\u003cLong\u003e(\"LongInfColumn\", DbInt64(), { 0 })`\n\nNote, that values of this type will be mapped to column LongInfColumn in Clickhouse.\n\n## Ops notes\n\nWe strongly encourage you to use replicated ClickHouse setup. \n\nJetAudit requires *ReplacingMergeTree engine family. It writes a version of audit record, and you can delete some records just writing new empty one with later version and equal id and timestamp\n\nJetAudit may align it's own scheme even in replicated setup, but we recommend you to disable defaultDDL in production and align the scheme manually, so you can react on any errors ClickHouse may produce.\n\n## More examples\n\nMore examples you may find in JetAudit tests. Also, feel free to contact me (@tanvd) with any questions on JetAudit usage.\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanvd%2Fjetaudit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftanvd%2Fjetaudit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanvd%2Fjetaudit/lists"}