NAME
OpenTelemetry::Instrumentation::Mango - OpenTelemetry instrumentation for Mango
SYNOPSIS
use OpenTelemetry::Instrumentation 'Mango';
my $mango = Mango->new('mongodb://localhost:27017');
$mango->db('test')->collection('foo')->insert({ bar => 'baz' });
# ... a client span is created for the operation
DESCRIPTION
OpenTelemetry::Instrumentation::Mango adds OpenTelemetry tracing to the Mango MongoDB driver. It follows the same model as OpenTelemetry::Instrumentation::DBI: installing this instrumentation wraps selected methods so that every MongoDB operation runs inside a CLIENT span.
Yes, Mango uses an obsolete wire protocol, and yes, it has not been updated since 2014, but it still works with older versions of MongoDB and this module will emit telemetry for this stack if you need it.
The instrumentation wraps the semantic funnels of Mango, which means every wire operation is covered:
"command" in Mango::Database: every database command (which includes all collection CRUD operations, as they are implemented as commands:
insert,update,delete,findAndModify,count,distinct,aggregate, and friends).Mango::Cursor::Query
_start: the initialfindquery."get_more" in Mango and "kill_cursors" in Mango: cursor pagination and cleanup.
Spans
Each operation produces a span named "<operation> <db.collection>" (for example insert test.foo), or "<operation> <db>" for database-level commands without a collection target. The name is truncated to 100 characters. Because "kill_cursors" in Mango receives a cursor id rather than a namespace, the id is kept in the span name instead of any database attributes.
Attributes
Spans generated by this instrumentation will record the following attributes:
db.system.name-
Always
mongodb. db.name-
Name of the database the operation ran against.
db.collection.name-
Name of the targeted collection, when the operation targets one.
db.operation.name-
The operation: the command name for database commands (
insert,count,findAndModify, ...), orfind,get_more,kill_cursors. db.statement-
The command or query document encoded as JSON, truncated to 512 characters. Omitted if it cannot be encoded.
server.addressandserver.port-
Taken from the first entry of
$mango->hosts, with a default value of 27017.
Blocking and non-blocking operations
Both blocking and non-blocking (callback-style) operations are supported. For blocking operations, the span is ended once the call returns (or dies, in which case the exception is recorded and the span status is set to error). For non-blocking operations, the span is ended when Mango invokes the callback: the status is set to error if Mango passed an error as the first callback argument after the invokant, and to success otherwise. The callback runs with the captured context restored, so spans created inside it nest under the operation span. Please not that if Mango never invokes the callback, the span for the non-blocking operation will not be ended.
This instrumentation never starts or stops any event loop, so it is safe to use under Mojolicious applications: blocking operations continue to use the Mango object's own ioloop, and non-blocking operations continue to be driven by whatever loop is running the application.
Testing with Test::Mock::Mango
If Test::Mock::Mango is loaded before this instrumentation is installed, the same wrappers are installed on the mocked classes (Test::Mock::Mango::DB, Test::Mock::Mango::Collection, and Test::Mock::Mango::Cursor), which lets you test instrumented code without a MongoDB server. In production, Test::Mock::Mango is not loaded, so this has no effect. Note that mocked cursors carry no collection reference, so spans produced through them only carry the operation name. Additionally, spans produced through mocked collection methods do not carry a db.statement attribute.
Running the integration tests
The test suite is fully offline by default: t/OpenTelemetry/Instrumentation/Mango.t runs against Test::Mock::Mango stubs and never opens a network connection. Additionally, t/online.t runs the same instrumentation against a real MongoDB server, but only when the TEST_ONLINE environment variable holds a connection string; without it, that test skips.
Note that as mentioned above Mango speaks MongoDB's legacy wire protocol, which was deprecated in MongoDB 5.0 and removed in MongoDB 5.1, so use a server of version 5.0 or earlier. For example, with Docker:
docker run --rm -d --name otel-mango-test \
-p 127.0.0.1:28017:27017 mongo:4.4
TEST_ONLINE=mongodb://127.0.0.1:28017 prove -lv t/online.t
docker stop otel-mango-test
The test uses its own database (otel_mango_online_test) and drops it when it finishes, and the container above is removed as soon as it stops, so no data is left behind.
TODO
SEE ALSO
- OpenTelemetry
- OpenTelemetry::Instrumentation
- OpenTelemetry::Instrumentation::DBI.
- Mango,
- Test::Mock::Mango.
AUTHORS
Javier Arturo Rodriguez <javier@cpan.org>
A significant part of this code has been shamelessly ripped off OpenTelemetry::Instrumentation::DBI written by José Joaquín Atria.
COPYRIGHT
This software is copyright (c) 2026 by Javier Arturo Rodriguez.
LICENSE
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.