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
31 changes: 31 additions & 0 deletions karyon3-api/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2015 Netflix, Inc.
*
* Licensed 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.
*/

apply plugin: 'java'

repositories {
maven { url 'https://oss.jfrog.org/libs-snapshot' }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why snapshot instead of jcentral?

}

dependencies {
}

eclipse {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about Intellij env?

classpath {
downloadSources = true
downloadJavadoc = true
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.netflix.karyon;
package com.netflix.karyon.api;

/**
* Base interface for all {@link Karyon} features to be implemented by an
* Base interface for all Karyon features to be implemented by an
* enum, such as {@link KaryonFeatures}. Each feature has an implicit
* default value.
*
* @see Karyon
* @author elandau
*/
public interface KaryonFeature {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.netflix.karyon;
package com.netflix.karyon.api;


/**
* Core karyon features. Features are configured/enabled on {@link KaryonConfiguration}
* Core karyon features
*
* @author elandau
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
package com.netflix.karyon;
package com.netflix.karyon.api;

import com.google.inject.ImplementedBy;

/**
* Very simple config interface to be used by Conditions to gain access
* to any type of configuration. The internal default in AutoModuleBuilder
* is to delegate to System properties.
*
* @see PropertiesPropertySource
*
* @author elandau
*
*/
@ImplementedBy(DefaultPropertySource.class)
public interface PropertySource {
/**
* Get the value of a property or null if not found
*
* @param key
* @return
*/
public String get(String key);
String get(String key);

/**
* Get the value of a property or default if not found
Expand All @@ -29,7 +25,7 @@ public interface PropertySource {
* @param defaultValue
* @return
*/
public String get(String key, String defaultValue);
String get(String key, String defaultValue);

/**
* Get a property value of a specific type
Expand All @@ -38,7 +34,7 @@ public interface PropertySource {
* @param type
* @return
*/
public <T> T get(String key, Class<T> type);
<T> T get(String key, Class<T> type);

/**
* Get a property value of a specific type while returning a
Expand All @@ -49,5 +45,5 @@ public interface PropertySource {
* @param defaultValue
* @return
*/
public <T> T get(String key, Class<T> type, T defaultValue);
<T> T get(String key, Class<T> type, T defaultValue);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know the type system in Java is a little funky sometimes, but could this just be.

T get(String key, T defaultValue); and allow you to get rid of the String version above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. The String version is completely unnecessary.

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.netflix.karyon;
package com.netflix.karyon.api;

/**
* Standardized set of properties
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.netflix.karyon.api.health;

import java.util.concurrent.CompletableFuture;

/**
* Contract for the top level application health check. This is the HealthCheck
* to be consulted when exposing a HealthCheck endpoint or for use when registering
* with a service registry service.
*/
public interface HealthCheck {
/**
* Perform a health check.
* @return A future on which the health check result will be emitted
*/
CompletableFuture<HealthCheckStatus> check();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.netflix.karyon.api.health;

import java.util.List;

/**
* Instance of a HealthCheck response and utility methods for creating specific statuses
*/
public interface HealthCheckStatus {
/**
* @return Final health check status
*/
HealthState getState();

/**
* @return List of indicator statuses that were used to determine HealthCheck
*/
List<HealthIndicatorStatus> getIndicators();

public static HealthCheckStatus create(HealthState state, List<HealthIndicatorStatus> indicators) {
return new HealthCheckStatus() {
@Override
public HealthState getState() {
return state;
}

@Override
public List<HealthIndicatorStatus> getIndicators() {
return indicators;
}
};
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.netflix.karyon.health;
package com.netflix.karyon.api.health;

import java.util.concurrent.CompletableFuture;

Expand Down Expand Up @@ -50,4 +50,26 @@ public interface HealthIndicator {
* Return the name of the health indicator. Note that health indicators with duplicate names are allowed.
*/
String getName();

public static HealthIndicator alwaysHealthy(String name) {
return memoize(name, HealthIndicatorStatus.healthy(name));
}

public static HealthIndicator alwaysUnhealthy(String name) {
return memoize(name, HealthIndicatorStatus.unhealthy(name, new Exception("Unhealthy")));
}

public static HealthIndicator memoize(final String name, final HealthIndicatorStatus status) {
return new HealthIndicator() {
@Override
public CompletableFuture<HealthIndicatorStatus> check() {
return CompletableFuture.completedFuture(status);
}

@Override
public String getName() {
return name;
}
};
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,12 @@
package com.netflix.karyon.health;
package com.netflix.karyon.api.health;

import java.util.Arrays;
import java.util.List;

import com.google.inject.ImplementedBy;

/**
* Registry of active HealthIndicator's. The HealthIndicator are used by {@link HealthCheck} to
* determine the application health.
*
* The default registry, {@link AllHealthIndicatorRegistry} uses Guice bindings to determine the
* list of all active indicators. To create a curated list of {@link HealthIndicator}s regardless of
* Guice bindings create a binding to HealthIndicatorRegistry as follows
*
* <code>
* {@literal @}Provides
* {@literal @}Singleton
* HealthIndicatorRegistry getHealthIndicatorRegistry({@literal @}Named("cpu") HealthIndicator cpuIndicator, {@literal @}Named("foo") HealthIndicator fooIndicator) {
* return HealthIndicatorRegistry.from(cpuIndicator, fooIndicator);
* }
* </code>
*
* @author elandau
*/
@ImplementedBy(AllHealthIndicatorRegistry.class)
public interface HealthIndicatorRegistry {
/**
* Return a list of all active health checks
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.netflix.karyon.health;
package com.netflix.karyon.api.health;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
Expand All @@ -7,14 +7,45 @@
import java.util.Map.Entry;

/**
* Utility class for creating common {@link HealthIndicatorStatus} instances
* Immutable health check instance returned from a {@link HealthIndicator}
*
* See {@link HealthIndicatorStatus} for utility methods to create HealthIndicatorStatus objects
* @author elandau
*
*/
public final class HealthIndicatorStatuses {
public interface HealthIndicatorStatus {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is more a meta question than a critique of this move(which I generally find to be a good idea), but should we really even be doing this much stuff? Why isn't a health check just a true/false, and why are we so involved in this process and defining complex APIs?

/**
* @return Map of named attributes that provide additional information regarding the health.
* For example, a CPU health check may return Unhealthy with attribute "usage"="90%"
*/
public Map<String, Object> getAttributes();

private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss z");
/**
* @return True if healthy or false otherwise.
*/
public boolean isHealthy();

/**
* @return Exception providing additional information regarding the failure state. This could be
* the last known exception.
*/
public String getError();

/**
* @return True if the status includes a error description
*/
public boolean hasError();

/**
* @return Time when healthcheck was conducted
*/
public String getTimestamp();

/**
* @return Name of HealthIndicator from which this status was created
*/
public String getName();

static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss z");

public static HealthIndicatorStatus healthy(String name) {
return create(name, true, Collections.<String, Object>emptyMap(), null);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.netflix.karyon.health;
package com.netflix.karyon.api.health;

/**
* Health state of an application
*/
public enum HealthState {
Starting,
Healthy,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
package com.netflix.karyon.lifecycle;

import com.google.inject.ImplementedBy;
package com.netflix.karyon.api.lifecycle;

/**
* Contract for tracking the application LifecycleState. The application LifecycleState
Expand Down Expand Up @@ -64,7 +62,6 @@
* @author elandau
*
*/
@ImplementedBy(LifecycleListenerApplicationLifecycle.class)
public interface ApplicationLifecycle {
public interface Listener {
void onStateChanged(LifecycleState state);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.netflix.karyon.api.lifecycle;

/**
* State of an application lifecycle. State transitions are linear as described in
* the following diagram.
*
* {@code O -> Starting -> Running -> Stopping -> Stopped -> (O) }
*/
public enum LifecycleState {
Starting,
Running,
Stopping,
Stopped
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.netflix.karyon.health;
package com.netflix.karyon.spi.health;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spi? typo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class in the 'api' package are class that are called by the user of karyon. Classes in 'spi' are classes that are supposed to be implemented. This distinction can be confusing and sometimes ambiguous but I thought I'd give it a try.


import java.util.Collections;
import java.util.Map;

import com.netflix.karyon.api.health.HealthIndicator;
import com.netflix.karyon.api.health.HealthIndicatorStatus;

public abstract class AbstractHealthIndicator implements HealthIndicator {
private final String name;

Expand Down Expand Up @@ -37,7 +40,7 @@ public String getName() {
*/

protected final HealthIndicatorStatus healthy() {
return HealthIndicatorStatuses.create(getName(), true, Collections.<String, Object> emptyMap(), null);
return HealthIndicatorStatus.create(getName(), true, Collections.<String, Object> emptyMap(), null);
}

/**
Expand All @@ -48,7 +51,7 @@ protected final HealthIndicatorStatus healthy() {
* @return a healthy status
*/
protected final HealthIndicatorStatus healthy(Map<String, Object> attr) {
return HealthIndicatorStatuses.create(getName(), true, attr, null);
return HealthIndicatorStatus.create(getName(), true, attr, null);
}

/**
Expand All @@ -58,7 +61,7 @@ protected final HealthIndicatorStatus healthy(Map<String, Object> attr) {
* @return a unhealthy status
*/
protected final HealthIndicatorStatus unhealthy() {
return HealthIndicatorStatuses.create(getName(), false, Collections.<String, Object> emptyMap(), null);
return HealthIndicatorStatus.create(getName(), false, Collections.<String, Object> emptyMap(), null);
}

/**
Expand All @@ -68,7 +71,7 @@ protected final HealthIndicatorStatus unhealthy() {
* @return a unhealthy status
*/
protected final HealthIndicatorStatus unhealthy(Map<String, Object> attr) {
return HealthIndicatorStatuses.create(getName(), false, attr, null);
return HealthIndicatorStatus.create(getName(), false, attr, null);
}

/**
Expand All @@ -78,7 +81,7 @@ protected final HealthIndicatorStatus unhealthy(Map<String, Object> attr) {
* @return a unhealthy status
*/
protected final HealthIndicatorStatus unhealthy(Throwable t) {
return HealthIndicatorStatuses.create(getName(), false, Collections.<String, Object> emptyMap(), t);
return HealthIndicatorStatus.create(getName(), false, Collections.<String, Object> emptyMap(), t);
}

/**
Expand All @@ -88,7 +91,7 @@ protected final HealthIndicatorStatus unhealthy(Throwable t) {
* @return a unhealthy status
*/
protected final HealthIndicatorStatus unhealthy(Map<String, Object> attr, Throwable t) {
return HealthIndicatorStatuses.create(getName(), false, attr, t);
return HealthIndicatorStatus.create(getName(), false, attr, t);
}

}
Loading