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
:startas the first argument; see the “:startclause” section below. - The event occurs
- The same event callback is called again, this time with the atom
:stopas the first argument; see the “:stopclause” 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_metadatais a map of compile-time metadata about the environment whereinstrument/3has been called.:function- “#{name}/#{arity}” of function whereinstrument/3has been called.
runtime_metadatais 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_diffis an integer representing the time it took to execute the instrumented function in native units.result_of_start_callbackis the return value of the:startclause of the sameevent_callback. This is a means of passing data from the:startclause to the:stopclause 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.tquery_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.tornon_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_toorhas_onesource_associationthat has no entrystruct-belongs_toorhas_onesource_associationthat has an entry[struct]-has_manysource_association
options:related:resource-related_resources. Matches the first argument.
:sourceassociation- the name of the associaton onsource_resourcethat containedrelated_resourcesresource-structof 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