This guide explains how to send additional logs to Metoro using OpenTelemetry. Metoro supports the OpenTelemetry Protocol (OTLP) for log ingestion, allowing you to send logs from any application or service that can export OpenTelemetry logs.

Prerequisites

  • A Metoro account
  • An application configured with OpenTelemetry

Pricing

Custom logs are billed at $0.30 per GB.

High Level Overview

The metoro exporter running in each cluster is a fully compliant OpenTelemetry collector. This means that you can send logs to Metoro using any OpenTelemetry compatible tracing library.

Endpoint Configuration

Configure your OpenTelemetry exporter to send logs to:

http://metoro-exporter.metoro.svc.cluster.local/api/v1/send/logs/otel

This endpoint is available within your Kubernetes cluster where the Metoro exporter is installed.

Authentication

No additional authentication is required when sending logs from within the cluster to the Metoro exporter.

OpenTelemetry Collector Configuration

If you’re using the OpenTelemetry Collector to forward logs to Metoro, here’s an example configuration:

receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  batch:
    timeout: 10s
    send_batch_size: 1000

exporters:
  otlphttp:
    endpoint: http://metoro-exporter.metoro.svc.cluster.local:8080/api/v1/logs/otel
    tls:
      insecure: true # Since we're in-cluster

service:
  pipelines:
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlphttp]

This configuration:

  • Receives logs via OTLP over both HTTP (4318) and gRPC (4317)
  • Batches logs for efficient transmission
  • Forwards logs to the Metoro exporter
  • Uses insecure communication since we’re within the cluster

Language-Specific Examples

Go

package main

import (
    "context"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
    "go.opentelemetry.io/otel/sdk/resource"
    sdklog "go.opentelemetry.io/otel/sdk/log"
    semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)

func initLogger() (*sdklog.LoggerProvider, error) {
    ctx := context.Background()

    exporter, err := otlploghttp.New(ctx,
        otlploghttp.WithEndpoint("metoro-exporter.metoro.svc.cluster.local:8080"),
        otlploghttp.WithURLPath("/api/v1/logs/otel"),
        otlploghttp.WithInsecure(), // Since we're in-cluster
    )
    if err != nil {
        return nil, err
    }

    resource := resource.NewWithAttributes(
        semconv.SchemaURL,
        semconv.ServiceName("your-service-name"),
    )

    loggerProvider := sdklog.NewLoggerProvider(
        sdklog.WithBatcher(exporter),
        sdklog.WithResource(resource),
    )

    return loggerProvider, nil
}

Python

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

def init_logger():
    exporter = OTLPSpanExporter(
        endpoint="http://metoro-exporter.metoro.svc.cluster.local:8080/api/v1/logs/otel",
        insecure=True  # Since we're in-cluster
    )

    resource = Resource.create({
        "service.name": "your-service-name"
    })

    provider = TracerProvider(resource=resource)
    processor = BatchSpanProcessor(exporter)
    provider.add_span_processor(processor)
    
    return provider

Node.js

const { LoggerProvider } = require('@opentelemetry/sdk-logs');
const { OTLPLogExporter } = require('@opentelemetry/exporter-logs-otlp-http');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');

const resource = new Resource({
  [SemanticResourceAttributes.SERVICE_NAME]: 'your-service-name',
});

const logExporter = new OTLPLogExporter({
  url: 'http://metoro-exporter.metoro.svc.cluster.local:8080/api/v1/logs/otel',
  headers: {},
});

const loggerProvider = new LoggerProvider({
  resource: resource,
});

loggerProvider.addLogRecordProcessor(new BatchLogRecordProcessor(logExporter));

Attributes and Context

When sending logs via OpenTelemetry, you can include additional attributes that will be indexed and searchable in Metoro:

  • Use resource attributes to define static information about the service
  • Use log attributes to include dynamic information with each log entry
  • Link logs with traces using trace context propagation

Troubleshooting

If you encounter issues with OpenTelemetry log ingestion:

  1. Verify your endpoint URL and API key are correct
  2. Check your network connectivity to the Metoro OTLP endpoint
  3. Enable debug logging in your OpenTelemetry SDK
  4. Verify your logs appear in the Metoro logs view
  5. Contact support if issues persist

Additional Resources