-
Notifications
You must be signed in to change notification settings - Fork 863
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into fix/model_load
- Loading branch information
Showing
13 changed files
with
399 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
...end/server/src/main/java/org/pytorch/serve/metrics/configuration/MetricConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package org.pytorch.serve.metrics.configuration; | ||
|
||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.FileNotFoundException; | ||
import java.util.List; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.yaml.snakeyaml.Yaml; | ||
import org.yaml.snakeyaml.composer.ComposerException; | ||
import org.yaml.snakeyaml.constructor.Constructor; | ||
|
||
public class MetricConfiguration { | ||
private static final Logger logger = LoggerFactory.getLogger(MetricConfiguration.class); | ||
private List<String> dimensions; | ||
|
||
@SuppressWarnings("checkstyle:MemberName") | ||
private MetricTypes ts_metrics; | ||
|
||
@SuppressWarnings("checkstyle:MemberName") | ||
private MetricTypes model_metrics; | ||
|
||
public void setDimensions(List<String> dimensions) { | ||
this.dimensions = dimensions; | ||
} | ||
|
||
public List<String> getDimensions() { | ||
return this.dimensions; | ||
} | ||
|
||
@SuppressWarnings("checkstyle:MethodName") | ||
public void setTs_metrics(MetricTypes tsMetrics) { | ||
this.ts_metrics = tsMetrics; | ||
} | ||
|
||
@SuppressWarnings("checkstyle:MethodName") | ||
public MetricTypes getTs_metrics() { | ||
return this.ts_metrics; | ||
} | ||
|
||
@SuppressWarnings("checkstyle:MethodName") | ||
public void setModel_metrics(MetricTypes modelMetrics) { | ||
// The Hostname dimension is included by default for model metrics | ||
modelMetrics.setCounter(this.addHostnameDimensionToMetrics(modelMetrics.getCounter())); | ||
modelMetrics.setGauge(this.addHostnameDimensionToMetrics(modelMetrics.getGauge())); | ||
modelMetrics.setHistogram(this.addHostnameDimensionToMetrics(modelMetrics.getHistogram())); | ||
this.model_metrics = modelMetrics; | ||
} | ||
|
||
@SuppressWarnings("checkstyle:MethodName") | ||
public MetricTypes getModel_metrics() { | ||
return this.model_metrics; | ||
} | ||
|
||
public void validate() { | ||
if (this.ts_metrics != null) { | ||
ts_metrics.validate(); | ||
} | ||
|
||
if (this.model_metrics != null) { | ||
model_metrics.validate(); | ||
} | ||
} | ||
|
||
public static MetricConfiguration loadConfiguration(String configFilePath) | ||
throws FileNotFoundException, ComposerException, RuntimeException { | ||
Constructor constructor = new Constructor(MetricConfiguration.class); | ||
Yaml yaml = new Yaml(constructor); | ||
FileInputStream inputStream = new FileInputStream(new File(configFilePath)); | ||
MetricConfiguration config = yaml.load(inputStream); | ||
config.validate(); | ||
logger.info("Successfully loaded metrics configuration from {}", configFilePath); | ||
|
||
return config; | ||
} | ||
|
||
private List<MetricSpecification> addHostnameDimensionToMetrics( | ||
List<MetricSpecification> metricsSpec) { | ||
if (metricsSpec == null) { | ||
return metricsSpec; | ||
} | ||
|
||
for (MetricSpecification spec : metricsSpec) { | ||
List<String> dimensions = spec.getDimensions(); | ||
dimensions.add("Hostname"); | ||
spec.setDimensions(dimensions); | ||
} | ||
|
||
return metricsSpec; | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
...end/server/src/main/java/org/pytorch/serve/metrics/configuration/MetricSpecification.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.pytorch.serve.metrics.configuration; | ||
|
||
import java.util.List; | ||
|
||
public class MetricSpecification { | ||
private String name; | ||
private String unit; | ||
private List<String> dimensions; | ||
|
||
public void setName(String name) { | ||
this.name = name; | ||
} | ||
|
||
public String getName() { | ||
return this.name; | ||
} | ||
|
||
public void setUnit(String unit) { | ||
this.unit = unit; | ||
} | ||
|
||
public String getUnit() { | ||
return this.unit; | ||
} | ||
|
||
public void setDimensions(List<String> dimensions) { | ||
this.dimensions = dimensions; | ||
} | ||
|
||
public List<String> getDimensions() { | ||
return this.dimensions; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "name: " + this.name + ", unit: " + this.unit + ", dimensions: " + this.dimensions; | ||
} | ||
|
||
public void validate() { | ||
if (this.name == null || this.name.isEmpty()) { | ||
throw new RuntimeException("Metric name cannot be empty. " + this); | ||
} | ||
|
||
if (this.unit == null || this.unit.isEmpty()) { | ||
throw new RuntimeException("Metric unit cannot be empty. " + this); | ||
} | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
frontend/server/src/main/java/org/pytorch/serve/metrics/configuration/MetricTypes.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package org.pytorch.serve.metrics.configuration; | ||
|
||
import java.util.List; | ||
|
||
public class MetricTypes { | ||
private List<MetricSpecification> counter; | ||
private List<MetricSpecification> gauge; | ||
private List<MetricSpecification> histogram; | ||
|
||
public void setCounter(List<MetricSpecification> counter) { | ||
this.counter = counter; | ||
} | ||
|
||
public List<MetricSpecification> getCounter() { | ||
return this.counter; | ||
} | ||
|
||
public void setGauge(List<MetricSpecification> gauge) { | ||
this.gauge = gauge; | ||
} | ||
|
||
public List<MetricSpecification> getGauge() { | ||
return this.gauge; | ||
} | ||
|
||
public void setHistogram(List<MetricSpecification> histogram) { | ||
this.histogram = histogram; | ||
} | ||
|
||
public List<MetricSpecification> getHistogram() { | ||
return this.histogram; | ||
} | ||
|
||
public void validate() { | ||
if (this.counter != null) { | ||
for (MetricSpecification spec : this.counter) { | ||
spec.validate(); | ||
} | ||
} | ||
|
||
if (this.gauge != null) { | ||
for (MetricSpecification spec : this.gauge) { | ||
spec.validate(); | ||
} | ||
} | ||
|
||
if (this.histogram != null) { | ||
for (MetricSpecification spec : this.histogram) { | ||
spec.validate(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
136 changes: 136 additions & 0 deletions
136
frontend/server/src/test/java/org/pytorch/serve/metrics/MetricConfigurationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package org.pytorch.serve.metrics.configuration; | ||
|
||
import java.io.FileNotFoundException; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import org.pytorch.serve.util.ConfigManager; | ||
import org.testng.Assert; | ||
import org.testng.annotations.Test; | ||
import org.yaml.snakeyaml.composer.ComposerException; | ||
|
||
public class MetricConfigurationTest { | ||
@Test | ||
public void testLoadValidConfiguration() | ||
throws FileNotFoundException, ComposerException, RuntimeException { | ||
MetricConfiguration config = | ||
MetricConfiguration.loadConfiguration( | ||
"src/test/resources/metrics/valid_configuration.yaml"); | ||
|
||
Assert.assertEquals( | ||
config.getDimensions(), | ||
new ArrayList<String>( | ||
Arrays.asList("ModelName", "ModelVersion", "Level", "Hostname"))); | ||
|
||
Assert.assertEquals(config.getTs_metrics().getCounter().size(), 2); | ||
|
||
MetricSpecification spec = config.getTs_metrics().getCounter().get(0); | ||
Assert.assertEquals(spec.getName(), "Requests2XX"); | ||
Assert.assertEquals(spec.getUnit(), "Count"); | ||
Assert.assertEquals( | ||
spec.getDimensions(), new ArrayList<String>(Arrays.asList("Level", "Hostname"))); | ||
|
||
spec = config.getTs_metrics().getCounter().get(1); | ||
Assert.assertEquals(spec.getName(), "InferenceRequestsTotal"); | ||
Assert.assertEquals(spec.getUnit(), "Count"); | ||
Assert.assertEquals( | ||
spec.getDimensions(), | ||
new ArrayList<String>(Arrays.asList("ModelName", "ModelVersion", "Hostname"))); | ||
|
||
Assert.assertEquals(config.getTs_metrics().getGauge().size(), 2); | ||
|
||
spec = config.getTs_metrics().getGauge().get(0); | ||
Assert.assertEquals(spec.getName(), "QueueTime"); | ||
Assert.assertEquals(spec.getUnit(), "Milliseconds"); | ||
Assert.assertEquals( | ||
spec.getDimensions(), new ArrayList<String>(Arrays.asList("Level", "Hostname"))); | ||
|
||
spec = config.getTs_metrics().getGauge().get(1); | ||
Assert.assertEquals(spec.getName(), "WorkerThreadTime"); | ||
Assert.assertEquals(spec.getUnit(), "Milliseconds"); | ||
Assert.assertEquals( | ||
spec.getDimensions(), new ArrayList<String>(Arrays.asList("Level", "Hostname"))); | ||
|
||
Assert.assertEquals(config.getTs_metrics().getHistogram(), null); | ||
|
||
Assert.assertEquals(config.getModel_metrics().getCounter(), null); | ||
|
||
Assert.assertEquals(config.getModel_metrics().getGauge().size(), 2); | ||
|
||
spec = config.getModel_metrics().getGauge().get(0); | ||
Assert.assertEquals(spec.getName(), "HandlerTime"); | ||
Assert.assertEquals(spec.getUnit(), "ms"); | ||
Assert.assertEquals( | ||
spec.getDimensions(), | ||
new ArrayList<String>(Arrays.asList("ModelName", "Level", "Hostname"))); | ||
|
||
spec = config.getModel_metrics().getGauge().get(1); | ||
Assert.assertEquals(spec.getName(), "PredictionTime"); | ||
Assert.assertEquals(spec.getUnit(), "ms"); | ||
Assert.assertEquals( | ||
spec.getDimensions(), | ||
new ArrayList<String>(Arrays.asList("ModelName", "Level", "Hostname"))); | ||
|
||
Assert.assertEquals(config.getModel_metrics().getHistogram(), null); | ||
} | ||
|
||
@Test | ||
public void testLoadValidConfigurationEmptyMetricDimensions() | ||
throws FileNotFoundException, ComposerException, RuntimeException { | ||
MetricConfiguration config = | ||
MetricConfiguration.loadConfiguration( | ||
"src/test/resources/metrics/valid_configuration_empty_metric_dimensions.yaml"); | ||
|
||
Assert.assertEquals(config.getDimensions(), null); | ||
|
||
Assert.assertEquals(config.getTs_metrics().getCounter().size(), 1); | ||
|
||
MetricSpecification spec = config.getTs_metrics().getCounter().get(0); | ||
Assert.assertEquals(spec.getName(), "InferenceRequestsTotal"); | ||
Assert.assertEquals(spec.getUnit(), "Count"); | ||
Assert.assertEquals(spec.getDimensions(), null); | ||
|
||
Assert.assertEquals(config.getTs_metrics().getGauge(), null); | ||
|
||
Assert.assertEquals(config.getTs_metrics().getHistogram(), null); | ||
|
||
Assert.assertEquals(config.getModel_metrics(), null); | ||
} | ||
|
||
@Test | ||
public void testLoadInvalidConfigurationMissingDimension() { | ||
Assert.assertThrows( | ||
ComposerException.class, | ||
() -> | ||
MetricConfiguration.loadConfiguration( | ||
"src/test/resources/metrics/invalid_configuration_missing_dimension.yaml")); | ||
} | ||
|
||
@Test | ||
public void testLoadInvalidConfigurationMissingMetricName() { | ||
Assert.assertThrows( | ||
RuntimeException.class, | ||
() -> | ||
MetricConfiguration.loadConfiguration( | ||
"src/test/resources/metrics/invalid_configuration_missing_metric_name.yaml")); | ||
} | ||
|
||
@Test | ||
public void testLoadInvalidConfigurationMissingMetricUnit() { | ||
Assert.assertThrows( | ||
RuntimeException.class, | ||
() -> | ||
MetricConfiguration.loadConfiguration( | ||
"src/test/resources/metrics/invalid_configuration_missing_metric_unit.yaml")); | ||
} | ||
|
||
@Test | ||
public void testMetricsModeConfiguration() { | ||
ConfigManager configManager = ConfigManager.getInstance(); | ||
String existingMetricsModeConfiguration = configManager.getMetricsMode(); | ||
Assert.assertEquals(existingMetricsModeConfiguration, "log"); | ||
configManager.setProperty("metrics_mode", "test_metrics_mode"); | ||
Assert.assertEquals(configManager.getMetricsMode(), "test_metrics_mode"); | ||
// Restore original metrics mode configuration | ||
configManager.setProperty("metrics_mode", existingMetricsModeConfiguration); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
frontend/server/src/test/resources/metrics/invalid_configuration_missing_dimension.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
dimensions: | ||
- &model_name "ModelName" | ||
- &model_version "ModelVersion" | ||
|
||
ts_metrics: | ||
counter: | ||
- name: InferenceRequestsTotal | ||
unit: Count | ||
dimensions: [*model_name, *model_version, *hostname] |
9 changes: 9 additions & 0 deletions
9
frontend/server/src/test/resources/metrics/invalid_configuration_missing_metric_name.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
dimensions: | ||
- &model_name "ModelName" | ||
- &model_version "ModelVersion" | ||
- &hostname "Hostname" | ||
|
||
ts_metrics: | ||
counter: | ||
- unit: Count | ||
dimensions: [*model_name, *model_version, *hostname] |
Oops, something went wrong.