=encoding UTF-8

=head1 NAME

OpenTelemetry - A Perl implementation of the OpenTelemetry standard

=head1 SYNOPSIS

    use OpenTelemetry;

    # Obtain the current default tracer provider
    my $provider = OpenTelemetry->tracer_provider;

    # Create a trace
    my $tracer = $provider->tracer( name => 'my_app', version => '1.0' );

    # Record spans
    $tracer->in_span( outer => sub ( $span, $context ) {
        # In outer span

        $tracer->in_span( inner => sub ( $span, $context ) {
            # In inner span
        });
    });

=head1 DESCRIPTION

The OpenTelemetry distribution is the Perl implementation of
L<OpenTelemetry|https://opentelemetry.io>. This module provides an entrypoint
and exposes exposes an interface to get and set components that need to be
globally available.

The OpenTelemetry standard keeps a strict separation between an API layer
that implements an interface that is backend-agnostic, and an SDK layer that
can be connected to the API to do the actual work.

The modules in this distribution implement the OpenTelemetry API, and as such
can be used to instrument code so it generates data about its performance and
operation. As long as no SDK is used, these data will not be processed in any
way, or transmitted anywhere.

See L<OpenTelemetry::SDK> for the reference implementation of the
OpenTelemetry SDK for more details about how it can be configured to make use
of the data generated by uses of this API.

The OpenTelemetry module offers two main interfaces: functions can be called
as class methods, in which case nothing needs to be imported; or they can be
imported into your namespace for a functional interface (in which case the
functions will have a C<otel_> prefix; see more details below).

In both cases, functions that expose a component that can be set will be
lvalue functions, which can be used in regular assignments. Note, however,
that these assignments will be globally visible. For local definitions,
consider using L<Syntax::Keyword::Dynamically>, or other similar methods.

=head1 CLASS METHODS

=head2 logger_provider

    $logger_provider = OpenTelemetry->logger_provider;
    OpenTelemetry->logger_provider = $new_logger_provider;

Get the global logger provider. This function can be used as an lvalue to set
a new logger provider, but if so the new value must be a subclass of
L<OpenTelemetry::Logs::LoggerProvider>. Trying to set it to a class that does
not inherit from that class is an error.

If the logger provider is read before any is set, it will default to a
L<OpenTelemetry::Logs::LoggerProvider>, which returns a logger that does
nothing. Please refer to the documentation of that class for more details.

=head2 tracer_provider

    $tracer_provider = OpenTelemetry->tracer_provider;
    OpenTelemetry->tracer_provider = $new_tracer_provider;

Get the global tracer provider. This function can be used as an lvalue to set
a new tracer provider, but if so the new value must be a subclass of
L<OpenTelemetry::Trace::TracerProvider>. Trying to set it to a class that does
not inherit from that class is an error.

If the tracer provider is read before any is set, it will default to a
L<OpenTelemetry::Trace::TracerProvider>, which creates non-recording spans.
Please refer to the documentation of that class for more details.

=head2 propagator

    $propagator = OpenTelemetry->propagator;
    OpenTelemetry->propagator = $new_propagator;

Get the global propagator. This function can be used as an lvalue to set
a new propagator, but if so the new value must implement the
L<OpenTelemetry::Propagator> role. Trying to set it to a class that does not
implement that role is an error.

If the propagator is read before any is set, a default
L<OpenTelemetry::Propagator::None> will be set.

=head2 error_handler

    $handler = OpenTelemetry->error_handler;
    OpenTelemetry->error_handler = $new_error_handler;

Get the error handler subroutine reference. This function can be used as an
lvalue to set a new error handler, but if so the new value must me a
subroutine reference. Trying to set it to a value that is not is an error.

The error handler will be called with the following named parameters:

=over

=item exception

The exception that raised the error.

=item message

A string providing additional context.

=item details

An optional hash reference with additional contextual information.

=back

The default error handler simply concatenates these and logs them using
L<Log::Any>. If present, the details are passed as structured data to
the logger.

=head2 handle_error

    OpenTelemetry->handle_error(
        exception => $exception,
        message   => $message,
        ...
    );

Calls the global error handler. This should be called on errors that are
otherwise recoverable, since the default error handler does not itself die,
and users are not required to die when setting a new one.

If the error is unrecoverable, prefer raising an exception such as those
described in L<OpenTelemetry::X>, although bear mind that whenever possible
the OpenTelemetry instrumentation should not be the cause of code not
completing, so most if not all errors should be recoverable.

=head1 EXPORTABLE FUNCTIONS

These functions are not available except when requested, so they cannot
themselves be called on the OpenTelemetry package. They are generated
on-demand when importing this module.

The exporting itself is done using L<Exporter::Tiny>, which provides ways
to rename or otherwise restrict imports. Please refer to the documentation
of that module for more details.

=head2 otel_config

    $value = otel_config(@keys);

Reads OpenTelemetry configuration values from the environmen. This is provided
as a convenience method and behaves exactly as L<OpenTelemetry::Common/config>.

=head2 otel_context_with_span

    $context = otel_context_with_span( $span, $root_context // undef );

Takes a span (such as those returned by calling
L<"create_span" on a tracer|OpenTelemetry::Trace::Tracer/create_span>
provided by the L</tracer_provider>) and returns a L<OpenTelemetry::Context>
containing it. If a L<OpenTelemetry::Context> is passed as its
second argument, the new context will be constructed from the one provided,
inheriting any existing values. Otherwise, the current context will be used.

This is provided as a convenience method and behaves exactly as
L<OpenTelemetry::Trace/context_with_span>.

=head2 otel_current_context

    $context = otel_current_context;
    otel_current_context = $new_context;

Gets the current context. This is provided as a convenience method and
behaves exactly as L<OpenTelemetry::Context/current>.

Can be used as an lvalue to set the current context, although this should
in general be localised. This function always returns an
L<OpenTelemetry::Context> object.

=head2 otel_error_handler

    $handler = otel_error_handler;
    otel_error_handler = $new_error_handler;

Behaves exactly as the L</error_handler> class method described above. Can be
used as an lvalue.

=head2 otel_handle_error

    otel_handle_error(
        exception => $exception,
        message   => $message,
        ...
    );

Behaves exactly as the L</handle_error> class method described above.

=head2 otel_logger_provider

    $logger_provider = otel_logger_provider;
    otel_logger_provider = $new_logger_provider;

Behaves exactly as the L</logger_provider> class method described above. Can
be used as an lvalue.

=head2 otel_propagator

    $propagator = otel_propagator;
    otel_propagator = $new_propagator;

Behaves exactly as the L</propagator> class method described above. Can be
used as an lvalue.

=head2 otel_span_from_context

    $span = otel_span_from_context( $context // undef );

Takes a L<OpenTelemetry::Context> as its only argument and returns the span
in the context. If no context is provided, the span will be read from the
current context.

This is provided as a convenience method and behaves exactly as
L<OpenTelemetry::Trace/span_from_context>.

=head2 otel_tracer_provider

    $tracer_provider = otel_tracer_provider;
    otel_tracer_provider = $new_tracer_provider;

Behaves exactly as the L</tracer_provider> class method described above. Can
be used as an lvalue.

=head2 otel_untraced_context

    $context = otel_untraced_context;

Gets the a L<OpenTelemetry::Context> where tracing has been disabled. This
is provided as a convenience method and behaves exactly as
L<OpenTelemetry::Trace/untraced_context>.

Available from 0.012.

=head1 SEE ALSO

=over

=item L<Log::Any>

=item L<Metrics::Any>

=item L<OpenTelemetry::SDK>

=item L<https://opentelemetry.io>

=back

=head1 ACKNOWLEDGEMENTS

Special thanks to L<CV-Library Ltd.|https://cv-library.co.uk> for their
support in the development of this library.

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2023 by José Joaquín Atria.

This is free software; you can redistribute it and/or modify it under the same
terms as the Perl 5 programming language system itself.
