Skip to content

Précepte is an opinionated scala monitoring library

License

Notifications You must be signed in to change notification settings

ProjectSeptemberInc/precepte

 
 

Repository files navigation

Precepte, let your code be state-aware & make runtime effect observation acceptable...

Join the chat at https://gitter.im/MfgLabs/precepte

Precepte is an opinionated purely functional & lazy API stacking some useful monads to help you observe the execution of your runtime effects by instrumenting your code with a managed state propagated all along your business workflow.

Precepte embraces the concept that observing has a cost but let you control explicitly the balance between precision and performance without sacrifying code cleanness and FP purity & laziness.

Precepte's idea is simply to make your code state-aware by allowing you to obtain a State anywhere in your code. This state will provide you with:

  • a context defining from where this code comes and where it is (function name, custom tags, etc..)
  • any values you want to measure in your observation

The state provided by Precepte is composed of:

  • a managed part that is managed by Precepte and that consists in:

    • the Span: a global ID uniquely identifying the full execution workflow
    • the Call Path: a sequence of tuples of PId (local step ID) and Tags (defined at compile-time) accumulated by Precepte all along the execution of the workflow. This is what provides you with the place from where you come and where you are...
  • an unmanaged part that is just a container in which you can put anything you want and also perform some compile-time DI.

// A Sample with Future effects (the ugliest of the effects)
// For now, we use scalaz (cats coming soon) so you need some monads from Scalaz
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scalaz.std.scalaFuture._
import scalaz.syntax.monad._

// import the default Precepte representation using our provided Tags & ManagedState type
import precepte.default._

// create some effectful steps in which you can
// ST[Int] represents a State with an unmanaged part in which you will inject an Int at execution
def f1 = Precepte(tags("simple.f1", DB)){(_: ST[Int]) => 1.point[Future]}
def f2(i: Int) = Precepte(tags("simple.f2", API)){(_: ST[Int]) => s"foo $i".point[Future]}

// Lazy definition of your effectful workflow
val res = for {
  i <- f1
  r <- f2(i)
} yield r

// create the initial state
// Span is the global unique ID
// 42 is your injected unmanaged state part (could be something much more interesting ;))
val state0 = ST(Span.gen, env, Vector.empty, 42)

// execute your effectful workflow starting with state0
val (s, a) = res.run(state0)

Precepte is a custom purely functional structure based on:

  • A State Monad to represent the pure propagation of the State in the workflow
  • A Free Monad to represent our monadic & applicative effectful workflow
  • Some helpers to make Precepte usable with Monad Transformers
  • Coyoneda to reduce the requirement of effects to be Functor in Free Monads
  • some custom optimization to reduce the burden of Free Monads classic model (right associatio, map fusion, structure squashing, )

About

Précepte is an opinionated scala monitoring library

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Scala 93.0%
  • HTML 6.3%
  • CSS 0.7%