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

org.openqa.selenium.grid.log.JaegerTracing Maven / Gradle / Ivy

// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC 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 org.openqa.selenium.grid.log;

import io.opentelemetry.sdk.trace.export.SpanExporter;

import java.lang.reflect.Method;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * We use an awful lof of reflection here because it's the only way we can
 * get this to work without requiring the selenium server take a dependency
 * on Jaeger, which may not be needed in all cases.
 */
class JaegerTracing {

  private static final Logger LOGGER = Logger.getLogger(JaegerTracing.class.getName());

  static Optional findJaegerExporter() {
    String host = System.getProperty("JAEGER_AGENT_HOST");
    if (host == null) {
      return Optional.empty();
    }

    String rawPort = System.getProperty("JAEGER_AGENT_PORT", "14250");
    int port = -1;
    try {
      port = Integer.parseInt(rawPort);
    } catch (NumberFormatException e) {
      LOGGER.log(Level.WARNING, "Error parsing port from JAEGER_AGENT_PORT environment variable", e);
      return Optional.empty();
    }
    if (port == -1) {
      return Optional.empty();
    }

    try {
      Object jaegerChannel = createManagedChannel(host, port);
      SpanExporter toReturn = (SpanExporter) createJaegerGrpcSpanExporter(jaegerChannel);

      if (toReturn == null) {
        return Optional.empty();
      }

      LOGGER.info(String.format("Attaching Jaeger tracing to %s:%s", host, port));
      return Optional.of(toReturn);
    } catch (ReflectiveOperationException e) {
      LOGGER.log(Level.WARNING, "Cannot instantiate Jaeger tracer", e);
      return Optional.empty();
    }
  }

  private static Object createManagedChannel(String host, int port) throws ReflectiveOperationException {
    // Equivalent to:
    // ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();

    ClassLoader cl = Thread.currentThread().getContextClassLoader();

    Class builderClazz = Class.forName("io.grpc.ManagedChannelBuilder", true, cl);
    Method forAddress = builderClazz.getMethod("forAddress", String.class, int.class);
    Object value = forAddress.invoke(null, host, port);

    Method usePlaintext = builderClazz.getMethod("usePlaintext");
    value = usePlaintext.invoke(value);

    Method build = builderClazz.getMethod("build");
    return build.invoke(value);
  }

  private static Object createJaegerGrpcSpanExporter(Object jaegerChannel) throws ReflectiveOperationException {
    // Equivalent to:
    // return JaegerGrpcSpanExporter.newBuilder()
    //   .setServiceName("selenium")
    //   .setChannel(jaegerChannel)
    //   .setDeadlineMs(30000)
    //   .build();

    ClassLoader cl = Thread.currentThread().getContextClassLoader();

    Class exporterClazz = Class.forName("io.opentelemetry.exporters.jaeger.JaegerGrpcSpanExporter", true, cl);
    Method newBuilder = exporterClazz.getMethod("newBuilder");
    Object builderObj = newBuilder.invoke(exporterClazz);

    Class builderClazz = builderObj.getClass();

    Method setServiceName = builderClazz.getMethod("setServiceName", String.class);
    builderObj = setServiceName.invoke(builderObj, System.getProperty("JAEGER_SERVICE_NAME", "selenium"));

    Class managedChannelClazz = Class.forName("io.grpc.ManagedChannel", true, cl);
    Method setChannel = builderClazz.getMethod("setChannel", managedChannelClazz);
    builderObj = setChannel.invoke(builderObj, jaegerChannel);

    Method setDeadline = builderClazz.getMethod("setDeadlineMs", long.class);
    builderObj = setDeadline.invoke(builderObj, 3000);

    Method build = builderClazz.getMethod("build");
    return build.invoke(builderObj);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy