Skip to content

Commit

Permalink
[VAULT-3057] Transaction Metrics Logging (#458)
Browse files Browse the repository at this point in the history
* added MetricsModule, NoopMetrics and DefaultMetrics implementation

* fix : Unable to find resource: vgs/metrics.star and additionally there was no module for vgs/metrics/__init__.star found)

* removed useStarlarkThread : true; because the StarlarkThread will be passed implicitly, and you don't need to pass it explicitly

* moved the MetricsModule class inside the vgs.metrics folder

* used Dict<String, Object> dict instead of Dict<String, String> dict

* Modules alphabetized

* Transaction metrics keys shifted to starlarky instead of atlas-commons

* removed the MetricsModule.ENABLE_DEFAULT_PROPERTY

* fix : java.lang.IllegalArgumentException: MetricsModule expecting only 1 metrics provider of type LarkyMetrics

* [VAULT-3077] Change the arguments of track from dictionary to list of parameters

* fix : added tests for metrics track method

* extra keys will be mapped to a **kwargs

* removed unused imports

* added few test and keys and starlark Int logic to Int

* removed allowed values in metrics.track parameters

* changed attributes to dict<string,string instead of dict<string,object>>

* when psp not given its default value will be NOT_SET
  • Loading branch information
shreyoshi-mahato authored Mar 14, 2024
1 parent 024d2e0 commit d502907
Show file tree
Hide file tree
Showing 11 changed files with 582 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import com.verygood.security.larky.modules.BinasciiModule;
import com.verygood.security.larky.modules.C99MathModule;
import com.verygood.security.larky.modules.vgs.metrics.MetricsModule;
import com.verygood.security.larky.modules.NetworkTokenModule;
import com.verygood.security.larky.modules.CerebroModule;
import com.verygood.security.larky.modules.ChaseModule;
Expand Down Expand Up @@ -96,16 +97,17 @@ public class ModuleSupplier {
);

public static final ImmutableSet<StarlarkValue> VGS_MODULES = ImmutableSet.of(
VaultModule.INSTANCE,
NetworkTokenModule.INSTANCE,
CerebroModule.INSTANCE,
ChaseModule.INSTANCE,
JKSModule.INSTANCE
JKSModule.INSTANCE,
MetricsModule.INSTANCE,
NetworkTokenModule.INSTANCE,
VaultModule.INSTANCE
);

public static final ImmutableSet<StarlarkValue> TEST_MODULES = ImmutableSet.of(
UnittestModule.INSTANCE,
AssertionsModule.INSTANCE
AssertionsModule.INSTANCE,
UnittestModule.INSTANCE
);

private final Map<String, Object> environment;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.verygood.security.larky.modules.vgs.metrics;

import com.google.common.collect.ImmutableList;
import com.verygood.security.larky.modules.vgs.metrics.impl.NoopMetrics;
import com.verygood.security.larky.modules.vgs.metrics.spi.LarkyMetrics;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.ParamType;
import net.starlark.java.annot.StarlarkBuiltin;
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.NoneType;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.ServiceLoader;

import static com.verygood.security.larky.modules.vgs.metrics.constants.TransactionMetricsKeys.*;

@Getter
@Slf4j
@StarlarkBuiltin(
name = "native_metrics",
category = "BUILTIN",
doc = "Overridable Metrics API in Larky")
public class MetricsModule implements LarkyMetrics {

public static final MetricsModule INSTANCE = new MetricsModule();
private final LarkyMetrics metrics;

public MetricsModule() {
ServiceLoader<LarkyMetrics> loader = ServiceLoader.load(LarkyMetrics.class);
List<LarkyMetrics> metricsProviders = ImmutableList.copyOf(loader.iterator());

if (metricsProviders.isEmpty()) {
log.error("Using NoopMetrics, should not be used in Production");
metrics = new NoopMetrics();
} else if (metricsProviders.size() == 1) {
metrics = metricsProviders.get(0);
} else {
throw new IllegalArgumentException(
String.format(
"MetricsModule expecting only 1 metrics provider of type LarkyMetrics, found %d",
metricsProviders.size()));

}
}

@StarlarkMethod(
name = "track",
doc = "Logs the amount, bin, currency, psp, result and type",
parameters = {
@Param(
name = KEY_AMOUNT,
named = true,
positional = false,
doc = "Amount"
),
@Param(
name = KEY_BIN,
named = true,
positional = false,
doc = "Bank Identification Number"
),
@Param(
name = KEY_CURRENCY,
named = true,
positional = false,
doc = "Currency"
),
@Param(
name = KEY_PSP,
named = true,
positional = false,
doc = "Payment Service Provider"
),
@Param(
name = KEY_RESULT,
named = true,
positional = false,
doc = "Transaction Result"
),
@Param(
name = KEY_TYPE,
named = true,
positional = false,
doc = "Transaction Type"
),
@Param(
name = KEY_ATTRIBUTES,
named = true,
positional = false,
doc = "kwargs",
defaultValue = "{}",
allowedTypes = {
@ParamType(type = Dict.class)
}
),
}
)
public void track(
Object amount,
Object bin,
Object currency,
Object psp,
Object result,
Object type,
Dict<String, String> attributes
) throws EvalException {
metrics.track(
getNullIfNoneOrBlank(amount),
getNullIfNoneOrBlank(bin),
getNullIfNoneOrBlank(currency),
getNullIfNoneOrBlank(psp),
getNullIfNoneOrBlank(result),
getNullIfNoneOrBlank(type),
attributes
);
}

private static Object getNullIfNoneOrBlank(Object value) {
if (value instanceof NoneType
|| (value instanceof String valStr && StringUtils.isBlank(valStr))) {
return null;
}
return value.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.verygood.security.larky.modules.vgs.metrics.constants;

public interface TransactionMetricsKeys {
String KEY_AMOUNT = "amount";
String KEY_BIN = "bin";
String KEY_CURRENCY = "currency";
String KEY_PSP = "psp";
String KEY_RESULT = "result";
String KEY_TYPE = "type";
String KEY_ATTRIBUTES = "attributes";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.verygood.security.larky.modules.vgs.metrics.impl;

import com.verygood.security.larky.modules.vgs.metrics.spi.LarkyMetrics;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;

public class DefaultMetrics implements LarkyMetrics {

public static final String OUTPUT_STRING = """
amount %s
bin %s
currency %s
psp %s
result %s
type %s
dict %s
_________________
""";

/**
* Not used in production
*/
@Override
public void track(
Object amount,
Object bin,
Object currency,
Object psp,
Object result,
Object type,
Dict<String, String> attributes
) throws EvalException {
System.out.printf(
OUTPUT_STRING,
amount,
bin,
currency,
psp,
result,
type,
attributes.toString()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.verygood.security.larky.modules.vgs.metrics.impl;

import com.verygood.security.larky.modules.vgs.metrics.spi.LarkyMetrics;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Starlark;

public class NoopMetrics implements LarkyMetrics {

/**
* Not used in production
*/
@Override
public void track(
Object amount,
Object bin,
Object currency,
Object psp,
Object result,
Object type,
Dict<String, String> attributes
) throws EvalException {
throw Starlark.errorf("metrics.track operation must be overridden");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.verygood.security.larky.modules.vgs.metrics.spi;

import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.StarlarkValue;


public interface LarkyMetrics extends StarlarkValue {

void track(
Object amount,
Object bin,
Object currency,
Object psp,
Object result,
Object type,
Dict<String, String> attributes
) throws EvalException;

}
25 changes: 25 additions & 0 deletions larky/src/main/resources/vgs/metrics.star
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
load("@stdlib//larky", larky="larky")
load("@vgs//native_metrics", _metrics="native_metrics")

def track(
amount=None,
bin=None,
currency=None,
psp="NOT_SET",
result=None,
type=None,
**kwargs):
_metrics.track(
amount=amount,
bin=bin,
currency=currency,
psp=psp,
result=result,
type=type,
attributes=kwargs
)


metrics = larky.struct(
track=track
)
Loading

0 comments on commit d502907

Please sign in to comment.