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

com.netflix.atlas.webapi.RequestId.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2015 Netflix, Inc.
 *
 * 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.netflix.atlas.webapi

import java.lang.management.ManagementFactory
import java.util.concurrent.atomic.AtomicLong

import com.netflix.atlas.config.ConfigManager

/**
 * Identifier for a request to another instance. The identifier consists of a unique string for
 * a given process followed by the attempt. The attempt counter is used to track retry behavior
 * for the same logical request. If a sub-request is issued as part of a request the parent id
 * can be prepended to the local id separated with a ':'.
 *
 * ```
 * id = "[${parent}:]${unique_string}.${attempt}" // pattern
 * id = "i-12345678_5783.2:i-12345678_5783.0"     // concrete example
 * ```
 */
object RequestId {

  private val config = ConfigManager.current

  private val instanceId = {
    val prop = "atlas.environment.instanceId"
    if (config.hasPath(prop)) config.getString(prop) else "localhost"
  }

  private val prefix = s"${instanceId}_$getpid"

  private val count = new AtomicLong(0L)

  // Derived from:
  // http://stackoverflow.com/questions/35842/how-can-a-java-program-get-its-own-process-id
  private def getpid: String = {
    val jvmName = ManagementFactory.getRuntimeMXBean.getName
    val index = jvmName.indexOf("@")
    if (index < 1) "unknown" else jvmName.substring(0, index)
  }

  def next: RequestId = RequestId(None, s"${prefix}_${count.getAndIncrement()}", 0)

  def next(parent: RequestId): RequestId = {
    RequestId(Some(parent), s"${prefix}_${count.getAndIncrement()}", 0)
  }

  def apply(id: String): RequestId = {
    val baseId: Option[RequestId] = None
    val path = id.split(":").foldLeft(baseId) { (acc, v) =>
      val index = v.indexOf(".")
      if (index < 0)
        Some(RequestId(acc, v, -1))
      else
        Some(RequestId(acc, v.substring(0, index), v.substring(index + 1).toInt))
    }
    path.get
  }
}

case class RequestId(parent: Option[RequestId], name: String, attempt: Int) {
  def retryId: RequestId = RequestId(parent, name, attempt + 1)

  override def toString: String = {
    val str = s"$name.$attempt"
    parent.fold(str)(p => s"$p:$str")
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy