Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bougueil committed Dec 2, 2023
0 parents commit 73473aa
Show file tree
Hide file tree
Showing 14 changed files with 647 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: CI

on:
pull_request:
push:
branches:
- main

jobs:
test:
runs-on: ubuntu-20.04
env:
MIX_ENV: test
strategy:
fail-fast: false
matrix:
include:
- pair:
elixir: 1.15.0
otp: 26.0.1
lint: lint
steps:
- uses: actions/checkout@v2

- uses: erlef/setup-beam@v1
with:
otp-version: ${{matrix.pair.otp}}
elixir-version: ${{matrix.pair.elixir}}

- name: Install Dependencies
run: mix deps.get --only test

- run: mix format --check-formatted
if: ${{ matrix.lint }}

- run: mix deps.get && mix deps.unlock --check-unused
if: ${{ matrix.lint }}

- run: mix deps.compile

- run: mix compile --warnings-as-errors
if: ${{ matrix.lint }}

- run: mix credo

- run: mix test

- run: mix dialyzer --unmatched_returns
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/_build
/cover
/deps
/doc
/.fetch
erl_crash.dump
*.ez
*.beam
/config/*.secret.exs
.elixir_ls/
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Changelog for Jop



## v0.1.0 (2023-12-02)

* First release.
117 changes: 117 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# JOP: an in-memory key value logger
[![Test](https://github.com/bougueil/jop_ex/actions/workflows/ci.yml/badge.svg)](https://github.com/bougueil/jop_ex/actions/workflows/ci.yml)

Logs in memory, spatially and temporally, key value events.<br>
These events, generated by multiple processes, are then flushed to disk for analysis (e.g. to detect locks).


## Installation


```elixir
def deps do
[
{:jop_ex, git: "https://github.com/bougueil/jop_ex"}
]
end
```

## Usage
```
iex> "myjop"
...> |> Jop.init()
...> |> Jop.log("key_1", :any_term_112)
...> |> Jop.log("key_2", :any_term_133)
...> |> Jop.flush()
log stored in jop_myjop.2020_05_12_21.42.49_dates.gz
log stored in jop_myjop.2020_05_12_21.42.49_keys.gz
#Jop<myjop:uninitialized>
```

## Performance
Excerpt from a run of the unit test :
```
througput 1267456 logs/s.
```

## Basic example
```
# prepare for logging and return a handle
myjop = Jop.init("myjop")
# log with handle event "key_1", :any_term_112
Jop.log myjop, "key_1", :any_term_112
Process.sleep 12
# clear logs
Jop.clear myjop
Jop.log myjop, "key_2", :any_term_113
Process.sleep 12
Jop.log myjop, "key_1", :any_term_112
Process.sleep 12
Jop.log myjop, "key_2", :any_term_113
# flush to disk and erase the log
Jop.flush myjop
log stored in jop_myjop.2020_05_12_21.42.49_dates.gz
log stored in jop_myjop.2020_05_12_21.42.49_keys.gz
#Jop<myjop:uninitialized>
```
will generate both a temporal (by date) and a spatial (by key) log files:

### Temporal log file
```
# list all operations by date
zcat jop_myjop.2020_05_12_21.42.49_dates.gz
00:00:00_000.482 "key_2": :any_term_113
00:00:00_014.674 "key_1": :any_term_112
00:00:00_028.568 "key_2": :any_term_113
```

### Spatial (by key) log file
```
# list all operations by key :
zcat jop_myjop.2020_05_12_21.42.49_keys.gz
"key_1": 00:00:00_014.674 :any_term_112
"key_2": 00:00:00_000.482 :any_term_113
"key_2": 00:00:00_028.568 :any_term_113
```
## Real life: multiple processes logging
Processes log in myjop as follow:
```
# Handle can be saved in process state
myjop = Jop.ref("myjop")
# Log if logging is activated
Jop.log myjop, "key_1", :any_term_112
```
Console activate / deactivate the logging:
```
# Activate the logging
# Starts the logging
myjop = Jop.init("myjop")
# Do some queries while the logging is on
inspect myjop # see how many records
Enum.count mylog
Enum.member? mylog, "mykey"
...
# Flush the logs on disk, keep on logging
Jop.flush myjop, :nostop
# Clear the logs, keep on logging
Jop.clear myjop # clear all entries and continue logging
# Flush the logs on disk and deactivate the logging
Jop.flush myjop
# Start logging again
Jop.init("myjop")
```
7 changes: 7 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Config

# https://spapas.github.io/2020/05/15/elixir-osmon-alerts/
# config :os_mon,
# memsup_system_only: true,
# start_disk_sup: false,
# start_cpu_sup: false
39 changes: 39 additions & 0 deletions lib/common.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# See LICENSE for licensing information.

defmodule JLValid do
@moduledoc false

defmacro ets?(tab, clauses) do
valid_if(tab, clauses)
end

defp valid_if(tab, do: do_clause) do
valid_if(tab, do: do_clause, else: nil)
end

defp valid_if(tab, do: do_clause, else: else_clause) do
quote do
case :undefined != :ets.info(unquote(tab), :size) do
x when :"Elixir.Kernel".in(x, [false, nil]) -> unquote(else_clause)
_ -> unquote(do_clause)
end
end
end
end

defmodule JLCommon do
@moduledoc false

@date_format ".~p_~2.2.0w_~2.2.0w_~2.2.0w.~2.2.0w.~2.2.0w"

def date_str do
hms =
List.flatten(
for e <- Tuple.to_list(:calendar.universal_time_to_local_time(:calendar.universal_time())) do
Tuple.to_list(e)
end
)

:io_lib.format(@date_format, hms)
end
end
Loading

0 comments on commit 73473aa

Please sign in to comment.