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

co.elastic.otel.ProfilerSharedMemoryWriter Maven / Gradle / Ivy

/*
 * Licensed to Elasticsearch B.V. under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.otel;

import co.elastic.otel.common.LocalRootSpan;
import co.elastic.otel.common.util.HexUtils;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.ReadableSpan;
import io.opentelemetry.semconv.ResourceAttributes;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ProfilerSharedMemoryWriter {

  private static final Logger log = Logger.getLogger(ProfilerSharedMemoryWriter.class.getName());

  private static final int TLS_MINOR_VERSION_OFFSET = 0;
  private static final int TLS_VALID_OFFSET = 2;
  private static final int TLS_TRACE_PRESENT_OFFSET = 3;
  private static final int TLS_TRACE_FLAGS_OFFSET = 4;
  private static final int TLS_TRACE_ID_OFFSET = 5;
  private static final int TLS_SPAN_ID_OFFSET = 21;
  private static final int TLS_LOCAL_ROOT_SPAN_ID_OFFSET = 29;
  static final int TLS_STORAGE_SIZE = 37;

  private static volatile int writeForMemoryBarrier = 0;

  static ByteBuffer generateProcessCorrelationStorage(
      Resource serviceResource, String socketFilePath) {
    String serviceName = serviceResource.getAttribute(ResourceAttributes.SERVICE_NAME);
    if (serviceName == null) {
      throw new IllegalStateException("A service name must be configured!");
    }
    String environment = serviceResource.getAttribute(ResourceAttributes.SERVICE_NAMESPACE);

    ByteBuffer buffer = ByteBuffer.allocateDirect(4096);
    buffer.order(ByteOrder.nativeOrder());
    buffer.position(0);

    buffer.putChar((char) 1); // layout-minor-version
    writeUtf8Str(buffer, serviceName);
    writeUtf8Str(buffer, environment == null ? "" : environment);
    writeUtf8Str(buffer, socketFilePath); // socket-file-path
    return buffer;
  }

  private static void writeUtf8Str(ByteBuffer buffer, String str) {
    byte[] utf8 = str.getBytes(StandardCharsets.UTF_8);
    buffer.putInt(utf8.length);
    buffer.put(utf8);
  }

  /**
   * This method ensures that all writes which happened prior to this method call are not moved
   * after the method call due to reordering.
   *
   * 

This is realized based on the Java Memory Model guarantess for volatile variables. Relevant * resources: * *

*/ private static void memoryStoreStoreBarrier() { writeForMemoryBarrier = 42; } static void updateThreadCorrelationStorage(Span newSpan) { ByteBuffer tls = UniversalProfilingCorrelation.getCurrentThreadStorage(true, TLS_STORAGE_SIZE); // tls might be null if unsupported or something went wrong on initialization if (tls != null) { // the valid flag is used to signal the host-agent that it is reading incomplete data tls.put(TLS_VALID_OFFSET, (byte) 0); memoryStoreStoreBarrier(); tls.putChar(TLS_MINOR_VERSION_OFFSET, (char) 1); SpanContext spanCtx = newSpan.getSpanContext(); if (spanCtx.isValid() && !spanCtx.isRemote()) { ReadableSpan localRoot = LocalRootSpan.getFor(newSpan); if (localRoot != null) { String localRootSpanId = localRoot.getSpanContext().getSpanId(); tls.put(TLS_TRACE_PRESENT_OFFSET, (byte) 1); tls.put(TLS_TRACE_FLAGS_OFFSET, spanCtx.getTraceFlags().asByte()); HexUtils.writeHexAsBinary(spanCtx.getTraceId(), 0, tls, TLS_TRACE_ID_OFFSET, 16); HexUtils.writeHexAsBinary(spanCtx.getSpanId(), 0, tls, TLS_SPAN_ID_OFFSET, 8); HexUtils.writeHexAsBinary(localRootSpanId, 0, tls, TLS_LOCAL_ROOT_SPAN_ID_OFFSET, 8); } else { tls.put(TLS_TRACE_PRESENT_OFFSET, (byte) 0); log.log(Level.WARNING, "Cannot propagate trace with unknown local root: {0}", newSpan); } } else { tls.put(TLS_TRACE_PRESENT_OFFSET, (byte) 0); } memoryStoreStoreBarrier(); tls.put(TLS_VALID_OFFSET, (byte) 1); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy