dd-trace-java icon indicating copy to clipboard operation
dd-trace-java copied to clipboard

muzzle.mismatch="datadog.trace.instrumentation.springweb.DatadogByteArrayOutputStream:36 Missing class B"

Open lrwh opened this issue 1 year ago • 0 comments

I have created a custom class that inherits from the OutputStream class, and when the application starts and loads, a Missing class B exception occurs. I am not sure what class B is, could you help me take a look?

[dd.trace 2024-10-28 18:15:26:999 +0800] [main] DEBUG datadog.trace.agent.tooling.muzzle.MuzzleCheck - Muzzled mismatch - instrumentation.names=[spring-web] instrumentation.class=datadog.trace.instrumentation.springweb.DispatcherServletInstrumentation instrumentation.target.classloader=jdk.internal.loader.ClassLoaders$AppClassLoader@512ddf17 muzzle.mismatch="datadog.trace.instrumentation.springweb.DatadogByteArrayOutputStream:36 Missing class B"

line 36

if (this.buffers.peekLast() == null || (this.buffers.getLast()).length == this.index) {

Image

code DatadogByteArrayOutputStream

package datadog.trace.instrumentation.springweb;


import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;

public class DatadogByteArrayOutputStream extends OutputStream {
  private static final int DEFAULT_BLOCK_SIZE = 256;
  private final Deque<byte[]> buffers = new ArrayDeque();
  private final int initialBlockSize;
  private int nextBlockSize;
  private int alreadyBufferedSize;
  private int index;
  private boolean closed;

  public DatadogByteArrayOutputStream() {
    this(256);
  }

  public DatadogByteArrayOutputStream(int initialBlockSize) {
    this.nextBlockSize = 0;
    this.alreadyBufferedSize = 0;
    this.index = 0;
    this.closed = false;
    this.initialBlockSize = initialBlockSize;
    this.nextBlockSize = initialBlockSize;
  }

  public void write(int datum) throws IOException {
    if (this.closed) {
      throw new IOException("Stream closed");
    } else {
      if (this.buffers.peekLast() == null || (this.buffers.getLast()).length == this.index) {
        this.addBuffer(1);
      }

      (this.buffers.getLast())[this.index++] = (byte)datum;
    }
  }

  public void write(byte[] data, int offset, int length) throws IOException {
    if (offset >= 0 && offset + length <= data.length && length >= 0) {
      if (this.closed) {
        throw new IOException("Stream closed");
      } else {
        if (this.buffers.peekLast() == null || ((byte[])this.buffers.getLast()).length == this.index) {
          this.addBuffer(length);
        }

        if (this.index + length > ((byte[])this.buffers.getLast()).length) {
          int pos = offset;

          do {
            if (this.index == ((byte[])this.buffers.getLast()).length) {
              this.addBuffer(length);
            }

            int copyLength = ((byte[])this.buffers.getLast()).length - this.index;
            if (length < copyLength) {
              copyLength = length;
            }

            System.arraycopy(data, pos, this.buffers.getLast(), this.index, copyLength);
            pos += copyLength;
            this.index += copyLength;
            length -= copyLength;
          } while(length > 0);
        } else {
          System.arraycopy(data, offset, this.buffers.getLast(), this.index, length);
          this.index += length;
        }

      }
    } else {
      throw new IndexOutOfBoundsException();
    }
  }

  public void close() {
    this.closed = true;
  }

  public String toString() {
    return new String(this.toByteArrayUnsafe());
  }

  public int size() {
    return this.alreadyBufferedSize + this.index;
  }

  public byte[] toByteArrayUnsafe() {
    int totalSize = this.size();
    if (totalSize == 0) {
      return new byte[0];
    } else {
      this.resize(totalSize);
      return (byte[])this.buffers.getFirst();
    }
  }

  public byte[] toByteArray() {
    byte[] bytesUnsafe = this.toByteArrayUnsafe();
    return (byte[])bytesUnsafe.clone();
  }

  public void reset() {
    this.buffers.clear();
    this.nextBlockSize = this.initialBlockSize;
    this.closed = false;
    this.index = 0;
    this.alreadyBufferedSize = 0;
  }

  public void writeTo(OutputStream out) throws IOException {
    Iterator<byte[]> it = this.buffers.iterator();

    while(it.hasNext()) {
      byte[] bytes = (byte[])it.next();
      if (it.hasNext()) {
        out.write(bytes, 0, bytes.length);
      } else {
        out.write(bytes, 0, this.index);
      }
    }

  }

  public void resize(int targetCapacity) {
    if (this.buffers.peekFirst() == null) {
      this.nextBlockSize = targetCapacity - this.size();
    } else if (this.size() != targetCapacity || ((byte[])this.buffers.getFirst()).length != targetCapacity) {
      int totalSize = this.size();
      byte[] data = new byte[targetCapacity];
      int pos = 0;
      Iterator<byte[]> it = this.buffers.iterator();

      while(it.hasNext()) {
        byte[] bytes = (byte[])it.next();
        if (it.hasNext()) {
          System.arraycopy(bytes, 0, data, pos, bytes.length);
          pos += bytes.length;
        } else {
          System.arraycopy(bytes, 0, data, pos, this.index);
        }
      }

      this.buffers.clear();
      this.buffers.add(data);
      this.index = totalSize;
      this.alreadyBufferedSize = 0;
    }

  }

  private void addBuffer(int minCapacity) {
    if (this.buffers.peekLast() != null) {
      this.alreadyBufferedSize += this.index;
      this.index = 0;
    }

    if (this.nextBlockSize < minCapacity) {
      this.nextBlockSize = nextPowerOf2(minCapacity);
    }

    this.buffers.add(new byte[this.nextBlockSize]);
    this.nextBlockSize *= 2;
  }

  private static int nextPowerOf2(int val) {
    --val;
    val |= val >> 1;
    val |= val >> 2;
    val |= val >> 4;
    val |= val >> 8;
    val |= val >> 16;
    ++val;
    return val;
  }
}

DispatcherServletInstrumentation class add helperClassNames

@AutoService(InstrumenterModule.class)
public final class DispatcherServletInstrumentation extends InstrumenterModule.Tracing
    implements Instrumenter.ForSingleType {

  public DispatcherServletInstrumentation() {
    super("spring-web");
  }

  @Override
  public String instrumentedType() {
    return "org.springframework.web.servlet.DispatcherServlet";
  }

  @Override
  public String[] helperClassNames() {
    return new String[] {
      packageName + ".SpringWebHttpServerDecorator",
      packageName + ".ServletRequestURIAdapter",
      packageName + ".HandlerMappingResourceNameFilter",
      packageName + ".PathMatchingHttpServletRequestWrapper",
      packageName + ".DataDogHttpServletResponseWrapper",
      //packageName + ".DataDogHttpServletResponseWrapper$WrapperOutputStream"
      packageName + ".DataDogHttpServletResponseWrapper$CustomServletOutputStream",
      packageName+".ContentCachingResponseWrapper",
        packageName+".ContentCachingResponseWrapper$ResponseServletOutputStream",
      packageName+".ContentCachingResponseWrapper$ResponsePrintWriter",
        packageName+".DatadogByteArrayOutputStream",
    };
  }
...

lrwh avatar Oct 28 '24 10:10 lrwh