diff --git a/.gitignore b/.gitignore index 8b2580f..2952864 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ pkg/ .vscode/ .vs/slnx.sqlite .vs/microservices-demo/v15/.suo +.idea +.skaffold-*.yaml +.kubernetes-manifests-*/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c79b0c2 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +sudo: required + +services: +- docker + +install: +- curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/v0.12.0/skaffold-linux-amd64 +- chmod +x skaffold +- sudo mv skaffold /usr/local/bin + +script: +- skaffold build --profile travis-ci diff --git a/README.md b/README.md index 0df2f15..aa6709b 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb). | [emailservice](./src/emailservice) | Python | Sends users an order confirmation email (hypothetically😇). | | [checkoutservice](./src/checkoutservice) | Go | Retrieves user cart, prepares order and orchestrates the payment, shipping and the email notification. | | [recommendationservice](./src/recommendationservice) | Python | Recommends other products based on what's given in the cart. | +| [adservice](./src/adservice) | Java | Provides text ads based on given context words. | | [loadgenerator](./src/loadgenerator) | Python/Locust | Continuously sends requests imitating realistic user shopping flows to the frontend. | @@ -109,12 +110,15 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb). gcloud auth configure-docker -q -3. Edit `skaffold.yaml`, prepend your GCR registry host (`gcr.io/YOUR_PROJECT/`) - to all `imageName:` fields (or update the existing project name). +3. Set your project ID on image names: -4. Edit the Deployment manifests in - [`./kubernetes-manifests`](./kubernetes-manifests) directory and update the - `image:` fields to match the changes you made in the previous step. + - Edit `skaffold.yaml`, update the `imageName:` fields that look like + `gcr.io/[PROJECT_ID]` with your own GCP project ID. + + - Similarly, edit all Kubernetes Deployment manifests in the + [`./kubernetes-manifests`](./kubernetes-manifests) directory. Find the + `image:` fields with `gcr.io/[...]` and change them to your own GCP project + ID. 5. Run `skaffold run` from the root of this repository. This command: - builds the container images diff --git a/img/architecture-diagram.png b/img/architecture-diagram.png index 108cdda..91a8a18 100644 Binary files a/img/architecture-diagram.png and b/img/architecture-diagram.png differ diff --git a/kubernetes-manifests/adservice.yaml b/kubernetes-manifests/adservice.yaml new file mode 100644 index 0000000..776d4fd --- /dev/null +++ b/kubernetes-manifests/adservice.yaml @@ -0,0 +1,63 @@ +# 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: adservice +spec: + template: + metadata: + labels: + app: adservice + spec: + terminationGracePeriodSeconds: 5 + containers: + - name: server + image: gcr.io/microservices-demo-app/adservice + ports: + - containerPort: 9555 + env: + - name: PORT + value: "9555" + resources: + requests: + cpu: 200m + memory: 180Mi + limits: + cpu: 300m + memory: 300Mi + readinessProbe: + tcpSocket: + port: 9555 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + tcpSocket: + port: 9555 + initialDelaySeconds: 10 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: adservice +spec: + type: ClusterIP + selector: + app: adservice + ports: + - name: grpc + port: 9555 + targetPort: 9555 diff --git a/kubernetes-manifests/frontend.yaml b/kubernetes-manifests/frontend.yaml index 4f62e77..d921a8f 100644 --- a/kubernetes-manifests/frontend.yaml +++ b/kubernetes-manifests/frontend.yaml @@ -30,7 +30,7 @@ spec: readinessProbe: initialDelaySeconds: 10 httpGet: - path: "/" + path: "/_healthz" port: 8080 httpHeaders: - name: "Cookie" diff --git a/pb/demo.proto b/pb/demo.proto index 11b8c29..09e5e4d 100644 --- a/pb/demo.proto +++ b/pb/demo.proto @@ -218,18 +218,18 @@ message PlaceOrderResponse { OrderResult order = 1; } -// ------------Ads service------------------ +// ------------Ad service------------------ -service AdsService { - rpc GetAds(AdsRequest) returns (AdsResponse) {} +service AdService { + rpc GetAds(AdRequest) returns (AdResponse) {} } -message AdsRequest { +message AdRequest { // List of important key words from the current page describing the context. repeated string context_keys = 1; } -message AdsResponse { +message AdResponse { repeated Ad ads = 1; } diff --git a/skaffold.yaml b/skaffold.yaml index a05d6eb..bd04f86 100644 --- a/skaffold.yaml +++ b/skaffold.yaml @@ -38,7 +38,31 @@ build: workspace: src/frontend - imageName: gcr.io/microservices-demo-app/loadgenerator workspace: src/loadgenerator + - imageName: gcr.io/microservices-demo-app/adservice + workspace: src/adservice deploy: kubectl: manifests: - ./kubernetes-manifests/**.yaml + + +profiles: + # "travis-ci" profile is used to build the images without + # pushing them. + - name: travis-ci + build: + local: + skipPush: true + # "gcb" profile allows building and pushing the images + # on Google Container Builder without requiring docker + # installed on the developer machine. However, note that + # since GCB does not cache the builds, each build will + # start from scratch and therefore take a long time. + # + # This is not used by default. To use it, run: + # skaffold run -p gcb + - name: gcb + build: + googleCloudBuild: + diskSizeGb: 300 + machineType: "N1_HIGHCPU_32" diff --git a/src/adservice/.gitignore b/src/adservice/.gitignore new file mode 100644 index 0000000..1809715 --- /dev/null +++ b/src/adservice/.gitignore @@ -0,0 +1,8 @@ +*.iml +*.ipr +*.iws +.gradle/** +.idea/** +build/** + + diff --git a/src/adservice/Dockerfile b/src/adservice/Dockerfile new file mode 100644 index 0000000..d65b040 --- /dev/null +++ b/src/adservice/Dockerfile @@ -0,0 +1,15 @@ +# adsservice +FROM openjdk:8 +RUN apt-get update && apt-get install net-tools telnet +WORKDIR /app + +# Next three steps are for caching dependency downloads +# to improve subsequent docker build. +COPY ["build.gradle", "gradlew", "./"] +COPY gradle gradle +RUN ./gradlew downloadRepos + +COPY . . +RUN ./gradlew installDist +EXPOSE 9555 +ENTRYPOINT ["/app/build/install/hipstershop/bin/AdService"] diff --git a/src/adservice/README.md b/src/adservice/README.md new file mode 100644 index 0000000..6d41ec3 --- /dev/null +++ b/src/adservice/README.md @@ -0,0 +1,26 @@ +# Ad Service + +The Ad service provides advertisement based on context keys. If no context keys are provided then it returns random ads. + +## Local Build + +The Ad service uses gradlew to compile/install/distribute. Gradle wrapper is already part of the source code. To build Ad Service, run +``` + cd src/adservice; ./gradlew installDist +``` +It will create executable script src/adservice/build/install/hipstershop/bin/AdService + +### Upgrade gradle version +If you need to upgrade the version of gradle then run +``` + cd src/adservice ; ./gradlew wrapper --gradle-version +``` + +## Docker Build + +From repository root, run: + +``` +docker build --file src/adservice/Dockerfile . +``` + diff --git a/src/adservice/build.gradle b/src/adservice/build.gradle new file mode 100644 index 0000000..47653ac --- /dev/null +++ b/src/adservice/build.gradle @@ -0,0 +1,122 @@ +description = 'Ad Service' + +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.15.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' +} + +ext { + speed = project.hasProperty('speed') ? project.getProperty('speed') : false + offlineCompile = new File("$buildDir/output/lib") +} + +dependencies { + if (speed) { + compile fileTree(dir: offlineCompile, include: '*.jar') + } else { + 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.grpc:grpc-services:${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/hipstershop' + srcDirs 'build/generated/source/proto/main/grpc/hipstershop' + } + } +} + +// Provide convenience executables for trying out the examples. +apply plugin: 'application' + +startScripts.enabled = false + +// This to cache dependencies during Docker image building. First build will take time. +// Subsequent build will be incremental. +task downloadRepos(type: Copy) { + from configurations.compile + into offlineCompile + from configurations.runtime + into offlineCompile +} + +task adService(type: CreateStartScripts) { + mainClassName = 'hipstershop.AdService' + applicationName = 'AdService' + outputDir = new File(project.buildDir, 'tmp') + classpath = jar.outputs.files + project.configurations.runtime +} + +task adServiceClient(type: CreateStartScripts) { + mainClassName = 'hipstershop.AdServiceClient' + applicationName = 'AdServiceClient' + outputDir = new File(project.buildDir, 'tmp') + classpath = jar.outputs.files + project.configurations.runtime +} + +applicationDistribution.into('bin') { + from(adService) + from(adServiceClient) + fileMode = 0755 +} diff --git a/src/adservice/genproto.sh b/src/adservice/genproto.sh new file mode 100755 index 0000000..36525e0 --- /dev/null +++ b/src/adservice/genproto.sh @@ -0,0 +1,22 @@ +#!/bin/bash -eu +# +# 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. + +#!/bin/bash -e + +# protos are needed in adservice folder for compiling during Docker build. + +mkdir -p proto && \ +cp ../../pb/demo.proto src/main/proto diff --git a/src/adservice/gradle/wrapper/gradle-wrapper.jar b/src/adservice/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..01b8bf6 Binary files /dev/null and b/src/adservice/gradle/wrapper/gradle-wrapper.jar differ diff --git a/src/adservice/gradle/wrapper/gradle-wrapper.properties b/src/adservice/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..933b647 --- /dev/null +++ b/src/adservice/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip diff --git a/src/adservice/gradlew b/src/adservice/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/src/adservice/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/adservice/gradlew.bat b/src/adservice/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/src/adservice/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/adservice/settings.gradle b/src/adservice/settings.gradle new file mode 100644 index 0000000..0bbe011 --- /dev/null +++ b/src/adservice/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'hipstershop' diff --git a/src/adservice/src/main/java/hipstershop/AdService.java b/src/adservice/src/main/java/hipstershop/AdService.java new file mode 100644 index 0000000..75ce76f --- /dev/null +++ b/src/adservice/src/main/java/hipstershop/AdService.java @@ -0,0 +1,242 @@ +/* + * 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. + */ + +package hipstershop; + +import com.google.common.collect.ImmutableMap; +import hipstershop.Demo.Ad; +import hipstershop.Demo.AdRequest; +import hipstershop.Demo.AdResponse; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.StatusRuntimeException; +import io.grpc.health.v1.HealthCheckResponse.ServingStatus; +import io.grpc.stub.StreamObserver; +import io.grpc.services.*; +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.Tracer; +import io.opencensus.trace.Tracing; +import io.opencensus.trace.samplers.Samplers; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class AdService { + private static final Logger logger = Logger.getLogger(AdService.class.getName()); + + private static final Tracer tracer = Tracing.getTracer(); + + private int MAX_ADS_TO_SERVE = 2; + private Server server; + private HealthStatusManager healthMgr; + + static final AdService service = new AdService(); + private void start() throws IOException { + int port = Integer.parseInt(System.getenv("PORT")); + healthMgr = new HealthStatusManager(); + + server = ServerBuilder.forPort(port).addService(new AdServiceImpl()) + .addService(healthMgr.getHealthService()).build().start(); + logger.info("Ad Service 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"); + AdService.this.stop(); + System.err.println("*** server shut down"); + } + }); + healthMgr.setStatus("", ServingStatus.SERVING); + } + + private void stop() { + if (server != null) { + healthMgr.clearStatus(""); + server.shutdown(); + } + } + + static class AdServiceImpl extends hipstershop.AdServiceGrpc.AdServiceImplBase { + + /** + * Retrieves ads based on context provided in the request {@code AdRequest}. + * + * @param req the request containing context. + * @param responseObserver the stream observer which gets notified with the value of + * {@code AdResponse} + */ + @Override + public void getAds(AdRequest req, StreamObserver responseObserver) { + AdService service = AdService.getInstance(); + Span parentSpan = tracer.getCurrentSpan(); + SpanBuilder spanBuilder = + tracer + .spanBuilderWithExplicitParent("Retrieve Ads", parentSpan) + .setRecordEvents(true) + .setSampler(Samplers.alwaysSample()); + try (Scope scope = spanBuilder.startScopedSpan()) { + Span span = tracer.getCurrentSpan(); + span.putAttribute("method", AttributeValue.stringAttributeValue("getAds")); + List ads = new ArrayList<>(); + logger.info("received ad request (context_words=" + req.getContextKeysCount() + ")"); + if (req.getContextKeysCount() > 0) { + span.addAnnotation( + "Constructing Ads using context", + ImmutableMap.of( + "Context Keys", + AttributeValue.stringAttributeValue(req.getContextKeysList().toString()), + "Context Keys length", + AttributeValue.longAttributeValue(req.getContextKeysCount()))); + for (int i = 0; i < req.getContextKeysCount(); i++) { + Ad ad = service.getAdsByKey(req.getContextKeys(i)); + if (ad != null) { + ads.add(ad); + } + } + } else { + span.addAnnotation("No Context provided. Constructing random Ads."); + ads = service.getDefaultAds(); + } + if (ads.isEmpty()) { + // Serve default ads. + span.addAnnotation("No Ads found based on context. Constructing random Ads."); + ads = service.getDefaultAds(); + } + AdResponse reply = AdResponse.newBuilder().addAllAds(ads).build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } catch (StatusRuntimeException e) { + logger.log(Level.WARNING, "GetAds Failed", e.getStatus()); + return; + } + } + } + + static final HashMap cacheMap = new HashMap(); + + Ad getAdsByKey(String key) { + return cacheMap.get(key); + } + + + public List getDefaultAds() { + List ads = new ArrayList<>(MAX_ADS_TO_SERVE); + Object[] keys = cacheMap.keySet().toArray(); + for (int i=0; i
-

© 2018 Google Inc

+

+ © 2018 Google Inc + + (Source Code) + +

This website is hosted for demo purposes only. It is not an @@ -12,7 +17,6 @@ {{ if $.session_id }}session-id: {{ $.session_id }}
{{end}} {{ if $.request_id }}request-id: {{ $.request_id }}
{{end}}
-

diff --git a/src/productcatalogservice/Gopkg.lock b/src/productcatalogservice/Gopkg.lock index ea18802..47756a3 100644 --- a/src/productcatalogservice/Gopkg.lock +++ b/src/productcatalogservice/Gopkg.lock @@ -2,27 +2,40 @@ [[projects]] + digest = "1:467af0aad47996b25b838d6f14c8371123a8a76ec239020a6c5894e1f8f60272" name = "cloud.google.com/go" packages = [ "compute/metadata", "internal/version", "monitoring/apiv3", "profiler", - "trace/apiv2" + "trace/apiv2", ] - revision = "64a2037ec6be8a4b0c1d1f706ed35b428b989239" - version = "v0.26.0" + pruneopts = "UT" + revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad" + version = "v0.27.0" [[projects]] + digest = "1:9fe70def8f0ceb3d455a0acad9dadd6632287cdbf9c8c2ea50e8dabe2ade40c4" name = "contrib.go.opencensus.io/exporter/stackdriver" packages = [ ".", - "propagation" + "propagation", ] + pruneopts = "UT" revision = "37aa2801fbf0205003e15636096ebf0373510288" version = "v0.5.0" [[projects]] + branch = "master" + digest = "1:c82c943645b21ca2fd3f9d248df1ca5f9055fb5fea5cf4145472163f198ed5df" + name = "github.com/GoogleCloudPlatform/microservices-demo" + packages = ["src/productcatalogservice/genproto"] + pruneopts = "UT" + revision = "6d969441585ade8c91c235115c7cdb12ac61354f" + +[[projects]] + digest = "1:4fbf68bee2a60f6af6414572936edb295f6f26b73c6fb25ab0e7b03b013854f5" name = "github.com/golang/protobuf" packages = [ "jsonpb", @@ -34,35 +47,43 @@ "ptypes/empty", "ptypes/struct", "ptypes/timestamp", - "ptypes/wrappers" + "ptypes/wrappers", ] - revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" - version = "v1.1.0" + pruneopts = "UT" + revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" + version = "v1.2.0" [[projects]] + digest = "1:2e3c336fc7fde5c984d2841455a658a6d626450b1754a854b3b32e7a8f49a07a" name = "github.com/google/go-cmp" packages = [ "cmp", "cmp/internal/diff", "cmp/internal/function", - "cmp/internal/value" + "cmp/internal/value", ] + pruneopts = "UT" revision = "3af367b6b30c263d47e8895973edcca9a49cf029" version = "v0.2.0" [[projects]] branch = "master" + digest = "1:089d56c0adb79140365b5c86815ce97233986da6f3a525c6b706773e4b83876f" name = "github.com/google/pprof" packages = ["profile"] - revision = "cf6d271c80826ef4d30d55512b5a77b115bd4b9c" + pruneopts = "UT" + revision = "84b7d314e22c8d12334e52726f68517973b6027b" [[projects]] + digest = "1:e145e9710a10bc114a6d3e2738aadf8de146adaa031854ffdf7bbfe15da85e63" name = "github.com/googleapis/gax-go" packages = ["."] + pruneopts = "UT" revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f" version = "v2.0.0" [[projects]] + digest = "1:1bb914cfb78f68f488a91cd7872d3d06a5f83c5bbacf0296dbef44e120b00a91" name = "go.opencensus.io" packages = [ ".", @@ -77,13 +98,16 @@ "tag", "trace", "trace/internal", - "trace/propagation" + "trace/propagation", + "trace/tracestate", ] - revision = "e262766cd0d230a1bb7c37281e345e465f19b41b" - version = "v0.14.0" + pruneopts = "UT" + revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89" + version = "v0.16.0" [[projects]] branch = "master" + digest = "1:1c14517b2f106c61d75006199b46a46576058661d469658cb0f90739919641d2" name = "golang.org/x/net" packages = [ "context", @@ -93,35 +117,43 @@ "http2/hpack", "idna", "internal/timeseries", - "trace" + "trace", ] - revision = "19491d39cadbd9cd33f26ca22cc89ba4ba38251c" + pruneopts = "UT" + revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2" [[projects]] branch = "master" + digest = "1:f645667d687fc8bf228865a2c5455824ef05bad08841e673673ef2bb89ac5b90" name = "golang.org/x/oauth2" packages = [ ".", "google", "internal", "jws", - "jwt" + "jwt", ] - revision = "3d292e4d0cdc3a0113e6d207bb137145ef1de42f" + pruneopts = "UT" + revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9" [[projects]] branch = "master" + digest = "1:e0140c0c868c6e0f01c0380865194592c011fe521d6e12d78bfd33e756fe018a" name = "golang.org/x/sync" packages = ["semaphore"] + pruneopts = "UT" revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" [[projects]] branch = "master" + digest = "1:6eb2645d74b43d9c87b51947df39f7c668a4f422cd512053f7f6f75bfaad0197" name = "golang.org/x/sys" packages = ["unix"] - revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945" + pruneopts = "UT" + revision = "d0be0721c37eeb5299f245a996a483160fc36940" [[projects]] + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -137,13 +169,15 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "UT" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" + digest = "1:e9e388241f9f0f02000dddaeeb91153d53f0cd09dcec33879cc7e043a2e65d75" name = "google.golang.org/api" packages = [ "googleapi/transport", @@ -153,11 +187,13 @@ "support/bundler", "transport", "transport/grpc", - "transport/http" + "transport/http", ] - revision = "9bdf771af19ab16b6a5084e5d542a7e04cb97004" + pruneopts = "UT" + revision = "7ca32eb868bf53ea2fc406698eb98583a8073d19" [[projects]] + digest = "1:26619fcd2452b4044174d26acd8b09c09dffee9a1c3a22d2383b873aa9a0131f" name = "google.golang.org/appengine" packages = [ ".", @@ -171,13 +207,15 @@ "internal/socket", "internal/urlfetch", "socket", - "urlfetch" + "urlfetch", ] + pruneopts = "UT" revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" version = "v1.1.0" [[projects]] branch = "master" + digest = "1:7a3da01a8f840fbbef1f027dc091ae52a29c6ab9374e126b6bdc5bf3b0ff2687" name = "google.golang.org/genproto" packages = [ "googleapis/api/annotations", @@ -190,11 +228,13 @@ "googleapis/monitoring/v3", "googleapis/rpc/errdetails", "googleapis/rpc/status", - "protobuf/field_mask" + "protobuf/field_mask", ] - revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" + pruneopts = "UT" + revision = "36d5787dc5356b711fe8f3040271aaf51c35955b" [[projects]] + digest = "1:4ad047d772a7d4841687df9534a767a9e243885ed6d7d2ced6af5995a5dc44b3" name = "google.golang.org/grpc" packages = [ ".", @@ -224,14 +264,29 @@ "resolver/passthrough", "stats", "status", - "tap" + "tap", ] - revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" - version = "v1.14.0" + pruneopts = "UT" + revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1" + version = "v1.15.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "9375853c56aec58c0407e2a95be6b83d632ff9d9921be437ea839904e9da5cf4" + input-imports = [ + "cloud.google.com/go/profiler", + "contrib.go.opencensus.io/exporter/stackdriver", + "github.com/GoogleCloudPlatform/microservices-demo/src/productcatalogservice/genproto", + "github.com/golang/protobuf/jsonpb", + "github.com/golang/protobuf/proto", + "github.com/google/go-cmp/cmp", + "go.opencensus.io/plugin/ocgrpc", + "go.opencensus.io/stats/view", + "go.opencensus.io/trace", + "golang.org/x/net/context", + "google.golang.org/grpc", + "google.golang.org/grpc/codes", + "google.golang.org/grpc/status", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/src/productcatalogservice/Gopkg.toml b/src/productcatalogservice/Gopkg.toml index 58b7da8..585d63c 100644 --- a/src/productcatalogservice/Gopkg.toml +++ b/src/productcatalogservice/Gopkg.toml @@ -27,15 +27,19 @@ [[constraint]] name = "cloud.google.com/go" - version = "0.26.0" + version = "0.27.0" [[constraint]] name = "contrib.go.opencensus.io/exporter/stackdriver" version = "0.5.0" +[[constraint]] + branch = "master" + name = "github.com/GoogleCloudPlatform/microservices-demo" + [[constraint]] name = "github.com/golang/protobuf" - version = "1.1.0" + version = "1.2.0" [[constraint]] name = "github.com/google/go-cmp" @@ -43,7 +47,7 @@ [[constraint]] name = "go.opencensus.io" - version = "0.14.0" + version = "0.16.0" [[constraint]] branch = "master" @@ -51,7 +55,7 @@ [[constraint]] name = "google.golang.org/grpc" - version = "1.14.0" + version = "1.15.0" [prune] go-tests = true diff --git a/src/productcatalogservice/server.go b/src/productcatalogservice/server.go index 067e68b..6599877 100644 --- a/src/productcatalogservice/server.go +++ b/src/productcatalogservice/server.go @@ -32,6 +32,7 @@ import ( "contrib.go.opencensus.io/exporter/stackdriver" "github.com/golang/protobuf/jsonpb" "go.opencensus.io/plugin/ocgrpc" + "go.opencensus.io/stats/view" "go.opencensus.io/trace" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -76,6 +77,15 @@ func run(port int) string { return l.Addr().String() } +func initStats(exporter *stackdriver.Exporter) { + view.RegisterExporter(exporter) + if err := view.Register(ocgrpc.DefaultServerViews...); err != nil { + log.Printf("Error registering default server views") + } else { + log.Printf("Registered default server views") + } +} + func initTracing() { // TODO(ahmetb) this method is duplicated in other microservices using Go // since they are not sharing packages. @@ -87,6 +97,9 @@ func initTracing() { trace.RegisterExporter(exporter) trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) log.Print("registered stackdriver tracing") + + // Register the views to collect server stats. + initStats(exporter) return } d := time.Second * 10 * time.Duration(i) diff --git a/src/shippingservice/Gopkg.lock b/src/shippingservice/Gopkg.lock index ac54449..a78a49e 100644 --- a/src/shippingservice/Gopkg.lock +++ b/src/shippingservice/Gopkg.lock @@ -2,27 +2,40 @@ [[projects]] + digest = "1:467af0aad47996b25b838d6f14c8371123a8a76ec239020a6c5894e1f8f60272" name = "cloud.google.com/go" packages = [ "compute/metadata", "internal/version", "monitoring/apiv3", "profiler", - "trace/apiv2" + "trace/apiv2", ] - revision = "64a2037ec6be8a4b0c1d1f706ed35b428b989239" - version = "v0.26.0" + pruneopts = "UT" + revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad" + version = "v0.27.0" [[projects]] + digest = "1:9fe70def8f0ceb3d455a0acad9dadd6632287cdbf9c8c2ea50e8dabe2ade40c4" name = "contrib.go.opencensus.io/exporter/stackdriver" packages = [ ".", - "propagation" + "propagation", ] + pruneopts = "UT" revision = "37aa2801fbf0205003e15636096ebf0373510288" version = "v0.5.0" [[projects]] + branch = "master" + digest = "1:57b417980654aa49be2ff6a1ee6498a412ab253930dd95f1e1f27a9bbf2e1081" + name = "github.com/GoogleCloudPlatform/microservices-demo" + packages = ["src/shippingservice/genproto"] + pruneopts = "UT" + revision = "6d969441585ade8c91c235115c7cdb12ac61354f" + +[[projects]] + digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a" name = "github.com/golang/protobuf" packages = [ "proto", @@ -33,24 +46,30 @@ "ptypes/empty", "ptypes/struct", "ptypes/timestamp", - "ptypes/wrappers" + "ptypes/wrappers", ] - revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" - version = "v1.1.0" + pruneopts = "UT" + revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" + version = "v1.2.0" [[projects]] branch = "master" + digest = "1:089d56c0adb79140365b5c86815ce97233986da6f3a525c6b706773e4b83876f" name = "github.com/google/pprof" packages = ["profile"] - revision = "cf6d271c80826ef4d30d55512b5a77b115bd4b9c" + pruneopts = "UT" + revision = "84b7d314e22c8d12334e52726f68517973b6027b" [[projects]] + digest = "1:e145e9710a10bc114a6d3e2738aadf8de146adaa031854ffdf7bbfe15da85e63" name = "github.com/googleapis/gax-go" packages = ["."] + pruneopts = "UT" revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f" version = "v2.0.0" [[projects]] + digest = "1:1bb914cfb78f68f488a91cd7872d3d06a5f83c5bbacf0296dbef44e120b00a91" name = "go.opencensus.io" packages = [ ".", @@ -65,13 +84,16 @@ "tag", "trace", "trace/internal", - "trace/propagation" + "trace/propagation", + "trace/tracestate", ] - revision = "e262766cd0d230a1bb7c37281e345e465f19b41b" - version = "v0.14.0" + pruneopts = "UT" + revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89" + version = "v0.16.0" [[projects]] branch = "master" + digest = "1:1c14517b2f106c61d75006199b46a46576058661d469658cb0f90739919641d2" name = "golang.org/x/net" packages = [ "context", @@ -81,35 +103,43 @@ "http2/hpack", "idna", "internal/timeseries", - "trace" + "trace", ] - revision = "19491d39cadbd9cd33f26ca22cc89ba4ba38251c" + pruneopts = "UT" + revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2" [[projects]] branch = "master" + digest = "1:f645667d687fc8bf228865a2c5455824ef05bad08841e673673ef2bb89ac5b90" name = "golang.org/x/oauth2" packages = [ ".", "google", "internal", "jws", - "jwt" + "jwt", ] - revision = "3d292e4d0cdc3a0113e6d207bb137145ef1de42f" + pruneopts = "UT" + revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9" [[projects]] branch = "master" + digest = "1:e0140c0c868c6e0f01c0380865194592c011fe521d6e12d78bfd33e756fe018a" name = "golang.org/x/sync" packages = ["semaphore"] + pruneopts = "UT" revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" [[projects]] branch = "master" + digest = "1:6eb2645d74b43d9c87b51947df39f7c668a4f422cd512053f7f6f75bfaad0197" name = "golang.org/x/sys" packages = ["unix"] - revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945" + pruneopts = "UT" + revision = "d0be0721c37eeb5299f245a996a483160fc36940" [[projects]] + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -125,13 +155,15 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "UT" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" + digest = "1:e9e388241f9f0f02000dddaeeb91153d53f0cd09dcec33879cc7e043a2e65d75" name = "google.golang.org/api" packages = [ "googleapi/transport", @@ -141,11 +173,13 @@ "support/bundler", "transport", "transport/grpc", - "transport/http" + "transport/http", ] - revision = "9bdf771af19ab16b6a5084e5d542a7e04cb97004" + pruneopts = "UT" + revision = "7ca32eb868bf53ea2fc406698eb98583a8073d19" [[projects]] + digest = "1:26619fcd2452b4044174d26acd8b09c09dffee9a1c3a22d2383b873aa9a0131f" name = "google.golang.org/appengine" packages = [ ".", @@ -159,13 +193,15 @@ "internal/socket", "internal/urlfetch", "socket", - "urlfetch" + "urlfetch", ] + pruneopts = "UT" revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" version = "v1.1.0" [[projects]] branch = "master" + digest = "1:7a3da01a8f840fbbef1f027dc091ae52a29c6ab9374e126b6bdc5bf3b0ff2687" name = "google.golang.org/genproto" packages = [ "googleapis/api/annotations", @@ -178,11 +214,13 @@ "googleapis/monitoring/v3", "googleapis/rpc/errdetails", "googleapis/rpc/status", - "protobuf/field_mask" + "protobuf/field_mask", ] - revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" + pruneopts = "UT" + revision = "36d5787dc5356b711fe8f3040271aaf51c35955b" [[projects]] + digest = "1:97c4b6de720998595a38558d26277cffc14290a7f60ae2cf6f077a300c50ed17" name = "google.golang.org/grpc" packages = [ ".", @@ -214,14 +252,26 @@ "resolver/passthrough", "stats", "status", - "tap" + "tap", ] - revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" - version = "v1.14.0" + pruneopts = "UT" + revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1" + version = "v1.15.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "e2a0b47948cf03a5d2a05d2baf26b0a1f4da4102b2c7bbba377d46c1095444f9" + input-imports = [ + "cloud.google.com/go/profiler", + "contrib.go.opencensus.io/exporter/stackdriver", + "github.com/GoogleCloudPlatform/microservices-demo/src/shippingservice/genproto", + "github.com/golang/protobuf/proto", + "go.opencensus.io/plugin/ocgrpc", + "go.opencensus.io/stats/view", + "go.opencensus.io/trace", + "golang.org/x/net/context", + "google.golang.org/grpc", + "google.golang.org/grpc/reflection", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/src/shippingservice/Gopkg.toml b/src/shippingservice/Gopkg.toml index e7f0fee..d82eeb4 100644 --- a/src/shippingservice/Gopkg.toml +++ b/src/shippingservice/Gopkg.toml @@ -27,19 +27,23 @@ [[constraint]] name = "cloud.google.com/go" - version = "0.26.0" + version = "0.27.0" [[constraint]] name = "contrib.go.opencensus.io/exporter/stackdriver" version = "0.5.0" +[[constraint]] + branch = "master" + name = "github.com/GoogleCloudPlatform/microservices-demo" + [[constraint]] name = "github.com/golang/protobuf" - version = "1.1.0" + version = "1.2.0" [[constraint]] name = "go.opencensus.io" - version = "0.14.0" + version = "0.16.0" [[constraint]] branch = "master" @@ -47,7 +51,7 @@ [[constraint]] name = "google.golang.org/grpc" - version = "1.14.0" + version = "1.15.0" [prune] go-tests = true diff --git a/src/shippingservice/main.go b/src/shippingservice/main.go index 59526ba..f82787a 100644 --- a/src/shippingservice/main.go +++ b/src/shippingservice/main.go @@ -24,6 +24,7 @@ import ( "cloud.google.com/go/profiler" "contrib.go.opencensus.io/exporter/stackdriver" "go.opencensus.io/plugin/ocgrpc" + "go.opencensus.io/stats/view" "go.opencensus.io/trace" "golang.org/x/net/context" "google.golang.org/grpc" @@ -111,6 +112,15 @@ func (s *server) ShipOrder(ctx context.Context, in *pb.ShipOrderRequest) (*pb.Sh }, nil } +func initStats(exporter *stackdriver.Exporter) { + view.RegisterExporter(exporter) + if err := view.Register(ocgrpc.DefaultServerViews...); err != nil { + log.Printf("Error registering default server views") + } else { + log.Printf("Registered default server views") + } +} + func initTracing() { // TODO(ahmetb) this method is duplicated in other microservices using Go // since they are not sharing packages. @@ -122,6 +132,9 @@ func initTracing() { trace.RegisterExporter(exporter) trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()}) log.Print("registered stackdriver tracing") + + // Register the views to collect server stats. + initStats(exporter) return } d := time.Second * 10 * time.Duration(i)