All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.comcast.money.otel.handlers.OtelSpanHandler.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2012 Comcast Cable Communications Management, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.comcast.money.otel.handlers

import com.comcast.money.api.{ SpanHandler, SpanInfo }
import com.typesafe.config.{ Config, ConfigFactory }
import io.opentelemetry.api.common.{ AttributeKey, Attributes }
import io.opentelemetry.sdk.trace.SpanProcessor
import io.opentelemetry.sdk.trace.`export`.{ BatchSpanProcessor, SimpleSpanProcessor, SpanExporter }

import scala.collection.JavaConverters._
import java.time.Duration

/**
 * An abstract `SpanHandler` that can wrap an OpenTelemetry `SpanExporter` implementation
 * and export spans to an OpenTelemetry-compatible exporter such as ZipKin or Jaeger.
 */
abstract class OtelSpanHandler(config: Config) extends SpanHandler {

  private[otel] val resourceAttributes: Attributes = createResourceAttributes(config)
  private[otel] val exporter: SpanExporter = createSpanExporter(getExporterConfig(config))
  private[otel] val processor: SpanProcessor = createSpanProcessor(exporter, config)

  /**
   * Handles a span that has been stopped.
   *
   * @param span `SpanInfo` that contains the information for the completed span
   */
  override def handle(span: SpanInfo): Unit = {
    processor.onEnd(new MoneyReadableSpanData(span, resourceAttributes))
  }

  protected def createResourceAttributes(config: Config): Attributes = {

    val resourceKey = "resource"
    if (config.hasPath(resourceKey)) {
      val attributes = Attributes.builder()
      val resourceConfig = config.getConfig(resourceKey)
      for (entry <- resourceConfig.entrySet().asScala) {
        val key = entry.getKey
        val value = resourceConfig.getString(key)
        attributes.put(AttributeKey.stringKey(key), value)
      }
      attributes.build()
    } else {
      Attributes.empty()
    }
  }

  protected def createSpanProcessor(spanExporter: SpanExporter, config: Config): SpanProcessor = {
    val batchKey = "batch"
    val batch = config.hasPath(batchKey) && config.getBoolean(batchKey)
    if (batch) {
      configureBatchProcessor(spanExporter, config)
    } else {
      SimpleSpanProcessor.create(spanExporter)
    }
  }

  private def configureBatchProcessor(spanExporter: SpanExporter, config: Config): SpanProcessor = {
    val builder = BatchSpanProcessor.builder(spanExporter)

    val exporterTimeoutMillisKey = "exporter-timeout-ms"
    val maxExportBatchSizeKey = "max-batch-size"
    val maxQueueSizeKey = "max-queue-size"
    val scheduleDelayMillisKey = "schedule-delay-ms"

    if (config.hasPath(exporterTimeoutMillisKey)) {
      builder.setExporterTimeout(Duration.ofMillis(config.getInt(exporterTimeoutMillisKey)))
    }
    if (config.hasPath(maxExportBatchSizeKey)) {
      builder.setMaxExportBatchSize(config.getInt(maxExportBatchSizeKey))
    }
    if (config.hasPath(maxQueueSizeKey)) {
      builder.setMaxQueueSize(config.getInt(maxQueueSizeKey))
    }
    if (config.hasPath(scheduleDelayMillisKey)) {
      builder.setScheduleDelay(Duration.ofMillis(config.getLong(scheduleDelayMillisKey)))
    }

    builder.build()
  }

  protected def getExporterConfig(config: Config): Config =
    if (config.hasPath("exporter")) {
      config.getConfig("exporter")
    } else ConfigFactory.empty

  protected def createSpanExporter(config: Config): SpanExporter
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy