Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class CapturedContext implements ValueReferenceResolver {
public static final CapturedContext EMPTY_CONTEXT = new CapturedContext(null);
public static final CapturedContext EMPTY_CAPTURING_CONTEXT =
new CapturedContext(ProbeImplementation.UNKNOWN);
private final transient Map<String, Object> extensions = new HashMap<>();
private final transient Map<String, CapturedValue> extensions = new HashMap<>();

private Map<String, CapturedValue> arguments;
private Map<String, CapturedValue> locals;
Expand All @@ -49,7 +49,7 @@ public CapturedContext(
this.throwable = throwable;
}

private CapturedContext(CapturedContext other, Map<String, Object> extensions) {
private CapturedContext(CapturedContext other, Map<String, CapturedValue> extensions) {
this.arguments = other.arguments;
this.locals = other.getLocals();
this.throwable = other.throwable;
Expand Down Expand Up @@ -85,11 +85,11 @@ public boolean isCapturing() {
}

@Override
public Object lookup(String name) {
public CapturedValue lookup(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("empty name for lookup operation");
}
Object target;
CapturedValue target;
if (name.startsWith(ValueReferences.SYNTHETIC_PREFIX)) {
String rawName = name.substring(ValueReferences.SYNTHETIC_PREFIX.length());
target = tryRetrieveSynthetic(rawName);
Expand All @@ -98,36 +98,39 @@ public Object lookup(String name) {
target = tryRetrieve(name);
checkUndefined(target, name, "Cannot find symbol: ");
}
return target instanceof CapturedValue ? ((CapturedValue) target).getValue() : target;
return target;
}

private void checkUndefined(Object target, String name, String msg) {
if (target == Values.UNDEFINED_OBJECT) {
private void checkUndefined(CapturedValue target, String name, String msg) {
if (target == CapturedValue.UNDEFINED || target.notCapturedReason != null) {
String errorMsg = msg + name;
throw new RuntimeException(errorMsg);
}
}

@Override
public Object getMember(Object target, String memberName) {
public CapturedValue getMember(Object target, String memberName) {
if (target == Values.UNDEFINED_OBJECT) {
return target;
return CapturedValue.UNDEFINED;
}
if (Redaction.isRedactedKeyword(memberName)) {
return REDACTED_VALUE;
return CapturedValue.redacted(memberName, null);
}
CapturedValue result;
if (target instanceof CapturedValue) {
Map<String, CapturedValue> fields = ((CapturedValue) target).fields;
if (fields.containsKey(memberName)) {
target = fields.get(memberName);
result = fields.get(memberName);
} else {
CapturedValue capturedTarget = ((CapturedValue) target);
target = capturedTarget.getValue();
if (target != null) {
Object targetedValue = capturedTarget.getValue();
if (targetedValue != null) {
// resolve to a CapturedValue instance
target = ReflectiveFieldValueResolver.resolve(target, target.getClass(), memberName);
result =
ReflectiveFieldValueResolver.getFieldAsCapturedValue(
targetedValue.getClass(), targetedValue, memberName);
} else {
target = Values.UNDEFINED_OBJECT;
result = CapturedValue.UNDEFINED;
}
}
} else {
Expand All @@ -138,25 +141,27 @@ public Object getMember(Object target, String memberName) {
if (specialFieldAccess != null) {
CapturedValue specialField = specialFieldAccess.apply(target);
if (specialField != null && specialField.getName().equals(memberName)) {
return specialField.getValue();
return specialField;
}
}
}
target = ReflectiveFieldValueResolver.resolve(target, target.getClass(), memberName);
result =
ReflectiveFieldValueResolver.getFieldAsCapturedValue(
target.getClass(), target, memberName);
}
checkUndefined(target, memberName, "Cannot dereference field: ");
return target;
checkUndefined(result, memberName, "Cannot dereference field: ");
return result;
}

private Object tryRetrieveSynthetic(String name) {
private CapturedValue tryRetrieveSynthetic(String name) {
if (extensions == null || extensions.isEmpty()) {
return Values.UNDEFINED_OBJECT;
return CapturedValue.UNDEFINED;
}
return extensions.getOrDefault(name, Values.UNDEFINED_OBJECT);
return extensions.getOrDefault(name, CapturedValue.UNDEFINED);
}

private Object tryRetrieve(String name) {
Object result = null;
private CapturedValue tryRetrieve(String name) {
CapturedValue result = null;
if (arguments != null && !arguments.isEmpty()) {
result = arguments.get(name);
}
Expand All @@ -174,12 +179,12 @@ private Object tryRetrieve(String name) {
}
CapturedValue thisValue;
if (arguments != null && (thisValue = arguments.get("this")) != null) {
result = getMember(thisValue.getValue(), name);
if (result != Values.UNDEFINED_OBJECT) {
result = getMember(thisValue, name);
if (result != CapturedValue.UNDEFINED) {
return result;
}
}
return result != null ? result : Values.UNDEFINED_OBJECT;
return result != null ? result : CapturedValue.UNDEFINED;
}

public CapturedContext copyWithoutCaptureExpressions() {
Expand All @@ -191,12 +196,12 @@ public CapturedContext copyWithoutCaptureExpressions() {
}

@Override
public ValueReferenceResolver withExtensions(Map<String, Object> extensions) {
public ValueReferenceResolver withExtensions(Map<String, CapturedValue> extensions) {
return new CapturedContext(this, extensions);
}

@Override
public void addExtension(String name, Object value) {
public void addExtension(String name, CapturedValue value) {
extensions.put(name, value);
}

Expand Down Expand Up @@ -235,8 +240,9 @@ public void addReturn(CapturedValue retValue) {
public void addThrowable(Throwable t) {
addThrowable(new CapturedThrowable(t));
// special local name for throwable
putInLocals(ValueReferences.EXCEPTION_REF, CapturedValue.of(t.getClass().getTypeName(), t));
extensions.put(ValueReferences.EXCEPTION_EXTENSION_NAME, t);
CapturedValue capturedException = CapturedValue.of(t.getClass().getTypeName(), t);
putInLocals(ValueReferences.EXCEPTION_REF, capturedException);
extensions.put(ValueReferences.EXCEPTION_EXTENSION_NAME, capturedException);
}

public void addThrowable(CapturedThrowable capturedThrowable) {
Expand Down Expand Up @@ -319,7 +325,8 @@ public Status evaluate(
if (methodLocation == MethodLocation.EXIT && startTimestamp > 0) {
duration = System.nanoTime() - startTimestamp;
addExtension(
ValueReferences.DURATION_EXTENSION_NAME, duration / 1_000_000.0); // convert to ms
ValueReferences.DURATION_EXTENSION_NAME,
CapturedValue.of(duration / 1_000_000.0)); // convert to ms
}
this.thisClassName = thisClassName;
boolean shouldEvaluate =
Expand Down Expand Up @@ -446,7 +453,7 @@ public boolean isCapturing() {

/** Stores a captured value */
public static class CapturedValue {
public static final CapturedValue UNDEFINED = CapturedValue.of(null, Values.UNDEFINED_OBJECT);
public static final CapturedValue UNDEFINED = CapturedValue.of(Values.UNDEFINED_OBJECT);

private String name;
private final String declaredType;
Expand Down Expand Up @@ -517,6 +524,10 @@ public void setName(String name) {
this.name = name;
}

public static CapturedValue of(Object value) {
return of(null, value);
}

public static CapturedValue of(String declaredType, Object value) {
return build(null, declaredType, value, Limits.DEFAULT, null);
}
Expand All @@ -525,10 +536,6 @@ public static CapturedValue of(String name, String declaredType, Object value) {
return build(name, declaredType, value, Limits.DEFAULT, null);
}

public CapturedValue derive(String name, String type, Object value) {
return build(name, type, value, limits, null);
}

public static CapturedValue of(
String name,
String declaredType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package datadog.trace.bootstrap.debugger.el;

import datadog.trace.bootstrap.debugger.CapturedContext.CapturedValue;
import java.util.Map;

/** Debugger EL specific value reference resolver. */
public interface ValueReferenceResolver {
Object lookup(String name);
CapturedValue lookup(String name);

Object getMember(Object target, String name);
CapturedValue getMember(Object target, String name);

default void addExtension(String name, Object value) {}
default void addExtension(String name, CapturedValue value) {}

default void removeExtension(String name) {}

default ValueReferenceResolver withExtensions(Map<String, Object> extensions) {
default ValueReferenceResolver withExtensions(Map<String, CapturedValue> extensions) {
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public BooleanValue evaluate(ValueReferenceResolver valueRefResolver) {
throw new EvaluationException(
"Boolean expression returning null", PrettyPrintVisitor.print(this));
}
return new BooleanValue(result);
return new BooleanValue(result, ValueType.OBJECT);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ public static IndexExpression index(ValueExpression<?> target, ValueExpression<?
}

public static Literal<Boolean> value(boolean value) {
return new BooleanValue(value);
return new BooleanValue(value, ValueType.BOOLEAN);
}

public static Literal<Number> value(Number value) {
return new NumericValue(value);
return new NumericValue(value, ValueType.OBJECT);
}

public static Literal<String> value(String value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
public class Literal<ConstantType>
implements Value<ConstantType>, ValueExpression<Value<ConstantType>> {
protected final ConstantType value;
protected final ValueType type;

protected Literal(ConstantType value) {
protected Literal(ConstantType value, ValueType type) {
this.value = value;
this.type = type;
}

@Override
Expand All @@ -34,6 +36,11 @@ public ConstantType getValue() {
return value;
}

@Override
public ValueType getType() {
return type;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.datadog.debugger.el.values.SetValue;
import com.datadog.debugger.el.values.StringValue;
import com.datadog.debugger.el.values.UndefinedValue;
import datadog.trace.bootstrap.debugger.CapturedContext;
import datadog.trace.bootstrap.debugger.el.Values;
import datadog.trace.bootstrap.debugger.util.WellKnownClasses;
import java.util.List;
Expand Down Expand Up @@ -39,6 +40,10 @@ static <T> Value<T> undefined() {

T getValue();

default ValueType getType() {
return ValueType.OBJECT;
}

default boolean isUndefined() {
return false;
}
Expand All @@ -47,7 +52,7 @@ default boolean isNull() {
return false;
}

static Value<?> of(Object value) {
static Value<?> of(Object value, ValueType type) {
if (value == null || value == Values.NULL_OBJECT || value == nullValue()) {
return nullValue();
}
Expand All @@ -71,11 +76,11 @@ static Value<?> of(Object value) {
value = longPrimitiveValueFunction.applyAsLong(value);
}
if (value instanceof Boolean) {
return new BooleanValue((Boolean) value);
return new BooleanValue((Boolean) value, type);
} else if (value instanceof Character) {
return new StringValue(value.toString());
} else if (value instanceof Number) {
return new NumericValue((Number) value);
return new NumericValue((Number) value, type);
} else if (value instanceof String) {
return new StringValue((String) value);
} else if (value instanceof List) {
Expand All @@ -92,4 +97,26 @@ static Value<?> of(Object value) {
return new ObjectValue(value);
}
}

static CapturedContext.CapturedValue toCapturedSnapshot(String name, Value<?> value) {
return CapturedContext.CapturedValue.of(
name, ValueType.toString(value.getType()), value.getValue());
}

static CapturedContext.CapturedValue toCapturedSnapshot(
String name,
Value<?> value,
int maxReferenceDepth,
int maxCollectionSize,
int maxCount,
int maxFieldCount) {
return CapturedContext.CapturedValue.of(
name,
ValueType.toString(value.getType()),
value.getValue(),
maxReferenceDepth,
maxCollectionSize,
maxCount,
maxFieldCount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.datadog.debugger.el;

public enum ValueType {
OBJECT,
BOOLEAN,
INT,
LONG,
DOUBLE,
BYTE,
SHORT,
CHAR,
FLOAT;

public static String toString(ValueType type) {
switch (type) {
case BOOLEAN:
case INT:
case LONG:
case DOUBLE:
case BYTE:
case SHORT:
case CHAR:
case FLOAT:
return type.name().toLowerCase();
default:
return Object.class.getTypeName();
}
}

public static ValueType of(String type) {
switch (type) {
case "boolean":
return BOOLEAN;
case "int":
return INT;
case "long":
return LONG;
case "double":
return DOUBLE;
case "byte":
return BYTE;
case "short":
return SHORT;
case "char":
return CHAR;
case "float":
return FLOAT;
default:
return OBJECT;
}
}
}
Loading
Loading