SayCheezEx 📸

Captures a snapshot of the environment at build time, so you can display it at run-time. And has a handy syntax to include UML graphs in your ExDocs.

This library takes inspiration from an earlier Clojure library, which you can find at https://github.com/l3nz/say-cheez. The previous library has been very useful to me over the years, and I'm hoping that this one will be just as helpful!

Hex.pmHex DocsHex.pmHex.pm

Using

Embedding build information

Whenever you want to reference a version/build information, create an Elixir attribute for the module and compute its value through SayCheezEx.

I often compute a "short" version number, an User-Agent for performing HTTP requests, and a full version that contains the full build information.

For example:

module Foo.Bar do
  import SayCheezEx, only: [cheez!: 1]

  # Create all attributes we need:

  # ...a version string
  # "v 0.1.5/d9a87c3 137 on server.local"
  @version cheez!(
    "v {:project_version}/{:git_commit_id} {:build_number} on {:build_on}"
  )

  # ...a longer version string, with build ane Erlang information
  # "0.1.5 d9a87c3/230411.1227 B:137/230411.1434/prod Ex:1.14.3/OTP25"
  @version_full cheez!(
    "{:project_version} {:git_all} B:{:build_number,=-}/{:build_at}/{:build_mix_env} Ex:{:system}"
  )

  # ...an HTTP user-agent to be used by this module
  # "Foo.Bar MyProject-0.1.5" 
  @user_agent cheez!(
    "#{__MODULE__} {:project_name}-{:project_version}"
  )
  ...
end

Always make sure that you assign those values to an attibute - never call those functions directly.

You can safely create such attributes in all modules that need them, as they are just one (usually very small) binary.

Strings composed through cheez! will interpolate attributes between brackets, with the following rules:

They will also make sure that any module name embedded through __MODULE__ appears as it does in Elixir.

What is available

See https://hexdocs.pm/say_cheez_ex/SayCheezEx.html#info/1 for a full list.

You can also call SayCheezEx.all() for a map with all available attributes:

%{
  build_at: "230411.1538",
  build_at_day: "2023-04-11",
  build_at_full: "2023-04-11.15:38:40",
  build_by: "lenz",
  build_number: "87",
  build_on: "MacBook-Pro.local",
  build_mix_env: "dev",
  git_all: "b204919/230411.1509",
  git_commit_id: "b204919",
  git_commit_id_full: "b2049190312ef810875476398978c2b0387251d3",
  git_date: "2023-04-11.15:09:50",
  git_date_compact: "230411.1509",
  git_last_committer: "Lenz",
  project_full_version: "0.2.1/b204919/230411.1509",
  project_name: "SayCheezEx",
  project_version: "0.2.1",
  sysinfo_arch: "aarch64-apple-darwin22.3.0",
  sysinfo_banner: "Erlang/OTP 25 [erts-13.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit]",
  sysinfo_beam: "BEAM jit 13.2",
  sysinfo_c_compiler: "gnuc 4.2.1",
  sysinfo_compat: "25",
  sysinfo_driver: "3.3",
  sysinfo_nif: "2.16",
  sysinfo_ptr: "64bit",
  sysinfo_word: "64bit",
  system: "1.14.3/OTP25",
  system_elixir: "1.14.3",
  system_otp: "25",
  ....
}

UML/DOT Graphs

You can now easily add graph created with GraphViz and PlantUML in your documentation. This is how they may look like: https://hexdocs.pm/say_cheez_ex/SayCheezEx.html#uml/1

At the moment, GraphViz needs to be installed, but PlantUML is computed through an online server.

And graphs will be cached aggressively, so they are generated only once and won't slow down your developement cycle.

Graphs will be embedded as SVG in your documentation, so they do not depend on client-side rendering, as it was the case with Mermaid.js.


module Foo do
    import SayCheezEx, only: [uml: 1, graphviz: 1]

    @moduledoc """
    Here goes a Graphviz graph:

    #{graphviz("digraph { Sup -> GenServ }")}

    Here a PlantUML graph:

    #{uml("""
      Bob -> Alice : I do love UML in documentation
      Alice -> Bob : I love it as well!
    """)}

    """

    ...
end

Installing

Just add to your mix.exs file:

    {:say_cheez_ex, "~> 0.3"}