calcinator v5.0.0 Calcinator.Instrument View Source
Similar to Phoenix, Calcinator supports instrumenters that can receive events from Calcinator
.
The instrument/3
macro is responsible for measuring the time it takes for the event to be processed and for
notifying a list of interested instrumenter modules of this measurement.
You can configure this list of instrumenter modules in the compile-time configuration for Calcinator.
config :calcinator,
instrumenters: [MyApp.Instrumenter]
The way these modules express their interest in events is by exporting public functions where the name of each function is the name of an event. The list of defined events is in “Events” section below.
Callbacks cycle
The event callback sequence is:
- The event callback is called before the event happens with the atom
:start
as the first argument; see the “:start
clause” section below. - The event occurs
- The same event callback is called again, this time with the atom
:stop
as the first argument; see the “:stop
clause” section below.
The second and third argument that each event callback takes depends on the value of the first argument, :start
or
:stop
. For this reason, most of the time you will want to define (at least) two separate clauses for each event
callback, one for the :start
and one for the :stop
callbacks.
All event callbacks are run in the same process that calls the instrument/3
macro; hence, instrumenters should be
careful to avoid performing blocking actions. If an event callback fails in any way (exits, throws, or raises), it
won’t affect anything as the error is caught, but the failure will be logged. Note that :stop
callbacks are not
guaranteed to be called as, for example, a link may break before they’ve been called.
:start
clause
When the first argument to an event callback is :start
, the signature of that callback is:
event_callback(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata :: map) :: any
where:
compile_metadata
is a map of compile-time metadata about the environment whereinstrument/3
has been called.:function
- “#{name}/#{arity}” of function whereinstrument/3
has been called.
runtime_metadata
is a map of runtime data that the instrumentation passes to the callbacks. It varies per call. See “Events” below for a list of defined events.
:stop
clause
When the first argument to an event callback is :stop
, the signature of that callback is:
event_callback(:stop, time_diff :: non_neg_integer, result_of_start_callback :: any)
where:
time_diff
is an integer representing the time it took to execute the instrumented function in native units.result_of_start_callback
is the return value of the:start
clause of the sameevent_callback
. This is a means of passing data from the:start
clause to the:stop
clause when instrumenting.
The return value of each :start
event callback will be stored and passed to the corresponding :stop
callback.
Events
:alembic
When Calcinator
calls Alembic.Document.from_json/2
alembic(:start
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :create | :update, params: params})
:calcinator_authorization
:calcinator_authorization
occurs around calls to the authorization_module.can?/3
in Calcinator.can?/3
to measure how long
it takes to authorize actions on the primary target.
:create
There are two calls to authorize :create
.
The first call will use the ecto_schema_module
as the target
to check if ecto_schema_module
structs can be
created in general by the subject
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :create
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: ecto_schema_module})
Before
authorization_module.can?(subject, :create, ecto_schema_module)
If the subject
can create ecto_schema_module
structs in general, then a second call will check if the specific
Ecto.Changeset.t
can be created.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata :: %{action: :create,
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: %Ecto.Changeset{data: %ecto_schema_module{}}})
Before
authorization_module.can?(subject, :create, %Ecto.Changeset{data: %ecto_schema_module{}})
:delete
There is only one call to authorize :delete
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :delete
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: %ecto_schema_module{}})
authorization_module.can?(subject, :delete, %ecto_schema_module{})
:index
There is one call to authorize :index
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :index
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: ecto_schema_module})
Before
authorization_module.can?(subject, :index, ecto_schema_module)
:show
Calcinator.get_related_resource/3
There is not a special action
for authorizing Calcinator.get_related_resource/3
, instead the source
is authorized
for :show
.
NOTE: This is the same pattern as for Calcinator.show/2
, Calcinator.show_relationship/3
, and
Calcinator.update/2
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :show
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: %ecto_schema_module{}})
Before
authorization_module.can?(subject, :show, %ecto_schema_module{})
If the source
can be shown, then its checked if the related
can be show in an association ascent under source
.
NOTE: This is the same pattern as for Calcinator.show_relationship/3
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :show
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: [%related_ecto_schema_module{}, %ecto_schema_module{}])
Before
authorization_module.can?(subject, :show, [%related_ecto_schema_module{}, %ecto_schema_module{}])
Calcinator.show/2
The primary data is authorized for :show
.
NOTE: This is the same pattern as the authorization to :show
the source
for Calcinator.get_related_resource/3
,
Calcinator.show_relationship/3
, and Calcinator.update/2
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :show
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: %ecto_schema_module{}})
Before
authorization_module.can?(subject, :show, %ecto_schema_module{})
Calcinator.show_relationship/3
There is not a special action
for authorizing Calcinator.show_relationship/3
, instead the source
is authorized
for :show
.
NOTE: This is the same pattern as for Calcinator.show/2
, Calcinator.get_related_resource/3
, and
Calcinator.update/2
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :show
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: %ecto_schema_module{}})
Before
authorization_module.can?(subject, :show, %ecto_schema_module{})
If the source
can be shown, then its checked if the related
can be show in an association ascent under source
.
NOTE: This is the same pattern as for Calcinator.get_related_resource/3
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :show
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: [%related_ecto_schema_module{}, %ecto_schema_module{}])
Before
authorization_module.can?(subject, :show, [%related_ecto_schema_module{}, %ecto_schema_module{}])
Calcinator.update/3
Before a target
can be updated, it is checked that subject
can :show
the target. NOTE: This is the same
pattern as for Calcinator.show/2
, Calcinator.get_related_resource/3
, and Calcinator.show_relatonship/3
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :show
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: %ecto_schema_module{}})
Before
authorization_module.can?(subject, :show, %ecto_schema_module{})
:update
Calcinator.update/3
If a target
is authorized for :show
, it is checked if the subject
can update the Ecto.Changeset.t
.
calcinator_authorization(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metdata :: %{action: :update
calcinator: %Calcinator{
authorizaton_module: module
ecto_schema_module: ecto_schema_module
},
target: %Ecto.Changeset{data: %ecto_schema_module{}}})
Before
authorization_module.can?(subject, :update, %Ecto.Changeset{data: %ecto_schema_module{}})
:calcinator_resources
The :calcinator_resources
event is fired around any resources_module
call by Calcinator
.
The general format has the args
passed to the Calcinator.Resources.t
callback
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata :: %{args: args,
calcinator: %Calcinator{resources_module: Calcinator.Resources.t},
callback: atom})
Calcinator.Resources.allow_sandbox_access/1
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata :: %{args: [beam],
calcinator: %Calcinator{resources_module: Calcinator.Resources.t},
callback: :allow_sandbox_access})
The only argument is the opaque beam
data structure that is used to allow sandbox access.
Calcinator.Resources.delete/2
, Calcinator.Resources.insert/2
, and Calcinator.Resources.update/2
calcinator_resources(:start,
compile_metadata ::
%{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata :: %{args: [changeset, query_options],
calcinator: %Calcinator{resources_module: Calcinator.Resources.t},
callback: :delete | :insert | :update})
Calcinator.Resources.delete/2
, Calcinator.Resources.insert/2
, and Calcinator.Resources.update/2
all take 2
arguments:
changeset
-Ecto.Changeset.t
query_options
-Calcinator.Resoures.query_options
Calcinator.Resources.get/2
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata :: %{args: [id, query_options],
calcinator: %Calcinator{resources_module: Calcinator.Resources.t},
callback: :get})
Arguments
id
- ID of resource to lookup (String.t
ornon_neg_integer
)query_options
-Calcinator.Resoures.query_options
Calcinator.Resources.list/1
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata :: %{args: [query_options],
calcinator: %Calcinator{resources_module: Calcinator.Resources.t},
callback: :list})
Arguments
query_options
-Calcinator.Resoures.query_options
Calcinator.Resources.sandboxed?/0
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata :: %{args: [],
calcinator: %Calcinator{resources_module: Calcinator.Resources.t},
callback: :sandboxed?})
:calcinator_view
calcinator
splits rendering into calling the view_module
and then encoding to the underlying transport. Only
calling view_module
happens during the :calcinator_view
event.
The general format has the args
passed to the Calcinator.View.t
callback
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata ::
%{args: args, calcinator: %Calcinator{view_module: Calcinator.View.t}, callback: atom})
:get_related_resources
or :show_relationship
For the Calcinator.View.get_related_resources/2
and Calcinator.View.show_relations/2
callback, the args
are the
same because show_relationship
uses the same source
and related
, but only shows the Resource Identifier
(id
and type
) instead of the full Resource (id
, type
, attributes
, and relationships
).
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata ::
%{args: [related_resources :: nil | struct | [struct],
%{related: %{resource: related_resource},
source: %{association: source_association, resource: source_resource},
subject: subject}],
calcinator: %Calcinator{view_module: Calcinator.View.t},
callback: :index})
The args
have 2 elements.
related_resource
- The related resource(s) whoseid
(or ids) would be used forshow_relationship
. Can be one of three formatsnil
-belongs_to
orhas_one
source_association
that has no entrystruct
-belongs_to
orhas_one
source_association
that has an entry[struct]
-has_many
source_association
options
:related
:resource
-related_resources
. Matches the first argument.
:source
association
- the name of the associaton onsource_resource
that containedrelated_resources
resource
-struct
of the starting primary data.
:subject
- the subject that is authorized to see source and related resources
:index
For the Calcinator.View.index/2
callback.
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata ::
%{args: [resources, %{subject: subject}],
calcinator: %Calcinator{view_module: Calcinator.View.t},
callback: :index})
The args
have 2 elements.
resources
- The index resourcesoptions
:subject
- the subject that is authorized to seeresources
:show
For the Calcinator.View.show/2
callback.
calcinator_view(:start,
compile_metadata :: %{module: module, function: String.t, file: String.t, line: non_neg_integer},
runtime_metadata ::
%{args: [resource, %{subject: subject}],
calcinator: %Calcinator{view_module: Calcinator.View.t},
callback: :show})
The args
have 2 elements.
resource
- The resource to be shownoptions
:subject
- the subject that is authorized to seeresource
Link to this section Summary
Functions
Instruments the given function
Link to this section Functions
Instruments the given function.
event
is the event identifier (usually an atom) that specifies which
instrumenting function to call in the instrumenter modules. runtime
is
metadata to be associated with the event at runtime (e.g., the query being
issued if the event to instrument is a DB query).
Predefined Events
Examples
instrument :calcinator_authorization, %{action: action, calcinator: calcinator, target: target}, fn ->
...
end