Configure OpenTelemetry
π If you have any questions shoot us an email or join us on Discord! π
Overviewβ
Multiplayer leverages OpenTelemetry for two features:
-
Auto-Documentation: When enabled, it automatically discovers all components, APIs, dependencies, platforms, and environments within your software system and lists them within the System Dashboard and your individual Platform architecture diagrams
-
Platform Debugger: Record and share deep session replays that include relevant data from frontend screens to distributed traces metrics and logs from your backend platform.
βΉοΈ These two features share the same set up window and the following OpenTelemetry configuration steps.
1. Set up the OpenTelemetry Integrationβ
- Open your project
- In the left-side menu, click "System" to open the System Dashboard
- Click "Configure Auto-Docs + Debugger"
- Name your integration
- Hit "Create"
- An OpenTelemetry (OTel) token will be created for your OTel integration.
Once you click βConfirmβ, we will proceed with the Multiplayer OTel integration and start automatically documenting your system and adding backend data (e.g. traces and logs) to your Platform Debugger sessions.
Please note that if you close the set up window before finishing the set up (or before copying the generated tokens), you will no longer be able to see the Otel tokens. You need to delete the integration and start again to generate new OTel tokens.
2. Configuring OTelβ
π Pro tip: If you're setting up the Platform Debugger, you'll need to incorporate the web library into your application (and enable the widget) in order to start recording a debugger session.
- JavaScript (web)
- Node.Js
- Go
- Python
- Ruby
- .NET
- Java
- PHP
- Rust
- Swift
- Generic
- Install session debugger library with following command:
npm i -S @multiplayer-app/session-debugger
- Initialize session debugger library:
// NOTE: this import should be done before all other imports in your main file.
import SessionDebugger from "@multiplayer-app/session-debugger";
SessionDebugger.init({
version: "<web-app-version>",
application: "<web-app-name>",
environment: "<web-app-environment>",
apiKey: "<multiplayer-key>",
canvasEnabled: true,
showWidget: true,
ignoreUrls: [
/https:\/\/domain\.to\.ignore\/.*/, // can be regex or string
/https:\/\/another\.domain\.to\.ignore\/.*/,
],
// NOTE: if frontend domain doesn't match to backend one, set backend domain to `propagateTraceHeaderCorsUrls` parameter
propagateTraceHeaderCorsUrls: [
new RegExp("https://your.backend.api.domain", "i"), // can be regex or string
new RegExp("https://another.backend.api.domain", "i")
],
schemifyDocSpanPayload: true,
maskDebSpanPayload: true,
docTraceRatio: 0.15 // 15% of traces will be sent for auto-documentation
});
// Optional
window["mpSessionDebuggerMetadata"] = {
userId: "12345",
userName: "John Doe",
};
- Install required packages run command:
npm i -S @multiplayer-app/otlp-core \
@opentelemetry/api \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/core \
@opentelemetry/exporter-trace-otlp-http \
@opentelemetry/resources \
@opentelemetry/sdk-node \
@opentelemetry/sdk-trace-base \
@opentelemetry/semantic-conventions \
@opentelemetry/sdk-logs \
@opentelemetry/api-logs
- Create a file
opentelemetry.js
. Put following content into it:
import { hostname } from "os"
import { node, NodeSDK } from "@opentelemetry/sdk-node"
import {
BatchSpanProcessor,
ParentBasedSampler,
} from "@opentelemetry/sdk-trace-base"
import {
getNodeAutoInstrumentations,
getResourceDetectors,
} from "@opentelemetry/auto-instrumentations-node"
import { detectResourcesSync, Resource } from "@opentelemetry/resources"
import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
SEMRESATTRS_HOST_NAME,
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
SEMRESATTRS_PROCESS_RUNTIME_VERSION,
SEMRESATTRS_PROCESS_PID,
} from "@opentelemetry/semantic-conventions"
import api from "@opentelemetry/api"
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
import { W3CTraceContextPropagator } from "@opentelemetry/core"
import {
MultiplayerHttpTraceExporterNode,
MultiplayerTraceIdRatioBasedSampler,
MultiplayerIdGenerator,
MultiplayerFilterTraceExporter,
MultiplayerHttpInstrumentationHooks,
MultiplayerHttpLogExporterNode,
} from "@multiplayer-app/otlp-core"
import { LoggerProvider, BatchLogRecordProcessor } from "@opentelemetry/sdk-logs"
import apiLogs from "@opentelemetry/api-logs"
// import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'
// NOTE: Change those variables before testing
const SERVICE_NAME = "<example-service-name>"
const SERVICE_VERSION = "<service-version>"
const PLATFORM_ENV = "<environment-name>"
const MULTIPLAYER_OTLP_KEY = "<multiplayer-key>"
// NOTE: Update instrumentation configuration as needed
// For more see: https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node
const instrumentations = [
getNodeAutoInstrumentations({
"@opentelemetry/instrumentation-http": {
requestHook: MultiplayerHttpInstrumentationHooks.requestHook({
headersToMask: ["X-Api-Key"],
maxPayloadSize: 5000,
schemifyDocSpanPayload: true
maskDebSpanPayload: true
}),
responseHook: MultiplayerHttpInstrumentationHooks.responseHook({
headersToMask: ["X-Api-Key"],
maxPayloadSize: 5000,
schemifyDocSpanPayload: true
maskDebSpanPayload: true
}),
},
}),
]
const getResource = () => {
const resourcesWithDetectors = detectResourcesSync({
detectors: getResourceDetectors(),
})
const resourceWithAttributes = new Resource({
[ATTR_SERVICE_NAME]: SERVICE_NAME,
[ATTR_SERVICE_VERSION]: SERVICE_VERSION,
[SEMRESATTRS_HOST_NAME]: hostname(),
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: PLATFORM_ENV,
[SEMRESATTRS_PROCESS_RUNTIME_VERSION]: process.version,
[SEMRESATTRS_PROCESS_PID]: process.pid,
})
const resource = resourceWithAttributes.merge(resourcesWithDetectors)
return resource
}
const opentelemetry = () => {
// NOTE: Either use MultiplayerHttpTraceExporterNode or OTLPTraceExporter
const multiplayerTraceExporter = new MultiplayerHttpTraceExporterNode({
apiKey: MULTIPLAYER_OTLP_KEY,
})
// const multiplayerTraceExporter = new OTLPTraceExporter({
// url: 'https://api.multiplayer.app/v1/traces',
// headers: {
// Authorization: MULTIPLAYER_OTLP_KEY
// },
// })
// NOTE: if you want to send traces to one more OpenTelemetry provider
// uncomment lines below use these variables: `apmProviderTraceExporter`, `apmProviderTraceExporter`
// const apmProviderTraceExporter = new OTLPTraceExporter({
// url: 'http://some.collector.url/v1/traces',
// })
// NOTE: Use MultiplayerFilterTraceExporter exporter wrapper to remove Multiplayer attributes (starts with `multiplayer.*` prefix)
// before sending traces to your APM provider
// const apmFilteredTraceExporter = new MultiplayerFilterTraceExporter(apmProviderTraceExporter)
const resource = getResource()
const provider = new node.NodeTracerProvider({
resource,
spanProcessors: [
// new BatchSpanProcessor(apmFilteredTraceExporter),
new BatchSpanProcessor(multiplayerTraceExporter),
],
sampler: new ParentBasedSampler({
// NOTE: this config will send 80% of all traces + 100% of debug traces + 30% of 80% document traces
root: new MultiplayerTraceIdRatioBasedSampler(0.8),
}),
// NOTE: this will set 30% of the traces sampled above for auto documentation
idGenerator: new MultiplayerIdGenerator({ autoDocTracesRatio: 0.3 }),
})
// Initialise logger provider and exporting logs to collector
const loggerProvider = new LoggerProvider({
resource,
})
// NOTE: Either use `MultiplayerHttpLogExporterNode` or `OTLPLogExporter`
const multiplayerLogExporter = new MultiplayerHttpLogExporterNode({
apiKey: MULTIPLAYER_OTLP_KEY,
})
// const multiplayerLogExporter = new OTLPLogExporter({
// url: 'https://api.multiplayer.app/v1/logs',
// headers: {
// Authorization: MULTIPLAYER_OTLP_KEY
// },
// })
const logRecordProcessor = new BatchLogRecordProcessor(multiplayerLogExporter)
loggerProvider.addLogRecordProcessor(logRecordProcessor)
apiLogs.logs.setGlobalLoggerProvider(loggerProvider)
provider.register()
api.trace.setGlobalTracerProvider(provider)
api.propagation.setGlobalPropagator(new W3CTraceContextPropagator())
const sdk = new NodeSDK({
instrumentations,
})
sdk.start()
}
opentelemetry()
- Import
opentelemetry.js
into your main app file (for exampleindex.js
).
// Note: import `opentelemetry.js` at the top your main app file.
import "./opentelemetry.js"
import http from "http"
const httpServer = http.createServer(app)
// ...
httpServer.listen(3000)
If you're using common.js
syntax, here is example:β
const { hostname } = require("os")
const { node, NodeSDK } = require("@opentelemetry/sdk-node")
const {
BatchSpanProcessor,
ParentBasedSampler,
} = require("@opentelemetry/sdk-trace-base")
const {
getNodeAutoInstrumentations,
getResourceDetectors
} = require("@opentelemetry/auto-instrumentations-node")
const { detectResourcesSync, Resource } = require("@opentelemetry/resources")
const {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
ATTR_HOST_NAME,
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
SEMRESATTRS_PROCESS_RUNTIME_VERSION,
SEMRESATTRS_PROCESS_PID,
} = require("@opentelemetry/semantic-conventions")
const api = require("@opentelemetry/api")
const { OTLPTraceExporter } = require("@opentelemetry/exporter-trace-otlp-http")
const { W3CTraceContextPropagator } = require("@opentelemetry/core")
const {
MultiplayerHttpTraceExporterNode,
MultiplayerTraceIdRatioBasedSampler,
MultiplayerIdGenerator,
MultiplayerFilterTraceExporter,
MultiplayerHttpInstrumentationHooks,
MultiplayerHttpLogExporterNode
} = require("@multiplayer-app/otlp-core")
const { LoggerProvider, BatchLogRecordProcessor } = require("@opentelemetry/sdk-logs")
const apiLogs = require("@opentelemetry/api-logs")
// const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-http')
// NOTE: Change those variables before testing
const SERVICE_NAME = "<example-service-name>"
const SERVICE_VERSION = "<service-version>"
const PLATFORM_ENV = "<environment-name>"
const MULTIPLAYER_OTLP_KEY = "<multiplayer-key>"
// NOTE: Update instrumentation configuration as needed
// For more see: https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node
const instrumentations = [
getNodeAutoInstrumentations({
"@opentelemetry/instrumentation-http": {
// Add http request payload and headers to span
requestHook: MultiplayerHttpInstrumentationHooks.requestHook({
headersToMask: ["X-Api-Key"],
maxPayloadSize: 5000,
schemifyDocSpanPayload: true
maskDebSpanPayload: true
}),
// Add http response payload and headers to span
responseHook: MultiplayerHttpInstrumentationHooks.responseHook({
headersToMask: [],
maxPayloadSize: 5000,
schemifyDocSpanPayload: true
maskDebSpanPayload: true
})
}
}),
]
const getResource = () => {
const resourcesWithDetectors = detectResourcesSync({
detectors: getResourceDetectors()
})
const resourceWithAttributes = new Resource({
[ATTR_SERVICE_NAME]: SERVICE_NAME,
[ATTR_SERVICE_VERSION]: SERVICE_VERSION,
[ATTR_HOST_NAME]: hostname(),
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: PLATFORM_ENV,
[SEMRESATTRS_PROCESS_RUNTIME_VERSION]: process.version,
[SEMRESATTRS_PROCESS_PID]: process.pid
})
const resource = resourceWithAttributes.merge(resourcesWithDetectors)
return resource
}
const opentelemetry = () => {
// NOTE: Either use MultiplayerHttpTraceExporterNode or OTLPTraceExporter
const multiplayerTraceExporter = new MultiplayerHttpTraceExporterNode({
apiKey: MULTIPLAYER_OTLP_KEY,
})
// const multiplayerTraceExporter = new OTLPTraceExporter({
// url: 'https://api.multiplayer.app/v1/traces',
// headers: {
// Authorization: MULTIPLAYER_OTLP_KEY
// },
// })
// NOTE: if you want to send traces to one more OpenTelemetry provider
// uncomment lines below use these variables: `apmProviderTraceExporter`, `apmProviderTraceExporter`
// const apmProviderTraceExporter = new OTLPTraceExporter({
// url: 'http://some.collector.url/v1/traces',
// })
// NOTE: Use MultiplayerFilterTraceExporter exporter wrapper to remove Multiplayer attributes (starts with `multiplayer.*` prefix)
// before sending traces to your APM provider
// const apmFilteredTraceExporter = new MultiplayerFilterTraceExporter(apmProviderTraceExporter)
const resource = getResource()
const provider = new node.NodeTracerProvider({
resource,
spanProcessors: [
// new BatchSpanProcessor(apmFilteredTraceExporter),
new BatchSpanProcessor(multiplayerTraceExporter),
],
sampler: new ParentBasedSampler({
// NOTE: this config will send 80% of all traces + 100% of debug traces + 30% of 80% document traces
root: new MultiplayerTraceIdRatioBasedSampler(0.8),
}),
// NOTE: this will set 30% of the traces sampled above for auto documentation
idGenerator: new MultiplayerIdGenerator({ autoDocTracesRatio: 0.3 }),
})
// Initialise logger provider and exporting logs to collector
const loggerProvider = new LoggerProvider({
resource,
})
// NOTE: Either use `MultiplayerHttpLogExporterNode` or `OTLPLogExporter`
const multiplayerLogExporter = new MultiplayerHttpLogExporterNode({
apiKey: MULTIPLAYER_OTLP_KEY,
})
// const multiplayerLogExporter = new OTLPLogExporter({
// url: 'https://api.multiplayer.app/v1/logs',
// headers: {
// Authorization: MULTIPLAYER_OTLP_KEY
// },
// })
const logRecordProcessor = new BatchLogRecordProcessor(multiplayerLogExporter)
loggerProvider.addLogRecordProcessor(logRecordProcessor)
apiLogs.logs.setGlobalLoggerProvider(loggerProvider)
provider.register()
api.trace.setGlobalTracerProvider(provider)
api.propagation.setGlobalPropagator(new W3CTraceContextPropagator())
const sdk = new NodeSDK({
instrumentations
})
sdk.start()
}
opentelemetry()
module.exports.opentelemetry = opentelemetry
- Install modules:
go get "github.com/multiplayer-app/multiplayer-otlp-go" \
"go.opentelemetry.io/otel" \
"go.opentelemetry.io/otel/sdk"
- Setup Opentelemetry SDK
package main
import (
"context"
"errors"
"github.com/multiplayer-app/multiplayer-otlp-go"
"os"
"time"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/trace"
)
// setupOTelSDK bootstraps the OpenTelemetry pipeline.
// If it does not return an error, make sure to call shutdown for proper cleanup.
func setupOTelSDK(ctx context.Context) (shutdown func(context.Context) error, err error) {
var shutdownFuncs []func(context.Context) error
// shutdown calls cleanup functions registered via shutdownFuncs.
// The errors from the calls are joined.
// Each registered cleanup will be invoked once.
shutdown = func(ctx context.Context) error {
var err error
for _, fn := range shutdownFuncs {
err = errors.Join(err, fn(ctx))
}
shutdownFuncs = nil
return err
}
// handleErr calls shutdown for cleanup and makes sure that all errors are returned.
handleErr := func(inErr error) {
err = errors.Join(inErr, shutdown(ctx))
}
// Set up propagator.
prop := newPropagator()
otel.SetTextMapPropagator(prop)
// Set up trace provider.
tracerProvider, err := newTraceProvider()
if err != nil {
handleErr(err)
return
}
shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown)
otel.SetTracerProvider(tracerProvider)
return
}
func newPropagator() propagation.TextMapPropagator {
return propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{},
propagation.Baggage{},
)
}
func newTraceProvider() (*trace.TracerProvider, error) {
multiplayerOtlpKey := os.Getenv("MULTIPLAYER_OTLP_KEY")
traceExporter := multiplayer.NewExporter(multiplayerOtlpKey)
traceProvider := trace.NewTracerProvider(
trace.WithIDGenerator(multiplayer.NewRatioDependentIdGenerator(1)),
trace.WithSampler(multiplayer.NewSampler(trace.AlwaysSample())),
trace.WithBatcher(traceExporter,
trace.WithBatchTimeout(time.Second)),
)
return traceProvider, nil
}
- Set middlewares if you want to include http request/response structure to documentation
// init http handler
options := multiplayer.NewMiddlewareOptions()
handler = multiplayer.WithResponseData(handler, options)
handler = multiplayer.WithRequestData(handler, options)
- Install required packages run command:
pip install \
multiplayer-opentelemetry\
opentelemetry-api\
opentelemetry-sdk
- Setup Opentelemetry SDK
from random import randint
from flask import Flask, request
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.sdk.resources import SERVICE_NAME, SERVICE_VERSION, DEPLOYMENT_ENVIRONMENT, Resource
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from multiplayer.opentelemetry.exporter.http.trace_exporter import MultiplayerOTLPSpanExporter
from multiplayer.opentelemetry.exporter.http.log_exporter import MultiplayerOTLPLogExporter
from multiplayer.opentelemetry.trace.sampler import MultiplayerTraceIdRatioBasedSampler
from multiplayer.opentelemetry.trace.id_generator import MultiplayerRandomIdGenerator
import logging
logging.basicConfig(level=logging.INFO)
MULTIPLAYER_OTLP_KEY = "<multiplayer-otlp-key>"
id_generator = MultiplayerRandomIdGenerator(autoDocTracesRatio = 1/2)
sampler = MultiplayerTraceIdRatioBasedSampler(rate = 1/2)
# Service name is required for most backends
resource = Resource(attributes={
SERVICE_NAME: "<example-service-name>",
SERVICE_VERSION: "<service-version>",
DEPLOYMENT_ENVIRONMENT: "<environment-name>"
})
traceProvider = TracerProvider(
resource = resource,
sampler = sampler,
id_generator = id_generator
)
processor = BatchSpanProcessor(MultiplayerOTLPSpanExporter(
apiKey = MULTIPLAYER_OTLP_KEY
))
traceProvider.add_span_processor(processor)
trace.set_tracer_provider(traceProvider)
logger_provider = LoggerProvider(
resource=Resource.create(
{
"service.name": "shoppingcart",
"service.instance.id": "instance-12",
}
),
)
set_logger_provider(logger_provider)
exporter = MultiplayerOTLPLogExporter(
apiKey = MULTIPLAYER_OTLP_KEY
)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
handler = LoggingHandler(level=logging.NOTSET, logger_provider=logger_provider)
instrumentor = FlaskInstrumentor()
app = Flask(__name__)
instrumentor.instrument_app(app)
logger = logging.getLogger(__name__)
@app.route("/rolldice")
def roll_dice():
player = request.args.get('player', default=None, type=str)
result = str(roll())
if player:
logger.warning("%s is rolling the dice: %s", player, result)
else:
logger.warning("Anonymous player is rolling the dice: %s", result)
return result
def roll():
return randint(1, 6)
if __name__ == "__main__":
app.run(port=8080)
- Install required packages run command:
bundle add multiplayer-otlp
- add opentelemetry configuration
# config/initializers/opentelemetry.rb
require "opentelemetry-sdk"
require "socket"
require "opentelemetry-exporter-otlp"
require "opentelemetry-api"
require "multiplayer_otlp"
resource = OpenTelemetry::SDK::Resources::Resource.create({
OpenTelemetry::SemanticConventions::Resource::SERVICE_NAME => "<service_name>",
OpenTelemetry::SemanticConventions::Resource::SERVICE_VERSION => "<service_version>",
OpenTelemetry::SemanticConventions::Resource::HOST_NAME => Socket.gethostname,
OpenTelemetry::SemanticConventions::Resource::DEPLOYMENT_ENVIRONMENT => "<environment_name>",
})
mp_exporter = Multiplayer::Exporter.new(Multiplayer::ExporterConfig.new(api_key: MULTIPLAYER_OTLP_KEY))
OpenTelemetry::SDK.configure do |c|
c.add_span_processor(OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(mp_exporter))
c.resource = resource
c.use_all
end
OpenTelemetry.tracer_provider.sampler = Multiplayer::Utils::TraceIdRatioBasedSampler.new(0.1) # change scale if needed (0 - never, 1- always)
OpenTelemetry.tracer_provider.id_generator = Multiplayer::Utils::IdGenerator.new(0.1) # change scale if needed (0 - never, 1- always)
- Set middlewares if you want to include http request/response structure to documentation
# Add middlewares in config/application.rb
# Example:
config.middleware.insert_before 0, Multiplayer::RequestMiddleware, headers_to_mask: [ "AUTH_HEADER_NAME" ]
config.middleware.use Multiplayer::ResponseMiddleware, headers_to_mask: [ "AUTH_HEADER_NAME" ]
- Create and launch an HTTP Server. To do that - execute following command:
dotnet new web
- Install required packages run command:
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package MultiplayerOpentelemetry
- In
Program.cs
, add the following lines:
using System.Diagnostics;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using OpenTelemetry;
using Multiplayer.OpenTelemetry.Exporter;
using Multiplayer.OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
const string SERVICE_NAME = "<example-service-name>";
const string SERVICE_VERSION = "<service-version>";
const string environment = "<environment-name>";
const string MULTIPLAYER_OTLP_KEY = "<multiplayer-key>";
var builder = WebApplication.CreateBuilder(args);
MultiplayerTraceIdConfiguration.ConfigureMultiplayerTraceIdGenerator(0.5);
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource =>
{
resource.AddService(
serviceName: builder.Configuration.GetValue<string>("ServiceName", SERVICE_NAME)!,
serviceNamespace: environment,
serviceVersion: typeof(Program).Assembly.GetName().Version?.ToString() ?? SERVICE_VERSION,
serviceInstanceId: Environment.MachineName
)
// Adding more resource attributes (optional)
.AddAttributes(new Dictionary<string, object>
{
{ "deployment.environment", environment },
{ "service.name", builder.Configuration.GetValue<string>("ServiceName", SERVICE_NAME) },
// Add any additional custom attributes here
});
})
.WithTracing(tracing =>
{
tracing.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation()
.SetSampler(new MultiplayerTraceIdRatioBasedSampler(0.5))
.AddProcessor(new SimpleActivityExportProcessor(new MultiplayerOtlpHttpTracesExporter(
MULTIPLAYER_OTLP_KEY
)));
})
.WithLogging(logs => logs
.AddProcessor(new BatchLogRecordExportProcessor(new MultiplayerOtlpHttpLogsExporter(MULTIPLAYER_OTLP_KEY))));
- Add required packages to your project.
dependencies {
// ...
implementation 'io.opentelemetry:opentelemetry-api:1.35.0'
implementation 'io.opentelemetry:opentelemetry-sdk:1.35.0'
implementation 'io.opentelemetry:opentelemetry-sdk-logs:1.35.0'
implementation 'io.opentelemetry:opentelemetry-exporter-otlp:1.35.0'
implementation 'app.multiplayer:opentelemetry:0.0.1'
// ...
}
- Create a file
OpenTelemetryConfig.java
. Put following content into it:
package app.multiplayer.demo.opentelemetry;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import app.multiplayer.opentelemetry.trace.MultiplayerRandomIdGenerator;
import app.multiplayer.opentelemetry.exporter.MultiplayerOtlpHttpLogExporter;
import app.multiplayer.opentelemetry.exporter.MultiplayerOtlpHttpSpanExporter;
import app.multiplayer.opentelemetry.trace.samplers.MultiplayerTraceIdRatioBasedSampler;
public class OpenTelemetryConfig {
public static void initialize() {
String SERVICE_NAME = "<example-service-name>";
String SERVICE_VERSION = "<service-version>";
String PLATFORM_ENV = "<environment-name>";
String MULTIPLAYER_OTLP_KEY = "<multiplayer-key>";
SpanExporter multiplayerSpanExporter = new MultiplayerOtlpHttpSpanExporter(MULTIPLAYER_OTLP_KEY);
LogRecordExporter multiplayerLogsExporter = new MultiplayerOtlpHttpLogExporter(MULTIPLAYER_OTLP_KEY);
Sampler sampler = MultiplayerTraceIdRatioBasedSampler.create(0.5);
SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
.setIdGenerator(new MultiplayerRandomIdGenerator(0.5))
.setSampler(sampler)
.addSpanProcessor(BatchSpanProcessor.builder(multiplayerSpanExporter).build())
.build();
SdkLoggerProvider loggerProvider = SdkLoggerProvider.builder()
.addLogRecordProcessor(BatchLogRecordProcessor.builder(multiplayerLogsExporter).build())
.build();
OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder()
.setTracerProvider(tracerProvider)
.setLoggerProvider(loggerProvider)
.buildAndRegisterGlobal();
}
}
- Call
OpenTelemetryConfig.initialize()
in your main java file:
public class App {
public static void main(String[] args) {
// ...
OpenTelemetryConfig.initialize();
// ...
}
// Coming soon
// Coming soon
// Coming soon
Send opentelemetry traces to endpoint: https://api.multiplayer.app/v1/traces
.
Send opentelemetry logs to endpoint: https://api.multiplayer.app/v1/logs
.
In order to send OTLP data to Multiplayer, you must configure your OTLP exporter to include a header named Authorization
with the value set to your key. Failure to do so will result in authentication errors.
OTEL_EXPORTER_OTLP_HEADERS=Authorization=<INSERT_KEY>
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://api.multiplayer.app/v1/traces
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://api.multiplayer.app/v1/logs
Next Stepsβ
You did it! Whatβs next?