diff --git a/kubernetes-manifests/adsservice.yaml b/kubernetes-manifests/adsservice.yaml new file mode 100644 index 0000000..096c4e2 --- /dev/null +++ b/kubernetes-manifests/adsservice.yaml @@ -0,0 +1,67 @@ +# Copyright 2018 Google LLC +# +# 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. + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: adsservice +spec: + template: + metadata: + labels: + app: adsservice + spec: + terminationGracePeriodSeconds: 5 + containers: + - name: server + image: gcr.io/istio-next/adsservice + ports: + - containerPort: 9555 + env: + - name: PORT + value: "9555" + - name: LISTEN_ADDR + value: "0.0.0.0" + - name: ADS_URL + value: "http://localhost:10010/ads/" + resources: + requests: + cpu: 200m + memory: 64Mi + limits: + cpu: 300m + memory: 128Mi + readinessProbe: + tcpSocket: + port: 9555 + initialDelaySeconds: 15 + periodSeconds: 10 + livenessProbe: + tcpSocket: + port: 9555 + initialDelaySeconds: 15 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: adsservice +spec: + type: ClusterIP + selector: + app: adsservice + ports: + - name: grpc + port: 9555 + targetPort: 9555 diff --git a/skaffold.yaml b/skaffold.yaml index a05d6eb..250ca96 100644 --- a/skaffold.yaml +++ b/skaffold.yaml @@ -34,6 +34,8 @@ build: workspace: src/currencyservice - imageName: gcr.io/microservices-demo-app/cartservice workspace: src/cartservice + - imageName: gcr.io/istio-next/adsservice + workspace: src/adsservice - imageName: gcr.io/microservices-demo-app/frontend workspace: src/frontend - imageName: gcr.io/microservices-demo-app/loadgenerator diff --git a/src/adsservice/.gitignore b/src/adsservice/.gitignore new file mode 100644 index 0000000..69caab2 --- /dev/null +++ b/src/adsservice/.gitignore @@ -0,0 +1,10 @@ +*.iml +*.ipr +*.iws +.gradle/** +.idea/** +build/** +gradle/** +gradlew.bat + + diff --git a/src/adsservice/Dockerfile b/src/adsservice/Dockerfile new file mode 100644 index 0000000..1a0c0e0 --- /dev/null +++ b/src/adsservice/Dockerfile @@ -0,0 +1,9 @@ +# cartservice +FROM openjdk:8 +RUN apt-get update && apt-get install net-tools telnet +WORKDIR /app +COPY build/install . +EXPOSE 9555 +ENTRYPOINT ["/app/hipstershop/bin/AdsService"] +#ENTRYPOINT ["ls /"] + diff --git a/src/adsservice/build.gradle b/src/adsservice/build.gradle new file mode 100644 index 0000000..b6554c2 --- /dev/null +++ b/src/adsservice/build.gradle @@ -0,0 +1,103 @@ +description = 'OpenCensus Examples' + +buildscript { + repositories { + mavenCentral() + mavenLocal() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3' + } +} + +apply plugin: 'idea' +apply plugin: 'java' +apply plugin: 'com.google.protobuf' + +repositories { + mavenCentral() + mavenLocal() +} + +group = "adservice" +version = "0.1.0-SNAPSHOT" // CURRENT_OPENCENSUS_VERSION + +def opencensusVersion = "0.14.0" // LATEST_OPENCENSUS_RELEASE_VERSION +def grpcVersion = "1.10.1" // CURRENT_GRPC_VERSION +def prometheusVersion = "0.3.0" + +tasks.withType(JavaCompile) { + sourceCompatibility = '1.8' + targetCompatibility = '1.8' +} + +dependencies { + compile "com.google.api.grpc:proto-google-common-protos:1.11.0", + "io.opencensus:opencensus-exporter-stats-prometheus:${opencensusVersion}", + "io.opencensus:opencensus-exporter-stats-stackdriver:${opencensusVersion}", + "io.opencensus:opencensus-exporter-trace-stackdriver:${opencensusVersion}", + "io.opencensus:opencensus-exporter-trace-logging:${opencensusVersion}", + "io.grpc:grpc-protobuf:${grpcVersion}", + "io.grpc:grpc-stub:${grpcVersion}", + "io.grpc:grpc-netty:${grpcVersion}", + "io.prometheus:simpleclient_httpserver:${prometheusVersion}" + + runtime "io.opencensus:opencensus-impl:${opencensusVersion}", + "io.netty:netty-tcnative-boringssl-static:2.0.8.Final" +} + +protobuf { + protoc { + artifact = 'com.google.protobuf:protoc:3.5.1-1' + } + plugins { + grpc { + artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" + } + } + generateProtoTasks { + all()*.plugins { + grpc {} + } + ofSourceSet('main') + } +} + +// Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code. +sourceSets { + main { + java { + srcDirs 'hipstershop' + srcDirs 'build/generated/source/proto/main/java' + srcDirs 'build/generated/source/proto/main/grpc/hipstershop' + } + } +} + +// Provide convenience executables for trying out the examples. +apply plugin: 'application' + +startScripts.enabled = false + +task adsService(type: CreateStartScripts) { + mainClassName = 'hipstershop.AdsService' + applicationName = 'AdsService' + outputDir = new File(project.buildDir, 'tmp') + classpath = jar.outputs.files + project.configurations.runtime +} + +task adsServiceClient(type: CreateStartScripts) { + mainClassName = 'hipstershop.AdsServiceClient' + applicationName = 'AdsServiceClient' + outputDir = new File(project.buildDir, 'tmp') + classpath = jar.outputs.files + project.configurations.runtime +} + +applicationDistribution.into('bin') { + from(adsService) + from(adsServiceClient) + fileMode = 0755 +} diff --git a/src/adsservice/gradlew b/src/adsservice/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/src/adsservice/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/src/adsservice/settings.gradle b/src/adsservice/settings.gradle new file mode 100644 index 0000000..1d1bd06 --- /dev/null +++ b/src/adsservice/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'hipstershop' \ No newline at end of file diff --git a/src/adsservice/src/main/java/hipstershop/AdsService.java b/src/adsservice/src/main/java/hipstershop/AdsService.java new file mode 100644 index 0000000..d9a5856 --- /dev/null +++ b/src/adsservice/src/main/java/hipstershop/AdsService.java @@ -0,0 +1,187 @@ +package hipstershop; + +import com.google.common.collect.ImmutableMap; +import hipstershop.Demo.Ads; +import hipstershop.Demo.AdsRequest; +import hipstershop.Demo.AdsResponse; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.stub.StreamObserver; +import io.opencensus.common.Duration; +import io.opencensus.contrib.grpc.metrics.RpcViews; +import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector; +import io.opencensus.exporter.trace.logging.LoggingTraceExporter; +import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration; +import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; +import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration; +import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.Span; +import io.opencensus.trace.Tracer; +import io.opencensus.trace.Tracing; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +public class AdsService { + private static final Logger logger = Logger.getLogger(AdsService.class.getName()); + + private static final Tracer tracer = Tracing.getTracer(); + + private int MAX_ADS_TO_SERVE = 2; + private Server server; + + static final AdsService service = new AdsService(); + private void start() throws IOException { + int port = Integer.parseInt(System.getenv("PORT")); + server = ServerBuilder.forPort(port).addService(new AdsServiceImpl()).build().start(); + logger.info("Server started, listening on " + port); + Runtime.getRuntime() + .addShutdownHook( + new Thread() { + @Override + public void run() { + // Use stderr here since the logger may have been reset by its JVM shutdown hook. + System.err.println("*** shutting down gRPC ads server since JVM is shutting down"); + AdsService.this.stop(); + System.err.println("*** server shut down"); + } + }); + } + + private void stop() { + if (server != null) { + server.shutdown(); + } + } + + static class AdsServiceImpl extends hipstershop.AdsServiceGrpc.AdsServiceImplBase { + + /** + * Retrieves ads based on context provided in the request {@code AdsRequest}. + * + * @param req the request containing context. + * @param responseObserver the stream observer which gets notified with the value of + * {@code AdsResponse} + */ + @Override + public void getAds(AdsRequest req, StreamObserver responseObserver) { + logger.info("Servicing getAds"); + AdsService service = AdsService.getInstance(); + Span span = tracer.getCurrentSpan(); + span.putAttribute("method", AttributeValue.stringAttributeValue("getAds")); + span.addAnnotation( + "Constructing Ads Request.", + ImmutableMap.of( + "Context Keys", AttributeValue.stringAttributeValue(req.getContextKeysList().toString()), + "Context Keys length", AttributeValue.longAttributeValue(req.getContextKeysCount()))); + List ads = new ArrayList<>(); + if (req.getContextKeysCount() > 0) { + span.addAnnotation("Getting Ads by context."); + for (int i = 0; i cacheMap = new HashMap(); + + Ads getAdsByKey(String key) { + return cacheMap.get(key); + } + + + public List getDefaultAds() { + List ads = new ArrayList<>(); + Iterator iterator = cacheMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry pair = (Map.Entry)iterator.next(); + ads.add((Ads)pair.getValue()); + if (ads.size() >= MAX_ADS_TO_SERVE) { + break; + } + } + return ads; + } + + public static AdsService getInstance() { + return service; + } + + /** Await termination on the main thread since the grpc library uses daemon threads. */ + private void blockUntilShutdown() throws InterruptedException { + if (server != null) { + server.awaitTermination(); + } + } + + static void initializeAds() { + // TODO: Replace localhost with + String adsUrl = System.getenv("ADS_URL"); + cacheMap.put("camera", Ads.newBuilder().setRedirectUrl(adsUrl + "/camera") + .setText("MyPro camera for sale. 50% off.").build()); + cacheMap.put("bike", Ads.newBuilder().setRedirectUrl(adsUrl + "/bike") + .setText("ZoomZoom bike for sale. 10% off.").build()); + cacheMap.put("kitchen", Ads.newBuilder().setRedirectUrl(adsUrl + "/kitchen") + .setText("CutPro knife for sale. Buy one, get second set for free").build()); + logger.info("Default Ads initialized"); + } + + /** Main launches the server from the command line. */ + public static void main(String[] args) throws IOException, InterruptedException { + // Add final keyword to pass checkStyle. + final String cloudProjectId = System.getenv("GCP_PROJECT_ID"); + logger.info("GCP Project ID is " + cloudProjectId); + + initializeAds(); + + // Registers all RPC views. + RpcViews.registerAllViews(); + + // Registers logging trace exporter. + LoggingTraceExporter.register(); + + + // Registers Stackdriver exporters. + if (cloudProjectId != null) { + StackdriverTraceExporter.createAndRegister( + StackdriverTraceConfiguration.builder().setProjectId(cloudProjectId).build()); + StackdriverStatsExporter.createAndRegister( + StackdriverStatsConfiguration.builder() + .setProjectId(cloudProjectId) + .setExportInterval(Duration.create(15, 0)) + .build()); + } + + // Register Prometheus exporters and export metrics to a Prometheus HTTPServer. + PrometheusStatsCollector.createAndRegister(); + + // Start the RPC server. You shouldn't see any output from gRPC before this. + logger.info("AdsService starting."); + final AdsService service = AdsService.getInstance(); + service.start(); + service.blockUntilShutdown(); + } +} \ No newline at end of file diff --git a/src/adsservice/src/main/java/hipstershop/AdsServiceClient.java b/src/adsservice/src/main/java/hipstershop/AdsServiceClient.java new file mode 100644 index 0000000..d9e9dc5 --- /dev/null +++ b/src/adsservice/src/main/java/hipstershop/AdsServiceClient.java @@ -0,0 +1,173 @@ +/* + * Copyright 2018, OpenCensus Authors + * + * 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. + */ + +package hipstershop; + + +import com.google.common.collect.ImmutableMap; +import hipstershop.Demo.Ads; +import hipstershop.Demo.AdsRequest; +import hipstershop.Demo.AdsResponse; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.StatusRuntimeException; +import io.grpc.stub.StreamObserver; +import io.opencensus.common.Duration; +import io.opencensus.common.Scope; +import io.opencensus.contrib.grpc.metrics.RpcViews; +import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector; +import io.opencensus.exporter.trace.logging.LoggingTraceExporter; +import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration; +import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; +import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration; +import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanBuilder; +import io.opencensus.trace.Status.CanonicalCode; +import io.opencensus.trace.Tracer; +import io.opencensus.trace.Tracing; +import io.opencensus.trace.samplers.Samplers; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** A simple client that requests a greeting from the {@link AdsServiceClient}. */ +public class AdsServiceClient { + private static final Logger logger = Logger.getLogger(AdsServiceClient.class.getName()); + + private static final Tracer tracer = Tracing.getTracer(); + + private final ManagedChannel channel; + private final hipstershop.AdsServiceGrpc.AdsServiceBlockingStub blockingStub; + + /** Construct client connecting to HelloWorld server at {@code host:port}. */ + public AdsServiceClient(String host, int port) { + this( + ManagedChannelBuilder.forAddress(host, port) + // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid + // needing certificates. + .usePlaintext(true) + .build()); + } + + /** Construct client for accessing RouteGuide server using the existing channel. */ + AdsServiceClient(ManagedChannel channel) { + this.channel = channel; + blockingStub = hipstershop.AdsServiceGrpc.newBlockingStub(channel); + } + + public void shutdown() throws InterruptedException { + channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + + /** Say hello to server. */ + public void getAds(String contextKey) { + logger.info("Get Ads with context " + contextKey + " ..."); + AdsRequest request = AdsRequest.newBuilder().addContextKeys(contextKey).build(); + AdsResponse response; + + SpanBuilder spanBuilder = + tracer.spanBuilder("AdsClient").setRecordEvents(true).setSampler(Samplers.alwaysSample()); + try (Scope scope = spanBuilder.startScopedSpan()) { + tracer.getCurrentSpan().addAnnotation("Getting Ads"); + response = blockingStub.getAds(request); + tracer.getCurrentSpan().addAnnotation("Received response from Ads Service."); + } catch (StatusRuntimeException e) { + tracer + .getCurrentSpan() + .setStatus( + CanonicalCode.valueOf(e.getStatus().getCode().name()) + .toStatus() + .withDescription(e.getMessage())); + logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); + return; + } + for(Ads ads: response.getAdsList()) { + logger.info("Ads: " + ads.getText()); + } + } + + static int getPortOrDefaultFromArgs(String[] args, int index, int defaultPort) { + int portNumber = defaultPort; + if (index < args.length) { + try { + portNumber = Integer.parseInt(args[index]); + } catch (NumberFormatException e) { + logger.warning( + String.format("Port %s is invalid, use default port %d.", args[index], defaultPort)); + } + } + return portNumber; + } + + + static String getStringOrDefaultFromArgs( + String[] args, int index, @Nullable String defaultString) { + String s = defaultString; + if (index < args.length) { + s = args[index]; + } + return s; + } + + /** + * Greet server. If provided, the first element of {@code args} is the name to use in the + * greeting. + */ + public static void main(String[] args) throws IOException, InterruptedException { + // Add final keyword to pass checkStyle. + final String contextKeys = getStringOrDefaultFromArgs(args, 0, "camera"); + final String host = getStringOrDefaultFromArgs(args, 1, "localhost"); + final int serverPort = getPortOrDefaultFromArgs(args, 2, 9555); + final String cloudProjectId = getStringOrDefaultFromArgs(args, 3, null); + //final int zPagePort = getPortOrDefaultFromArgs(args, 4, 3001); + + // Registers all RPC views. + RpcViews.registerAllViews(); + + + // Registers logging trace exporter. + LoggingTraceExporter.register(); + + // Registers Stackdriver exporters. + if (cloudProjectId != null) { + StackdriverTraceExporter.createAndRegister( + StackdriverTraceConfiguration.builder().setProjectId(cloudProjectId).build()); + StackdriverStatsExporter.createAndRegister( + StackdriverStatsConfiguration.builder() + .setProjectId(cloudProjectId) + .setExportInterval(Duration.create(15, 0)) + .build()); + } + + // Register Prometheus exporters and export metrics to a Prometheus HTTPServer. + //PrometheusStatsCollector.createAndRegister(); + + AdsServiceClient client = new AdsServiceClient(host, serverPort); + try { + client.getAds(contextKeys); + } finally { + client.shutdown(); + } + + logger.info("Exiting AdsServiceClient..."); + } +} diff --git a/src/adsservice/src/main/proto/demo.proto b/src/adsservice/src/main/proto/demo.proto new file mode 120000 index 0000000..f3c47fb --- /dev/null +++ b/src/adsservice/src/main/proto/demo.proto @@ -0,0 +1 @@ +../../../../../pb/demo.proto \ No newline at end of file