Merge branch 'master' of github.com:GoogleCloudPlatform/microservices-demo

This commit is contained in:
Simon Zeltser 2019-02-05 19:48:04 -08:00
commit 658efb3278
37 changed files with 1081 additions and 403 deletions

View file

@ -4,7 +4,7 @@ services:
- docker - docker
install: install:
- curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/v0.18.0/skaffold-linux-amd64 - curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/v0.20.0/skaffold-linux-amd64
- chmod +x skaffold - chmod +x skaffold
- sudo mv skaffold /usr/local/bin - sudo mv skaffold /usr/local/bin

View file

@ -5,13 +5,18 @@ web-based e-commerce app called **“Hipster Shop”** where users can browse it
add them to the cart, and purchase them. add them to the cart, and purchase them.
**Google uses this application to demonstrate Kubernetes, GKE, Istio, **Google uses this application to demonstrate Kubernetes, GKE, Istio,
Stackdriver, gRPC** and similar cloud-native technologies nowadays. Stackdriver, gRPC, OpenCensus** and similar cloud-native technologies.
> **Note to Googlers:** Please fill out the form at
[go/microservices-demo](http://go/microservices-demo) if you are using this
application.
## Screenshots ## Screenshots
| Home Page | Checkout Screen | | Home Page | Checkout Screen |
|-----------|-----------------| |-----------|-----------------|
| [![Screenshot of store homepage](./img/hipster-shop-frontend-1.png)](./img/hipster-shop-frontend-1.png) | [![Screenshot of checkout screen](./img/hipster-shop-frontend-2.png)](./img/hipster-shop-frontend-2.png) | | [![Screenshot of store homepage](./docs/img/hipster-shop-frontend-1.png)](./docs/img/hipster-shop-frontend-1.png) | [![Screenshot of checkout screen](./docs/img/hipster-shop-frontend-2.png)](./docs/img/hipster-shop-frontend-2.png) |
## Service Architecture ## Service Architecture
@ -19,7 +24,7 @@ Stackdriver, gRPC** and similar cloud-native technologies nowadays.
languages that talk to each other over gRPC. languages that talk to each other over gRPC.
[![Architecture of [![Architecture of
microservices](./img/architecture-diagram.png)](./img/architecture-diagram.png) microservices](./docs/img/architecture-diagram.png)](./docs/img/architecture-diagram.png)
Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb). Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
@ -74,16 +79,19 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
- Docker for Desktop (Mac/Windows): It provides Kubernetes support as [noted - Docker for Desktop (Mac/Windows): It provides Kubernetes support as [noted
here](https://docs.docker.com/docker-for-mac/kubernetes/). here](https://docs.docker.com/docker-for-mac/kubernetes/).
- [skaffold](https://github.com/GoogleContainerTools/skaffold/#installation) - [skaffold](https://github.com/GoogleContainerTools/skaffold/#installation)
(ensure version ≥v0.20)
1. Launch “Docker for Desktop”. Go to Preferences and choose “Enable Kubernetes”. 1. Launch “Docker for Desktop”. Go to Preferences:
- choose “Enable Kubernetes”,
- set CPUs to at least 3, and Memory to at least 6.0 GiB
1. Run `kubectl get nodes` to verify you're connected to “Kubernetes on Docker”. 3. Run `kubectl get nodes` to verify you're connected to “Kubernetes on Docker”.
1. Run `skaffold run` (first time will be slow, it can take ~20-30 minutes). 4. Run `skaffold run` (first time will be slow, it can take ~20-30 minutes).
This will build and deploy the application. If you need to rebuild the images This will build and deploy the application. If you need to rebuild the images
automatically as you refactor he code, run `skaffold dev` command. automatically as you refactor he code, run `skaffold dev` command.
1. Run `kubectl get pods` to verify the Pods are ready and running. The 5. Run `kubectl get pods` to verify the Pods are ready and running. The
application frontend should be available at http://localhost:80 on your application frontend should be available at http://localhost:80 on your
machine. machine.
@ -112,16 +120,18 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
1. In the root of this repository, run `skaffold run --default-repo=gcr.io/[PROJECT_ID]`, 1. In the root of this repository, run `skaffold run --default-repo=gcr.io/[PROJECT_ID]`,
where [PROJECT_ID] is your GCP project ID. where [PROJECT_ID] is your GCP project ID.
This command: This command:
- builds the container images - builds the container images
- pushes them to GCR - pushes them to GCR
- applies the `./kubernetes-manifests` deploying the application to - applies the `./kubernetes-manifests` deploying the application to
Kubernetes. Kubernetes.
**Troubleshooting:** If you get "No space left on device" error on Google Cloud Shell, **Troubleshooting:** If you get "No space left on device" error on Google
you can build the images on Google Cloud Build: Cloud Shell, you can build the images on Google Cloud Build: [Enable the
[Enable the Cloud Build API](https://console.cloud.google.com/flows/enableapi?apiid=cloudbuild.googleapis.com), then run `skaffold run -p gcb --default-repo=gcr.io/[PROJECT_ID]` instead. Cloud Build
API](https://console.cloud.google.com/flows/enableapi?apiid=cloudbuild.googleapis.com),
then run `skaffold run -p gcb --default-repo=gcr.io/[PROJECT_ID]` instead.
1. Find the IP address of your application, then visit the application on your 1. Find the IP address of your application, then visit the application on your
browser to confirm installation. browser to confirm installation.
@ -134,38 +144,62 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
are seeing this, run `kubectl get service frontend-external -o=yaml | kubectl apply -f-` are seeing this, run `kubectl get service frontend-external -o=yaml | kubectl apply -f-`
to trigger load balancer reconfiguration. to trigger load balancer reconfiguration.
### (Optional) Deploying on a Istio-installed cluster ### Option 3: Using Static Images
> 💡 Recommended for test-driving the application on an existing cluster.
**Prerequisite**: a running Kubernetes cluster.
1. Clone this repository.
1. Deploy the application: `kubectl apply -f ./release/kubernetes-manifests`
1. Run `kubectl get pods` to see pods are in a healthy and ready state.
1. Find the IP address of your application, then visit the application on your
browser to confirm installation.
kubectl get service frontend-external
### (Optional) Deploying on a Istio-installed GKE cluster
> **Note:** you followed GKE deployment steps above, run `skaffold delete` first > **Note:** you followed GKE deployment steps above, run `skaffold delete` first
> to delete what's deployed. > to delete what's deployed.
1. Create a GKE cluster. 1. Create a GKE cluster (described above).
2. Install Istio **without mutual TLS** authentication option. 2. Use [Istio on GKE add-on](https://cloud.google.com/istio/docs/istio-on-gke/installing)
to install Istio to your existing GKE cluster.
> (Optional) If you'd like to enable mTLS in the demo app, you need to gcloud beta container clusters update demo \
> make a few changes to the deployment manifests: --zone=us-central1-a \
--update-addons=Istio=ENABLED \
--istio-config=auth=MTLS_PERMISSIVE
> NOTE: If you need to enable `MTLS_STRICT` mode, you will need to update
> several manifest files:
> >
> - `kubernetes-manifests/frontend.yaml`: delete "livenessProbe" and > - `kubernetes-manifests/frontend.yaml`: delete "livenessProbe" and
> "readinessProbe" fields. > "readinessProbe" fields.
> - `kubernetes-manifests/loadgenerator.yaml`: delete "initContainers" field. > - `kubernetes-manifests/loadgenerator.yaml`: delete "initContainers" field.
3. Install the automatic sidecar injection (annotate the `default` namespace 3. (Optional) Enable Stackdriver Tracing/Logging with Istio Stackdriver Adapter
by [following this guide](https://cloud.google.com/istio/docs/istio-on-gke/installing#enabling_tracing_and_logging).
4. Install the automatic sidecar injection (annotate the `default` namespace
with the label): with the label):
kubectl label namespace default istio-injection=enabled kubectl label namespace default istio-injection=enabled
4. Apply the manifests in [`./istio-manifests`](./istio-manifests) directory. 5. Apply the manifests in [`./istio-manifests`](./istio-manifests) directory.
kubectl apply -f ./istio-manifests kubectl apply -f ./istio-manifests
This is required only once. This is required only once.
5. Deploy the application with `skaffold run --default-repo=gcr.io/[PROJECT_ID]`. 6. Deploy the application with `skaffold run --default-repo=gcr.io/[PROJECT_ID]`.
6. Run `kubectl get pods` to see pods are in a healthy and ready state. 7. Run `kubectl get pods` to see pods are in a healthy and ready state.
7. Find the IP address of your istio gateway Ingress or Service, and visit the 8. Find the IP address of your istio gateway Ingress or Service, and visit the
application. application.
INGRESS_HOST="$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" INGRESS_HOST="$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
@ -174,10 +208,16 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
curl -v "http://$INGRESS_HOST" curl -v "http://$INGRESS_HOST"
## Conferences featuring Hipster Shop
- [Google Cloud Next'18 London Keynote](https://youtu.be/nIq2pkNcfEI?t=3071)
showing Stackdriver Incident Response Management
- Google Cloud Next'18 SF
- [Day 1 Keynote](https://youtu.be/vJ9OaAqfxo4?t=2416) showing GKE On-Prem
- [Day 3 Keynote](https://youtu.be/JQPOPV_VH5w?t=815) showing Stackdriver
APM (Tracing, Code Search, Profiler, Google Cloud Build)
- [Introduction to Service Management with Istio](https://www.youtube.com/watch?v=wCJrdKdD6UM&feature=youtu.be&t=586)
--- ---
**Note to fellow Googlers:** Please fill out the form at This is not an official Google project.
[go/microservices-demo](http://go/microservices-demo) if you are using this
application.
This is not an official Google project.

View file

@ -11,7 +11,7 @@
steps: steps:
- id: 'Deploy application to cluster' - id: 'Deploy application to cluster'
name: 'gcr.io/k8s-skaffold/skaffold:v0.18.0' name: 'gcr.io/k8s-skaffold/skaffold:v0.20.0'
entrypoint: 'bash' entrypoint: 'bash'
args: args:
- '-c' - '-c'

View file

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 776 KiB

After

Width:  |  Height:  |  Size: 776 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 358 KiB

After

Width:  |  Height:  |  Size: 358 KiB

Before After
Before After

18
hack/README.md Executable file
View file

@ -0,0 +1,18 @@
## `hack/`
This directory provides scripts for building and pushing Docker images, and tagging new demo
releases.
### env variables
- `TAG` - git release tag / Docker tag.
- `REPO_PREFIX` - Docker repo prefix to push images. Format: `$user/$project`. Resulting images will be of the
format `$user/$project/$svcname:$tag` (where `svcname` = `adservice`, `cartservice`,
etc.)
### scripts
1. `./make-docker-images.sh`: builds and pushes images to the specified Docker repository.
2. `./make-release-artifacts.sh`: generates a combined YAML file with image $TAG at:
`./release/kubernetes-manifests/demo.yaml`.
3. `./make-release.sh`: runs scripts 1 and 2, then runs `git tag` / pushes updated manifests to master.

41
hack/make-docker-images.sh Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env bash
# Copyright 2019 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.
# Builds and pushes docker image for each demo microservice.
set -euo pipefail
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
log() { echo "$1" >&2; }
TAG="${TAG?TAG env variable must be specified}"
REPO_PREFIX="${REPO_PREFIX?REPO_PREFIX env variable must be specified}"
while IFS= read -d $'\0' -r dir; do
# build image
svcname="$(basename "${dir}")"
image="${REPO_PREFIX}/$svcname:$TAG"
(
cd "${dir}"
log "Building: ${image}"
docker build -t "${image}" .
log "Pushing: ${image}"
docker push "${image}"
)
done < <(find "${SCRIPTDIR}/../src" -mindepth 1 -maxdepth 1 -type d -print0)
log "Successfully built and pushed all images."

73
hack/make-release-artifacts.sh Executable file
View file

@ -0,0 +1,73 @@
#!/usr/bin/env bash
# Copyright 2019 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.
# This script compiles manifest files with the image tags and places them in
# /release/...
set -euo pipefail
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
[[ -n "${DEBUG:-}" ]] && set -x
log() { echo "$1" >&2; }
TAG="${TAG?TAG env variable must be specified}"
REPO_PREFIX="${REPO_PREFIX?REPO_PREFIX env variable must be specified}"
OUT_DIR="${OUT_DIR:-${SCRIPTDIR}/../release}"
read_manifests() {
local dir
dir="$1"
while IFS= read -d $'\0' -r file; do
cat "${file}"
echo "---"
done < <(find "${dir}" -name '*.yaml' -type f -print0)
}
mk_kubernetes_manifests() {
out_manifest="$(read_manifests "${SCRIPTDIR}/../kubernetes-manifests")"
# replace "image" repo, tag for each service
for dir in ./src/*/
do
svcname="$(basename "${dir}")"
image="$REPO_PREFIX/$svcname:$TAG"
pattern="^(\s*)image:\s.*$svcname(.*)(\s*)"
replace="\1image: $image\3"
out_manifest="$(gsed -r "s|$pattern|$replace|g" <(echo "${out_manifest}") )"
done
echo "${out_manifest}"
}
mk_istio_manifests() {
read_manifests "${SCRIPTDIR}/../istio-manifests"
}
main() {
mkdir -p "${OUT_DIR}"
local k8s_manifests_file istio_manifests_file
k8s_manifests_file="${OUT_DIR}/kubernetes-manifests.yaml"
mk_kubernetes_manifests > "${k8s_manifests_file}"
log "Written ${k8s_manifests_file}"
istio_manifests_file="${OUT_DIR}/istio-manifests.yaml"
mk_istio_manifests > "${istio_manifests_file}"
log "Written ${istio_manifests_file}"
}
main

42
hack/make-release.sh Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Copyright 2019 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.
# Creates a new release by 1) building/pushing images, 2) injecting tag into YAML,
# 3) creating a new git tag, and 4) pushing tags/updated YAML to $BRANCH.
set -euo pipefail
log() { echo "$1" >&2; }
fail() { log "$1"; exit 1; }
TAG="${TAG?TAG env variable must be specified}"
REPO_PREFIX="${REPO_PREFIX?REPO_PREFIX env variable must be specified}"
# build and push images
./hack/make-docker-images.sh
# update yaml
./hack/make-release-artifacts.sh
# create git release / push to master
log "Pushing k8s manifests to master..."
git tag "$TAG"
git add release/
git commit --allow-empty -m "Release $TAG"
git push --tags
git push origin master
log "Successfully tagged release $TAG."

View file

@ -31,6 +31,8 @@ spec:
env: env:
- name: PORT - name: PORT
value: "9555" value: "9555"
#- name: JAEGER_SERVICE_ADDR
# value: "jaeger-collector:14268"
resources: resources:
requests: requests:
cpu: 200m cpu: 200m
@ -40,12 +42,12 @@ spec:
memory: 300Mi memory: 300Mi
readinessProbe: readinessProbe:
initialDelaySeconds: 20 initialDelaySeconds: 20
periodSeconds: 5 periodSeconds: 15
exec: exec:
command: ["/bin/grpc_health_probe", "-addr=:9555"] command: ["/bin/grpc_health_probe", "-addr=:9555"]
livenessProbe: livenessProbe:
initialDelaySeconds: 20 initialDelaySeconds: 20
periodSeconds: 5 periodSeconds: 15
exec: exec:
command: ["/bin/grpc_health_probe", "-addr=:9555"] command: ["/bin/grpc_health_probe", "-addr=:9555"]
--- ---

View file

@ -46,6 +46,8 @@ spec:
value: "currencyservice:7000" value: "currencyservice:7000"
- name: CART_SERVICE_ADDR - name: CART_SERVICE_ADDR
value: "cartservice:7070" value: "cartservice:7070"
# - name: JAEGER_SERVICE_ADDR
# value: "jaeger-collector:14268"
resources: resources:
requests: requests:
cpu: 100m cpu: 100m

View file

@ -58,6 +58,8 @@ spec:
value: "checkoutservice:5050" value: "checkoutservice:5050"
- name: AD_SERVICE_ADDR - name: AD_SERVICE_ADDR
value: "adservice:9555" value: "adservice:9555"
# - name: JAEGER_SERVICE_ADDR
# value: "jaeger-collector:14268"
resources: resources:
requests: requests:
cpu: 100m cpu: 100m

View file

@ -34,6 +34,9 @@ spec:
livenessProbe: livenessProbe:
exec: exec:
command: ["/bin/grpc_health_probe", "-addr=:3550"] command: ["/bin/grpc_health_probe", "-addr=:3550"]
# env:
# - name: JAEGER_SERVICE_ADDR
# value: "jaeger-collector:14268"
resources: resources:
requests: requests:
cpu: 100m cpu: 100m

View file

@ -34,6 +34,9 @@ spec:
livenessProbe: livenessProbe:
exec: exec:
command: ["/bin/grpc_health_probe", "-addr=:50051"] command: ["/bin/grpc_health_probe", "-addr=:50051"]
# env:
# - name: JAEGER_SERVICE_ADDR
# value: "jaeger-collector:14268"
resources: resources:
requests: requests:
cpu: 100m cpu: 100m

View file

@ -12,14 +12,14 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
apiVersion: skaffold/v1alpha5 apiVersion: skaffold/v1beta2
kind: Config kind: Config
build: build:
artifacts: artifacts:
# image tags are relative; to specify an image repo (e.g. GCR), you # image tags are relative; to specify an image repo (e.g. GCR), you
# must provide a "default repo" using one of the methods described # must provide a "default repo" using one of the methods described
# here: # here:
# https://github.com/GoogleContainerTools/skaffold/blob/master/docs/concepts.adoc#2-push # https://skaffold.dev/docs/concepts/#image-repository-handling
- image: emailservice - image: emailservice
context: src/emailservice context: src/emailservice
- image: productcatalogservice - image: productcatalogservice

View file

@ -10,12 +10,14 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3' classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3'
classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.7.1"
} }
} }
apply plugin: 'idea' apply plugin: 'idea'
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'com.google.protobuf' apply plugin: 'com.google.protobuf'
apply plugin: 'com.github.sherter.google-java-format'
repositories { repositories {
mavenCentral() mavenCentral()
@ -23,12 +25,11 @@ repositories {
} }
group = "adservice" group = "adservice"
version = "0.1.0-SNAPSHOT" // CURRENT_OPENCENSUS_VERSION version = "0.1.0-SNAPSHOT"
def opencensusVersion = "0.17.0" // LATEST_OPENCENSUS_RELEASE_VERSION def opencensusVersion = "0.18.0"
def grpcVersion = "1.15.0" // CURRENT_GRPC_VERSION def grpcVersion = "1.17.0"
def jacksonVersion = "2.9.6" def jacksonVersion = "2.9.6"
def prometheusVersion = "0.3.0"
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
sourceCompatibility = '1.8' sourceCompatibility = '1.8'
@ -44,8 +45,10 @@ dependencies {
if (speed) { if (speed) {
compile fileTree(dir: offlineCompile, include: '*.jar') compile fileTree(dir: offlineCompile, include: '*.jar')
} else { } else {
compile "com.google.api.grpc:proto-google-common-protos:1.11.0", compile "com.google.api.grpc:proto-google-common-protos:1.12.0",
"io.opencensus:opencensus-exporter-stats-prometheus:${opencensusVersion}", "io.opencensus:opencensus-api:${opencensusVersion}",
"io.opencensus:opencensus-contrib-grpc-util:${opencensusVersion}",
"io.opencensus:opencensus-exporter-trace-jaeger:${opencensusVersion}",
"io.opencensus:opencensus-exporter-stats-stackdriver:${opencensusVersion}", "io.opencensus:opencensus-exporter-stats-stackdriver:${opencensusVersion}",
"io.opencensus:opencensus-exporter-trace-stackdriver:${opencensusVersion}", "io.opencensus:opencensus-exporter-trace-stackdriver:${opencensusVersion}",
"io.opencensus:opencensus-exporter-trace-logging:${opencensusVersion}", "io.opencensus:opencensus-exporter-trace-logging:${opencensusVersion}",
@ -53,7 +56,6 @@ dependencies {
"io.grpc:grpc-stub:${grpcVersion}", "io.grpc:grpc-stub:${grpcVersion}",
"io.grpc:grpc-netty:${grpcVersion}", "io.grpc:grpc-netty:${grpcVersion}",
"io.grpc:grpc-services:${grpcVersion}", "io.grpc:grpc-services:${grpcVersion}",
"io.prometheus:simpleclient_httpserver:${prometheusVersion}",
"org.apache.logging.log4j:log4j-core:2.11.1" "org.apache.logging.log4j:log4j-core:2.11.1"
runtime "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}", runtime "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}",
@ -81,6 +83,10 @@ protobuf {
} }
} }
googleJavaFormat {
toolVersion '1.7'
}
// Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code. // Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code.
sourceSets { sourceSets {
main { main {

View file

@ -16,8 +16,8 @@
package hipstershop; package hipstershop;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import hipstershop.Demo.Ad; import hipstershop.Demo.Ad;
import hipstershop.Demo.AdRequest; import hipstershop.Demo.AdRequest;
@ -26,50 +26,50 @@ import io.grpc.Server;
import io.grpc.ServerBuilder; import io.grpc.ServerBuilder;
import io.grpc.StatusRuntimeException; import io.grpc.StatusRuntimeException;
import io.grpc.health.v1.HealthCheckResponse.ServingStatus; import io.grpc.health.v1.HealthCheckResponse.ServingStatus;
import io.grpc.stub.StreamObserver;
import io.grpc.services.*; import io.grpc.services.*;
import io.grpc.stub.StreamObserver;
import io.opencensus.common.Duration; import io.opencensus.common.Duration;
import io.opencensus.common.Scope;
import io.opencensus.contrib.grpc.metrics.RpcViews; 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.StackdriverStatsConfiguration;
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter;
import io.opencensus.exporter.trace.jaeger.JaegerTraceExporter;
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration; import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration;
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter; import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter;
import io.opencensus.trace.AttributeValue; import io.opencensus.trace.AttributeValue;
import io.opencensus.trace.Span; import io.opencensus.trace.Span;
import io.opencensus.trace.SpanBuilder;
import io.opencensus.trace.Tracer; import io.opencensus.trace.Tracer;
import io.opencensus.trace.Tracing; import io.opencensus.trace.Tracing;
import io.opencensus.trace.samplers.Samplers;
import java.io.IOException; import java.io.IOException;
import java.util.Collection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public final class AdService {
public class AdService {
private static final Logger logger = LogManager.getLogger(AdService.class); private static final Logger logger = LogManager.getLogger(AdService.class);
private static final Tracer tracer = Tracing.getTracer(); private static final Tracer tracer = Tracing.getTracer();
private int MAX_ADS_TO_SERVE = 2; private static int MAX_ADS_TO_SERVE = 2;
private Server server; private Server server;
private HealthStatusManager healthMgr; private HealthStatusManager healthMgr;
static final AdService service = new AdService(); private static final AdService service = new AdService();
private void start() throws IOException { private void start() throws IOException {
int port = Integer.parseInt(System.getenv("PORT")); int port = Integer.parseInt(System.getenv("PORT"));
healthMgr = new HealthStatusManager(); healthMgr = new HealthStatusManager();
server = ServerBuilder.forPort(port).addService(new AdServiceImpl()) server =
.addService(healthMgr.getHealthService()).build().start(); ServerBuilder.forPort(port)
.addService(new AdServiceImpl())
.addService(healthMgr.getHealthService())
.build()
.start();
logger.info("Ad Service started, listening on " + port); logger.info("Ad Service started, listening on " + port);
Runtime.getRuntime() Runtime.getRuntime()
.addShutdownHook( .addShutdownHook(
@ -92,26 +92,20 @@ public class AdService {
} }
} }
static class AdServiceImpl extends hipstershop.AdServiceGrpc.AdServiceImplBase { private static class AdServiceImpl extends hipstershop.AdServiceGrpc.AdServiceImplBase {
/** /**
* Retrieves ads based on context provided in the request {@code AdRequest}. * Retrieves ads based on context provided in the request {@code AdRequest}.
* *
* @param req the request containing context. * @param req the request containing context.
* @param responseObserver the stream observer which gets notified with the value of * @param responseObserver the stream observer which gets notified with the value of {@code
* {@code AdResponse} * AdResponse}
*/ */
@Override @Override
public void getAds(AdRequest req, StreamObserver<AdResponse> responseObserver) { public void getAds(AdRequest req, StreamObserver<AdResponse> responseObserver) {
AdService service = AdService.getInstance(); AdService service = AdService.getInstance();
Span parentSpan = tracer.getCurrentSpan(); Span span = tracer.getCurrentSpan();
SpanBuilder spanBuilder = try {
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")); span.putAttribute("method", AttributeValue.stringAttributeValue("getAds"));
List<Ad> allAds = new ArrayList<>(); List<Ad> allAds = new ArrayList<>();
logger.info("received ad request (context_words=" + req.getContextKeysList() + ")"); logger.info("received ad request (context_words=" + req.getContextKeysList() + ")");
@ -141,29 +135,29 @@ public class AdService {
responseObserver.onCompleted(); responseObserver.onCompleted();
} catch (StatusRuntimeException e) { } catch (StatusRuntimeException e) {
logger.log(Level.WARN, "GetAds Failed", e.getStatus()); logger.log(Level.WARN, "GetAds Failed", e.getStatus());
return; responseObserver.onError(e);
} }
} }
} }
static final ImmutableListMultimap<String, Ad> adsMap = createAdsMap(); private static final ImmutableListMultimap<String, Ad> adsMap = createAdsMap();
Collection<Ad> getAdsByCategory(String category) { private Collection<Ad> getAdsByCategory(String category) {
return adsMap.get(category); return adsMap.get(category);
} }
private static final Random random = new Random(); private static final Random random = new Random();
public List<Ad> getRandomAds() { private List<Ad> getRandomAds() {
List<Ad> ads = new ArrayList<>(MAX_ADS_TO_SERVE); List<Ad> ads = new ArrayList<>(MAX_ADS_TO_SERVE);
Collection<Ad> allAds = adsMap.values(); Collection<Ad> allAds = adsMap.values();
for (int i=0; i<MAX_ADS_TO_SERVE; i++) { for (int i = 0; i < MAX_ADS_TO_SERVE; i++) {
ads.add(Iterables.get(allAds, random.nextInt(allAds.size()))); ads.add(Iterables.get(allAds, random.nextInt(allAds.size())));
} }
return ads; return ads;
} }
public static AdService getInstance() { private static AdService getInstance() {
return service; return service;
} }
@ -174,21 +168,42 @@ public class AdService {
} }
} }
static ImmutableListMultimap<String, Ad> createAdsMap() { private static ImmutableListMultimap<String, Ad> createAdsMap() {
Ad camera = Ad.newBuilder().setRedirectUrl("/product/2ZYFJ3GM2N") Ad camera =
.setText("Film camera for sale. 50% off.").build(); Ad.newBuilder()
Ad lens = Ad.newBuilder().setRedirectUrl("/product/66VCHSJNUP") .setRedirectUrl("/product/2ZYFJ3GM2N")
.setText("Vintage camera lens for sale. 20% off.").build(); .setText("Film camera for sale. 50% off.")
Ad recordPlayer = Ad.newBuilder().setRedirectUrl("/product/0PUK6V6EV0") .build();
.setText("Vintage record player for sale. 30% off.").build(); Ad lens =
Ad bike = Ad.newBuilder().setRedirectUrl("/product/9SIQT8TOJO") Ad.newBuilder()
.setText("City Bike for sale. 10% off.").build(); .setRedirectUrl("/product/66VCHSJNUP")
Ad baristaKit = Ad.newBuilder().setRedirectUrl("/product/1YMWWN1N4O") .setText("Vintage camera lens for sale. 20% off.")
.setText("Home Barista kitchen kit for sale. Buy one, get second kit for free").build(); .build();
Ad airPlant = Ad.newBuilder().setRedirectUrl("/product/6E92ZMYYFZ") Ad recordPlayer =
.setText("Air plants for sale. Buy two, get third one for free").build(); Ad.newBuilder()
Ad terrarium = Ad.newBuilder().setRedirectUrl("/product/L9ECAV7KIM") .setRedirectUrl("/product/0PUK6V6EV0")
.setText("Terrarium for sale. Buy one, get second one for free").build(); .setText("Vintage record player for sale. 30% off.")
.build();
Ad bike =
Ad.newBuilder()
.setRedirectUrl("/product/9SIQT8TOJO")
.setText("City Bike for sale. 10% off.")
.build();
Ad baristaKit =
Ad.newBuilder()
.setRedirectUrl("/product/1YMWWN1N4O")
.setText("Home Barista kitchen kit for sale. Buy one, get second kit for free")
.build();
Ad airPlant =
Ad.newBuilder()
.setRedirectUrl("/product/6E92ZMYYFZ")
.setText("Air plants for sale. Buy two, get third one for free")
.build();
Ad terrarium =
Ad.newBuilder()
.setRedirectUrl("/product/L9ECAV7KIM")
.setText("Terrarium for sale. Buy one, get second one for free")
.build();
return ImmutableListMultimap.<String, Ad>builder() return ImmutableListMultimap.<String, Ad>builder()
.putAll("photography", camera, lens) .putAll("photography", camera, lens)
.putAll("vintage", camera, lens, recordPlayer) .putAll("vintage", camera, lens, recordPlayer)
@ -198,20 +213,15 @@ public class AdService {
.build(); .build();
} }
public static void initStackdriver() { private static void initStackdriver() {
logger.info("Initialize StackDriver"); logger.info("Initialize StackDriver");
// Registers all RPC views.
RpcViews.registerAllViews();
// Registers logging trace exporter.
LoggingTraceExporter.register();
long sleepTime = 10; /* seconds */ long sleepTime = 10; /* seconds */
int maxAttempts = 5; int maxAttempts = 5;
boolean statsExporterRegistered = false; boolean statsExporterRegistered = false;
boolean traceExporterRegistered = false; boolean traceExporterRegistered = false;
for (int i=0; i<maxAttempts; i++) { for (int i = 0; i < maxAttempts; i++) {
try { try {
if (!traceExporterRegistered) { if (!traceExporterRegistered) {
StackdriverTraceExporter.createAndRegister( StackdriverTraceExporter.createAndRegister(
@ -226,10 +236,12 @@ public class AdService {
statsExporterRegistered = true; statsExporterRegistered = true;
} }
} catch (Exception e) { } catch (Exception e) {
if (i==(maxAttempts-1)) { if (i == (maxAttempts - 1)) {
logger.log(Level.WARN, "Failed to register Stackdriver Exporter." + logger.log(
" Tracing and Stats data will not reported to Stackdriver. Error message: " + e Level.WARN,
.toString()); "Failed to register Stackdriver Exporter."
+ " Tracing and Stats data will not reported to Stackdriver. Error message: "
+ e.toString());
} else { } else {
logger.info("Attempt to register Stackdriver Exporter in " + sleepTime + " seconds "); logger.info("Attempt to register Stackdriver Exporter in " + sleepTime + " seconds ");
try { try {
@ -243,18 +255,33 @@ public class AdService {
logger.info("StackDriver initialization complete."); logger.info("StackDriver initialization complete.");
} }
private static void initJaeger() {
String jaegerAddr = System.getenv("JAEGER_SERVICE_ADDR");
if (jaegerAddr != null && !jaegerAddr.isEmpty()) {
String jaegerUrl = String.format("http://%s/api/traces", jaegerAddr);
// Register Jaeger Tracing.
JaegerTraceExporter.createAndRegister(jaegerUrl, "adservice");
logger.info("Jaeger initialization complete.");
} else {
logger.info("Jaeger initialization disabled.");
}
}
/** Main launches the server from the command line. */ /** Main launches the server from the command line. */
public static void main(String[] args) throws IOException, InterruptedException { public static void main(String[] args) throws IOException, InterruptedException {
// Add final keyword to pass checkStyle. // Registers all RPC views.
RpcViews.registerAllGrpcViews();
new Thread( new Runnable() { new Thread(
public void run(){ new Runnable() {
initStackdriver(); public void run() {
} initStackdriver();
}).start(); }
})
.start();
// Register Prometheus exporters and export metrics to a Prometheus HTTPServer. // Register Jaeger
PrometheusStatsCollector.createAndRegister(); initJaeger();
// Start the RPC server. You shouldn't see any output from gRPC before this. // Start the RPC server. You shouldn't see any output from gRPC before this.
logger.info("AdService starting."); logger.info("AdService starting.");
@ -262,4 +289,4 @@ public class AdService {
service.start(); service.start();
service.blockUntilShutdown(); service.blockUntilShutdown();
} }
} }

View file

@ -16,7 +16,6 @@
package hipstershop; package hipstershop;
import hipstershop.Demo.Ad; import hipstershop.Demo.Ad;
import hipstershop.Demo.AdRequest; import hipstershop.Demo.AdRequest;
import hipstershop.Demo.AdResponse; import hipstershop.Demo.AdResponse;
@ -26,34 +25,32 @@ import io.grpc.StatusRuntimeException;
import io.opencensus.common.Duration; import io.opencensus.common.Duration;
import io.opencensus.common.Scope; import io.opencensus.common.Scope;
import io.opencensus.contrib.grpc.metrics.RpcViews; import io.opencensus.contrib.grpc.metrics.RpcViews;
import io.opencensus.exporter.trace.logging.LoggingTraceExporter; import io.opencensus.contrib.grpc.util.StatusConverter;
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration; import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration;
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter; import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter;
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration; import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration;
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter; import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter;
import io.opencensus.trace.SpanBuilder; import io.opencensus.trace.Span;
import io.opencensus.trace.Status.CanonicalCode;
import io.opencensus.trace.Tracer; import io.opencensus.trace.Tracer;
import io.opencensus.trace.Tracing; import io.opencensus.trace.Tracing;
import io.opencensus.trace.samplers.Samplers; import io.opencensus.trace.samplers.Samplers;
import java.io.IOException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/** A simple client that requests ads from the Ads Service. */ /** A simple client that requests ads from the Ads Service. */
public class AdServiceClient { public class AdServiceClient {
private static final Logger logger = LogManager.getLogger(AdServiceClient.class);
private static final Logger logger = LogManager.getLogger(AdServiceClient.class);
private static final Tracer tracer = Tracing.getTracer(); private static final Tracer tracer = Tracing.getTracer();
private final ManagedChannel channel; private final ManagedChannel channel;
private final hipstershop.AdServiceGrpc.AdServiceBlockingStub blockingStub; private final hipstershop.AdServiceGrpc.AdServiceBlockingStub blockingStub;
/** Construct client connecting to Ad Service at {@code host:port}. */ /** Construct client connecting to Ad Service at {@code host:port}. */
public AdServiceClient(String host, int port) { private AdServiceClient(String host, int port) {
this( this(
ManagedChannelBuilder.forAddress(host, port) ManagedChannelBuilder.forAddress(host, port)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
@ -63,12 +60,12 @@ public class AdServiceClient {
} }
/** Construct client for accessing RouteGuide server using the existing channel. */ /** Construct client for accessing RouteGuide server using the existing channel. */
AdServiceClient(ManagedChannel channel) { private AdServiceClient(ManagedChannel channel) {
this.channel = channel; this.channel = channel;
blockingStub = hipstershop.AdServiceGrpc.newBlockingStub(channel); blockingStub = hipstershop.AdServiceGrpc.newBlockingStub(channel);
} }
public void shutdown() throws InterruptedException { private void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
} }
@ -78,28 +75,29 @@ public class AdServiceClient {
AdRequest request = AdRequest.newBuilder().addContextKeys(contextKey).build(); AdRequest request = AdRequest.newBuilder().addContextKeys(contextKey).build();
AdResponse response; AdResponse response;
SpanBuilder spanBuilder = Span span =
tracer.spanBuilder("AdsClient").setRecordEvents(true).setSampler(Samplers.alwaysSample()); tracer
try (Scope scope = spanBuilder.startScopedSpan()) { .spanBuilder("AdsClient")
.setRecordEvents(true)
.setSampler(Samplers.alwaysSample())
.startSpan();
try (Scope scope = tracer.withSpan(span)) {
tracer.getCurrentSpan().addAnnotation("Getting Ads"); tracer.getCurrentSpan().addAnnotation("Getting Ads");
response = blockingStub.getAds(request); response = blockingStub.getAds(request);
tracer.getCurrentSpan().addAnnotation("Received response from Ads Service."); tracer.getCurrentSpan().addAnnotation("Received response from Ads Service.");
} catch (StatusRuntimeException e) { } catch (StatusRuntimeException e) {
tracer tracer.getCurrentSpan().setStatus(StatusConverter.fromGrpcStatus(e.getStatus()));
.getCurrentSpan() logger.log(Level.WARN, "RPC failed: " + e.getStatus());
.setStatus(
CanonicalCode.valueOf(e.getStatus().getCode().name())
.toStatus()
.withDescription(e.getMessage()));
logger.log(Level.WARN, "RPC failed: {0}", e.getStatus());
return; return;
} finally {
span.end();
} }
for(Ad ads: response.getAdsList()) { for (Ad ads : response.getAdsList()) {
logger.info("Ads: " + ads.getText()); logger.info("Ads: " + ads.getText());
} }
} }
static int getPortOrDefaultFromArgs(String[] args, int index, int defaultPort) { private static int getPortOrDefaultFromArgs(String[] args, int index, int defaultPort) {
int portNumber = defaultPort; int portNumber = defaultPort;
if (index < args.length) { if (index < args.length) {
try { try {
@ -112,8 +110,7 @@ public class AdServiceClient {
return portNumber; return portNumber;
} }
private static String getStringOrDefaultFromArgs(
static String getStringOrDefaultFromArgs(
String[] args, int index, @Nullable String defaultString) { String[] args, int index, @Nullable String defaultString) {
String s = defaultString; String s = defaultString;
if (index < args.length) { if (index < args.length) {
@ -126,54 +123,46 @@ public class AdServiceClient {
* Ads Service Client main. If provided, the first element of {@code args} is the context key to * Ads Service Client main. If provided, the first element of {@code args} is the context key to
* get the ads from the Ads Service * get the ads from the Ads Service
*/ */
public static void main(String[] args) throws IOException, InterruptedException { public static void main(String[] args) throws InterruptedException {
// Add final keyword to pass checkStyle. // Add final keyword to pass checkStyle.
final String contextKeys = getStringOrDefaultFromArgs(args, 0, "camera"); final String contextKeys = getStringOrDefaultFromArgs(args, 0, "camera");
final String host = getStringOrDefaultFromArgs(args, 1, "localhost"); final String host = getStringOrDefaultFromArgs(args, 1, "localhost");
final int serverPort = getPortOrDefaultFromArgs(args, 2, 9555); 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. // Registers all RPC views.
RpcViews.registerAllViews(); RpcViews.registerAllGrpcViews();
// Registers logging trace exporter.
LoggingTraceExporter.register();
// Registers Stackdriver exporters. // Registers Stackdriver exporters.
if (cloudProjectId != null) { long sleepTime = 10; /* seconds */
long sleepTime = 10; /* seconds */ int maxAttempts = 3;
int maxAttempts = 3;
for (int i=0; i<maxAttempts; i++) { for (int i = 0; i < maxAttempts; i++) {
try { try {
StackdriverTraceExporter.createAndRegister( StackdriverTraceExporter.createAndRegister(StackdriverTraceConfiguration.builder().build());
StackdriverTraceConfiguration.builder().setProjectId(cloudProjectId).build()); StackdriverStatsExporter.createAndRegister(
StackdriverStatsExporter.createAndRegister( StackdriverStatsConfiguration.builder()
StackdriverStatsConfiguration.builder() .setExportInterval(Duration.create(15, 0))
.setProjectId(cloudProjectId) .build());
.setExportInterval(Duration.create(15, 0)) } catch (Exception e) {
.build()); if (i == (maxAttempts - 1)) {
} catch (Exception e) { logger.log(
if (i==(maxAttempts-1)) { Level.WARN,
logger.log(Level.WARN, "Failed to register Stackdriver Exporter." + "Failed to register Stackdriver Exporter."
" Tracing and Stats data will not reported to Stackdriver. Error message: " + e + " Tracing and Stats data will not reported to Stackdriver. Error message: "
.toString()); + e.toString());
} else { } else {
logger.info("Attempt to register Stackdriver Exporter in " + sleepTime + " seconds"); logger.info("Attempt to register Stackdriver Exporter in " + sleepTime + " seconds");
try { try {
Thread.sleep(TimeUnit.SECONDS.toMillis(sleepTime)); Thread.sleep(TimeUnit.SECONDS.toMillis(sleepTime));
} catch (Exception se) { } catch (Exception se) {
logger.log(Level.WARN, "Exception while sleeping" + e.toString()); logger.log(Level.WARN, "Exception while sleeping" + e.toString());
}
} }
} }
} }
} }
// Register Prometheus exporters and export metrics to a Prometheus HTTPServer. // Register Prometheus exporters and export metrics to a Prometheus HTTPServer.
//PrometheusStatsCollector.createAndRegister(); // PrometheusStatsCollector.createAndRegister();
AdServiceClient client = new AdServiceClient(host, serverPort); AdServiceClient client = new AdServiceClient(host, serverPort);
try { try {

View file

@ -3,12 +3,14 @@
<Appenders> <Appenders>
<Console name="STDOUT" target="SYSTEM_OUT"> <Console name="STDOUT" target="SYSTEM_OUT">
<!-- This is a JSON format that can be read by the Stackdriver Logging agent. The trace and <!-- This is a JSON format that can be read by the Stackdriver Logging agent. The trace ID,
span IDs are interpreted by Stackdriver, and "traceSampled" is a custom field. --> span ID, and timestamp are interpreted by Stackdriver, and "traceSampled" is a custom
field. -->
<JsonLayout compact="true" eventEol="true"> <JsonLayout compact="true" eventEol="true">
<KeyValuePair key="logging.googleapis.com/trace" value="$${ctx:traceId}"/> <KeyValuePair key="logging.googleapis.com/trace" value="$${ctx:traceId}"/>
<KeyValuePair key="logging.googleapis.com/spanId" value="$${ctx:spanId}"/> <KeyValuePair key="logging.googleapis.com/spanId" value="$${ctx:spanId}"/>
<KeyValuePair key="traceSampled" value="$${ctx:traceSampled}"/> <KeyValuePair key="traceSampled" value="$${ctx:traceSampled}"/>
<KeyValuePair key="time" value="$${date:yyyy-MM-dd}T$${date:HH:mm:ss.SSS}Z"/>
</JsonLayout> </JsonLayout>
</Console> </Console>

View file

@ -2,27 +2,49 @@
[[projects]] [[projects]]
digest = "1:467af0aad47996b25b838d6f14c8371123a8a76ec239020a6c5894e1f8f60272"
name = "cloud.google.com/go" name = "cloud.google.com/go"
packages = [ packages = [
"compute/metadata", "compute/metadata",
"internal/version", "internal/version",
"monitoring/apiv3", "monitoring/apiv3",
"profiler", "profiler",
"trace/apiv2" "trace/apiv2",
] ]
pruneopts = "UT"
revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad" revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad"
version = "v0.27.0" version = "v0.27.0"
[[projects]] [[projects]]
digest = "1:4b96dcd8534bc6450a922bd16a76360ba3381f0d1daf40abbaec91c053fbfeb5"
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"
packages = [ packages = ["."]
".", pruneopts = "UT"
"propagation"
]
revision = "37aa2801fbf0205003e15636096ebf0373510288" revision = "37aa2801fbf0205003e15636096ebf0373510288"
version = "v0.5.0" version = "v0.5.0"
[[projects]] [[projects]]
branch = "master"
digest = "1:1d8f3cb93c42c5652bb509fde29ecdd1feede9334e355e8bbdc0f9f95b40c254"
name = "git.apache.org/thrift.git"
packages = ["lib/go/thrift"]
pruneopts = "UT"
revision = "a5df39032ca206e2e6a9ec975147e81746d9a255"
source = "github.com/apache/thrift"
[[projects]]
branch = "master"
digest = "1:f6bdf3d8d3cbb2f98d3ebaa66b3ac25166a06830027ece7d592d9ea09dedf504"
name = "github.com/GoogleCloudPlatform/microservices-demo"
packages = [
"src/checkoutservice/genproto",
"src/checkoutservice/money",
]
pruneopts = "UT"
revision = "33ca3b63d82698035ffc1230dcb650885a005197"
[[projects]]
digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a"
name = "github.com/golang/protobuf" name = "github.com/golang/protobuf"
packages = [ packages = [
"proto", "proto",
@ -33,41 +55,62 @@
"ptypes/empty", "ptypes/empty",
"ptypes/struct", "ptypes/struct",
"ptypes/timestamp", "ptypes/timestamp",
"ptypes/wrappers" "ptypes/wrappers",
] ]
pruneopts = "UT"
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0" version = "v1.2.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:089d56c0adb79140365b5c86815ce97233986da6f3a525c6b706773e4b83876f"
name = "github.com/google/pprof" name = "github.com/google/pprof"
packages = ["profile"] packages = ["profile"]
revision = "e027b505a088ac3c68c339a1d7ce7724bf34538b" pruneopts = "UT"
revision = "985cf9b4fdd2b479e4563ec57352005f69d5f9f6"
[[projects]] [[projects]]
digest = "1:236d7e1bdb50d8f68559af37dbcf9d142d56b431c9b2176d41e2a009b664cda8"
name = "github.com/google/uuid" name = "github.com/google/uuid"
packages = ["."] packages = ["."]
revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494" pruneopts = "UT"
version = "v1.0.0" revision = "9b3b1e0f5f99ae461456d768e7d301a7acdaa2d8"
version = "v1.1.0"
[[projects]] [[projects]]
digest = "1:cd9864c6366515827a759931746738ede6079faa08df9c584596370d6add135c"
name = "github.com/googleapis/gax-go" name = "github.com/googleapis/gax-go"
packages = ["."] packages = [
revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f" ".",
version = "v2.0.0" "v2",
]
pruneopts = "UT"
revision = "c8a15bac9b9fe955bd9f900272f9a306465d28cf"
version = "v2.0.3"
[[projects]] [[projects]]
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc" digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
version = "v1.0.1"
[[projects]]
digest = "1:87c2e02fb01c27060ccc5ba7c5a407cc91147726f8f40b70cceeedbc52b1f3a8"
name = "github.com/sirupsen/logrus" name = "github.com/sirupsen/logrus"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "3e01752db0189b9157070a0e1668a620f9a85da2" revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5"
version = "v1.0.6" version = "v1.3.0"
[[projects]] [[projects]]
digest = "1:a5154dfd6b37bef5a3eab759e13296348e639dc8c7604f538368167782b08ccd"
name = "go.opencensus.io" name = "go.opencensus.io"
packages = [ packages = [
".", ".",
"exporter/jaeger",
"exporter/jaeger/internal/gen-go/jaeger",
"internal", "internal",
"internal/tagencoding", "internal/tagencoding",
"plugin/ocgrpc", "plugin/ocgrpc",
@ -80,21 +123,23 @@
"trace", "trace",
"trace/internal", "trace/internal",
"trace/propagation", "trace/propagation",
"trace/tracestate" "trace/tracestate",
] ]
pruneopts = "UT"
revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89" revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89"
version = "v0.16.0" version = "v0.16.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8" digest = "1:38f553aff0273ad6f367cb0a0f8b6eecbaef8dc6cb8b50e57b6a81c1d5b1e332"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = ["ssh/terminal"] packages = ["ssh/terminal"]
pruneopts = "UT" pruneopts = "UT"
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c" revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:8ecb828bb550a8c6b7d75b8261a42c369461311616ebe5451966d067f5f993bf"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = [ packages = [
"context", "context",
@ -104,35 +149,46 @@
"http2/hpack", "http2/hpack",
"idna", "idna",
"internal/timeseries", "internal/timeseries",
"trace" "trace",
] ]
revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2" pruneopts = "UT"
revision = "1e06a53dbb7e2ed46e91183f219db23c6943c532"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:23443edff0740e348959763085df98400dcfd85528d7771bb0ce9f5f2754ff4a"
name = "golang.org/x/oauth2" name = "golang.org/x/oauth2"
packages = [ packages = [
".", ".",
"google", "google",
"internal", "internal",
"jws", "jws",
"jwt" "jwt",
] ]
revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9" pruneopts = "UT"
revision = "d668ce993890a79bda886613ee587a69dd5da7a6"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:75515eedc0dc2cb0b40372008b616fa2841d831c63eedd403285ff286c593295"
name = "golang.org/x/sync" name = "golang.org/x/sync"
packages = ["semaphore"] packages = ["semaphore"]
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" pruneopts = "UT"
revision = "37e7f081c4d4c64e13b10787722085407fe5d15f"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:12ef3ef293a3a3930a82e5f38a3c45a1b03a9ed72dedc192d90e89d59b1f13a5"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix"] packages = [
revision = "1561086e645b2809fb9f8a1e2a38160bf8d53bf4" "unix",
"windows",
]
pruneopts = "UT"
revision = "7fbe1cd0fcc20051e1fcb87fbabec4a1bacaaeba"
[[projects]] [[projects]]
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
name = "golang.org/x/text" name = "golang.org/x/text"
packages = [ packages = [
"collate", "collate",
@ -148,13 +204,15 @@
"unicode/bidi", "unicode/bidi",
"unicode/cldr", "unicode/cldr",
"unicode/norm", "unicode/norm",
"unicode/rangetable" "unicode/rangetable",
] ]
pruneopts = "UT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0" version = "v0.3.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:b74a0ae8b7755bf9cdadead4dea674d76517cd2fea7bd482a6a46bb6b3ce085b"
name = "google.golang.org/api" name = "google.golang.org/api"
packages = [ packages = [
"googleapi/transport", "googleapi/transport",
@ -164,11 +222,14 @@
"support/bundler", "support/bundler",
"transport", "transport",
"transport/grpc", "transport/grpc",
"transport/http" "transport/http",
"transport/http/internal/propagation",
] ]
revision = "19ff8768a5c0b8e46ea281065664787eefc24121" pruneopts = "UT"
revision = "032faecc3e7e2c445ec37a1b1ec4e5a3016d96f2"
[[projects]] [[projects]]
digest = "1:c4eaa5f79d36f76ef4bd0c4f96e36bc1b7b5a359528d1267f0cb7a5d58b7b5bb"
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
packages = [ packages = [
".", ".",
@ -182,13 +243,15 @@
"internal/socket", "internal/socket",
"internal/urlfetch", "internal/urlfetch",
"socket", "socket",
"urlfetch" "urlfetch",
] ]
revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06" pruneopts = "UT"
version = "v1.2.0" revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
version = "v1.4.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:3552e7267a98c605e6cbfe6b03c34589265ab72e6078b95fb2e10e0cb44f5cc8"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = [ packages = [
"googleapis/api/annotations", "googleapis/api/annotations",
@ -201,11 +264,13 @@
"googleapis/monitoring/v3", "googleapis/monitoring/v3",
"googleapis/rpc/errdetails", "googleapis/rpc/errdetails",
"googleapis/rpc/status", "googleapis/rpc/status",
"protobuf/field_mask" "protobuf/field_mask",
] ]
revision = "c3f76f3b92d1ffa4c58a9ff842a58b8877655e0f" pruneopts = "UT"
revision = "ae2f86662275e140f395167f1dab7081a5bd5fa8"
[[projects]] [[projects]]
digest = "1:6497ab07ec89179db8d5a563d33635be04ceffaa29007a3ae74b9f15f4d3068e"
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
packages = [ packages = [
".", ".",
@ -235,14 +300,32 @@
"resolver/passthrough", "resolver/passthrough",
"stats", "stats",
"status", "status",
"tap" "tap",
] ]
pruneopts = "UT"
revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
version = "v1.14.0" version = "v1.14.0"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "0c103e5e32d8ecdd70048b6d91e02b910e30bad54f06b230a9664f585433a669" input-imports = [
"cloud.google.com/go/profiler",
"contrib.go.opencensus.io/exporter/stackdriver",
"github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/genproto",
"github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/money",
"github.com/golang/protobuf/proto",
"github.com/google/uuid",
"github.com/sirupsen/logrus",
"go.opencensus.io/exporter/jaeger",
"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/health/grpc_health_v1",
"google.golang.org/grpc/status",
]
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -25,6 +25,7 @@ import (
"contrib.go.opencensus.io/exporter/stackdriver" "contrib.go.opencensus.io/exporter/stackdriver"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/exporter/jaeger"
"go.opencensus.io/plugin/ocgrpc" "go.opencensus.io/plugin/ocgrpc"
"go.opencensus.io/stats/view" "go.opencensus.io/stats/view"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@ -98,6 +99,28 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
func initJaegerTracing() {
svcAddr := os.Getenv("JAEGER_SERVICE_ADDR")
if svcAddr == "" {
log.Info("jaeger initialization disabled.")
return
}
// Register the Jaeger exporter to be able to retrieve
// the collected spans.
exporter, err := jaeger.NewExporter(jaeger.Options{
Endpoint: fmt.Sprintf("http://%s", svcAddr),
Process: jaeger.Process{
ServiceName: "checkoutservice",
},
})
if err != nil {
log.Fatal(err)
}
trace.RegisterExporter(exporter)
log.Info("jaeger initialization completed.")
}
func initStats(exporter *stackdriver.Exporter) { func initStats(exporter *stackdriver.Exporter) {
view.SetReportingPeriod(60 * time.Second) view.SetReportingPeriod(60 * time.Second)
view.RegisterExporter(exporter) view.RegisterExporter(exporter)
@ -108,7 +131,7 @@ func initStats(exporter *stackdriver.Exporter) {
} }
} }
func initTracing() { func initStackDriverTracing() {
// TODO(ahmetb) this method is duplicated in other microservices using Go // TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages. // since they are not sharing packages.
for i := 1; i <= 3; i++ { for i := 1; i <= 3; i++ {
@ -117,7 +140,6 @@ func initTracing() {
log.Infof("failed to initialize stackdriver exporter: %+v", err) log.Infof("failed to initialize stackdriver exporter: %+v", err)
} else { } else {
trace.RegisterExporter(exporter) trace.RegisterExporter(exporter)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
log.Info("registered stackdriver tracing") log.Info("registered stackdriver tracing")
// Register the views to collect server stats. // Register the views to collect server stats.
@ -131,6 +153,11 @@ func initTracing() {
log.Warn("could not initialize stackdriver exporter after retrying, giving up") log.Warn("could not initialize stackdriver exporter after retrying, giving up")
} }
func initTracing() {
initJaegerTracing()
initStackDriverTracing()
}
func initProfiling(service, version string) { func initProfiling(service, version string) {
// TODO(ahmetb) this method is duplicated in other microservices using Go // TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages. // since they are not sharing packages.

View file

@ -1,21 +1,7 @@
FROM python:3-alpine as base FROM python:3-slim as base
FROM base as builder FROM base as builder
# gRPC and app deps
RUN apk add --update --no-cache \
gcc \
linux-headers \
make \
musl-dev \
python-dev \
g++ \
# App Deps
cairo-dev \
cairo \
openssl-dev \
gobject-introspection-dev
# get packages # get packages
COPY requirements.txt . COPY requirements.txt .
RUN pip install -r requirements.txt RUN pip install -r requirements.txt
@ -25,6 +11,10 @@ FROM base as final
# Enable unbuffered logging # Enable unbuffered logging
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
RUN apt-get -qq update \
&& apt-get install -y --no-install-recommends \
wget
# Download the grpc health probe # Download the grpc health probe
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
@ -35,9 +25,6 @@ WORKDIR /email_server
# Grab packages from builder # Grab packages from builder
COPY --from=builder /usr/local/lib/python3.7/ /usr/local/lib/python3.7/ COPY --from=builder /usr/local/lib/python3.7/ /usr/local/lib/python3.7/
# Need libstdc++ for grpc
RUN apk add --no-cache libstdc++
# Add the application # Add the application
COPY . . COPY . .

View file

@ -0,0 +1,6 @@
google-api-core==1.6.0
grpcio-health-checking==1.12.1
grpcio==1.16.1
jinja2==2.10
opencensus[stackdriver]==0.1.10
python-json-logger==0.1.9

View file

@ -1,41 +1,29 @@
asn1crypto==0.24.0 #
cachetools==2.1.0 # This file is autogenerated by pip-compile
certifi==2018.8.24 # To update, run:
cffi==1.11.5 #
chardet==3.0.4 # pip-compile --output-file requirements.txt requirements.in
configparser==3.5.0 #
cryptography==2.3.1 cachetools==3.0.0 # via google-auth
entrypoints==0.2.3 certifi==2018.11.29 # via requests
enum34==1.1.6 chardet==3.0.4 # via requests
futures==3.1.1 google-api-core[grpc]==1.6.0
google-api-core==1.6.0 google-auth==1.6.2 # via google-api-core
google-auth==1.6.1 google-cloud-core==0.29.1 # via google-cloud-trace
google-cloud-core==0.29.0 google-cloud-trace==0.20.2 # via opencensus
googleapis-common-protos==1.5.3 googleapis-common-protos==1.5.5 # via google-api-core
grpc-google-iam-v1==0.11.4
grpcio==1.16.1
grpcio-health-checking==1.12.1 grpcio-health-checking==1.12.1
grpcio-tools==1.12.1 grpcio==1.16.1
idna==2.7 idna==2.8 # via requests
ipaddress==1.0.22 jinja2==2.10
jeepney==0.4 markupsafe==1.1.0 # via jinja2
Jinja2==2.10
keyring==15.1.0
keyrings.alt==3.1
MarkupSafe==1.0
opencensus[stackdriver]==0.1.10 opencensus[stackdriver]==0.1.10
protobuf==3.6.1 protobuf==3.6.1 # via google-api-core, googleapis-common-protos, grpcio-health-checking
pyasn1==0.4.4 pyasn1-modules==0.2.3 # via google-auth
pyasn1-modules==0.2.2 pyasn1==0.4.5 # via pyasn1-modules, rsa
pycairo==1.17.1
pycparser==2.19
pycrypto==2.6.1
PyGObject==3.30.1
python-json-logger==0.1.9 python-json-logger==0.1.9
pytz==2018.5 pytz==2018.9 # via google-api-core
pyxdg==0.26 requests==2.21.0 # via google-api-core
requests==2.20.0 rsa==4.0 # via google-auth
rsa==4.0 six==1.12.0 # via google-api-core, google-auth, grpcio, protobuf
SecretStorage==3.1.0 urllib3==1.24.1 # via requests
six==1.11.0
urllib3==1.23

111
src/frontend/Gopkg.lock generated
View file

@ -16,16 +16,33 @@
version = "v0.27.0" version = "v0.27.0"
[[projects]] [[projects]]
digest = "1:9fe70def8f0ceb3d455a0acad9dadd6632287cdbf9c8c2ea50e8dabe2ade40c4" digest = "1:4b96dcd8534bc6450a922bd16a76360ba3381f0d1daf40abbaec91c053fbfeb5"
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"
packages = [ packages = ["."]
".",
"propagation",
]
pruneopts = "UT" pruneopts = "UT"
revision = "37aa2801fbf0205003e15636096ebf0373510288" revision = "37aa2801fbf0205003e15636096ebf0373510288"
version = "v0.5.0" version = "v0.5.0"
[[projects]]
branch = "master"
digest = "1:1d8f3cb93c42c5652bb509fde29ecdd1feede9334e355e8bbdc0f9f95b40c254"
name = "git.apache.org/thrift.git"
packages = ["lib/go/thrift"]
pruneopts = "UT"
revision = "6503043bc42ab96da14c25f3aee2bb4add719774"
source = "github.com/apache/thrift"
[[projects]]
branch = "master"
digest = "1:6cbe7676244a1429f4c22601f799d377a70449469ef636f91d992d719b559ff3"
name = "github.com/GoogleCloudPlatform/microservices-demo"
packages = [
"src/frontend/genproto",
"src/frontend/money",
]
pruneopts = "UT"
revision = "d944092100696aa4a5974ef5c2e710547a824622"
[[projects]] [[projects]]
digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a" digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a"
name = "github.com/golang/protobuf" name = "github.com/golang/protobuf"
@ -50,23 +67,26 @@
name = "github.com/google/pprof" name = "github.com/google/pprof"
packages = ["profile"] packages = ["profile"]
pruneopts = "UT" pruneopts = "UT"
revision = "84b7d314e22c8d12334e52726f68517973b6027b" revision = "3ea8567a2e5752420fc544d2e2ad249721768934"
[[projects]] [[projects]]
digest = "1:3a26588bc48b96825977c1b3df964f8fd842cd6860cc26370588d3563433cf11" digest = "1:236d7e1bdb50d8f68559af37dbcf9d142d56b431c9b2176d41e2a009b664cda8"
name = "github.com/google/uuid" name = "github.com/google/uuid"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494" revision = "9b3b1e0f5f99ae461456d768e7d301a7acdaa2d8"
version = "v1.0.0" version = "v1.1.0"
[[projects]] [[projects]]
digest = "1:e145e9710a10bc114a6d3e2738aadf8de146adaa031854ffdf7bbfe15da85e63" digest = "1:cd9864c6366515827a759931746738ede6079faa08df9c584596370d6add135c"
name = "github.com/googleapis/gax-go" name = "github.com/googleapis/gax-go"
packages = ["."] packages = [
".",
"v2",
]
pruneopts = "UT" pruneopts = "UT"
revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f" revision = "c8a15bac9b9fe955bd9f900272f9a306465d28cf"
version = "v2.0.0" version = "v2.0.3"
[[projects]] [[projects]]
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1" digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
@ -84,6 +104,14 @@
revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf"
version = "v1.6.2" version = "v1.6.2"
[[projects]]
digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
version = "v1.0.1"
[[projects]] [[projects]]
digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747" digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747"
name = "github.com/pkg/errors" name = "github.com/pkg/errors"
@ -93,18 +121,20 @@
version = "v0.8.0" version = "v0.8.0"
[[projects]] [[projects]]
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc" digest = "1:69b1cc331fca23d702bd72f860c6a647afd0aa9fcbc1d0659b1365e26546dd70"
name = "github.com/sirupsen/logrus" name = "github.com/sirupsen/logrus"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "3e01752db0189b9157070a0e1668a620f9a85da2" revision = "bcd833dfe83d3cebad139e4a29ed79cb2318bf95"
version = "v1.0.6" version = "v1.2.0"
[[projects]] [[projects]]
digest = "1:1bb914cfb78f68f488a91cd7872d3d06a5f83c5bbacf0296dbef44e120b00a91" digest = "1:a5154dfd6b37bef5a3eab759e13296348e639dc8c7604f538368167782b08ccd"
name = "go.opencensus.io" name = "go.opencensus.io"
packages = [ packages = [
".", ".",
"exporter/jaeger",
"exporter/jaeger/internal/gen-go/jaeger",
"internal", "internal",
"internal/tagencoding", "internal/tagencoding",
"plugin/ocgrpc", "plugin/ocgrpc",
@ -125,15 +155,15 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8" digest = "1:38f553aff0273ad6f367cb0a0f8b6eecbaef8dc6cb8b50e57b6a81c1d5b1e332"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = ["ssh/terminal"] packages = ["ssh/terminal"]
pruneopts = "UT" pruneopts = "UT"
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c" revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:1c14517b2f106c61d75006199b46a46576058661d469658cb0f90739919641d2" digest = "1:8ecb828bb550a8c6b7d75b8261a42c369461311616ebe5451966d067f5f993bf"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = [ packages = [
"context", "context",
@ -146,11 +176,11 @@
"trace", "trace",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2" revision = "927f97764cc334a6575f4b7a1584a147864d5723"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:f645667d687fc8bf228865a2c5455824ef05bad08841e673673ef2bb89ac5b90" digest = "1:23443edff0740e348959763085df98400dcfd85528d7771bb0ce9f5f2754ff4a"
name = "golang.org/x/oauth2" name = "golang.org/x/oauth2"
packages = [ packages = [
".", ".",
@ -160,26 +190,26 @@
"jwt", "jwt",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9" revision = "d668ce993890a79bda886613ee587a69dd5da7a6"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:e0140c0c868c6e0f01c0380865194592c011fe521d6e12d78bfd33e756fe018a" digest = "1:75515eedc0dc2cb0b40372008b616fa2841d831c63eedd403285ff286c593295"
name = "golang.org/x/sync" name = "golang.org/x/sync"
packages = ["semaphore"] packages = ["semaphore"]
pruneopts = "UT" pruneopts = "UT"
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" revision = "37e7f081c4d4c64e13b10787722085407fe5d15f"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:374fc90fcb026e9a367e3fad29e988e5dd944b68ca3f24a184d77abc5307dda4" digest = "1:191cccd950a4aeadb60306062f2bdc2f924d750d0156ec6c691b17211bfd7349"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = [ packages = [
"unix", "unix",
"windows", "windows",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "d0be0721c37eeb5299f245a996a483160fc36940" revision = "82a175fd1598e8a172e58ebdf5ed262bb29129e5"
[[projects]] [[projects]]
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
@ -206,7 +236,7 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:e9e388241f9f0f02000dddaeeb91153d53f0cd09dcec33879cc7e043a2e65d75" digest = "1:2e81813e8e072aa700e101369890e55539729d817d32dbc3fab228d6b40c4d83"
name = "google.golang.org/api" name = "google.golang.org/api"
packages = [ packages = [
"googleapi/transport", "googleapi/transport",
@ -217,12 +247,13 @@
"transport", "transport",
"transport/grpc", "transport/grpc",
"transport/http", "transport/http",
"transport/http/internal/propagation",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "7ca32eb868bf53ea2fc406698eb98583a8073d19" revision = "19e022d8cf43ce81f046bae8cc18c5397cc7732f"
[[projects]] [[projects]]
digest = "1:26619fcd2452b4044174d26acd8b09c09dffee9a1c3a22d2383b873aa9a0131f" digest = "1:c4eaa5f79d36f76ef4bd0c4f96e36bc1b7b5a359528d1267f0cb7a5d58b7b5bb"
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
packages = [ packages = [
".", ".",
@ -239,12 +270,12 @@
"urlfetch", "urlfetch",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
version = "v1.1.0" version = "v1.4.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:7a3da01a8f840fbbef1f027dc091ae52a29c6ab9374e126b6bdc5bf3b0ff2687" digest = "1:3552e7267a98c605e6cbfe6b03c34589265ab72e6078b95fb2e10e0cb44f5cc8"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = [ packages = [
"googleapis/api/annotations", "googleapis/api/annotations",
@ -260,28 +291,33 @@
"protobuf/field_mask", "protobuf/field_mask",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "36d5787dc5356b711fe8f3040271aaf51c35955b" revision = "bd9b4fb69e2ffd37621a6caa54dcbead29b546f2"
[[projects]] [[projects]]
digest = "1:4ad047d772a7d4841687df9534a767a9e243885ed6d7d2ced6af5995a5dc44b3" digest = "1:3fc54ad826c0183f803bb97e0927dfc05fcb7b7a6ddabed646ee8184d861fa9b"
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
packages = [ packages = [
".", ".",
"balancer", "balancer",
"balancer/base", "balancer/base",
"balancer/roundrobin", "balancer/roundrobin",
"binarylog/grpc_binarylog_v1",
"codes", "codes",
"connectivity", "connectivity",
"credentials", "credentials",
"credentials/internal",
"credentials/oauth", "credentials/oauth",
"encoding", "encoding",
"encoding/proto", "encoding/proto",
"grpclog", "grpclog",
"internal", "internal",
"internal/backoff", "internal/backoff",
"internal/binarylog",
"internal/channelz", "internal/channelz",
"internal/envconfig", "internal/envconfig",
"internal/grpcrand", "internal/grpcrand",
"internal/grpcsync",
"internal/syscall",
"internal/transport", "internal/transport",
"keepalive", "keepalive",
"metadata", "metadata",
@ -295,8 +331,8 @@
"tap", "tap",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1" revision = "df014850f6dee74ba2fc94874043a9f3f75fbfd8"
version = "v1.15.0" version = "v1.17.0"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
@ -311,6 +347,7 @@
"github.com/gorilla/mux", "github.com/gorilla/mux",
"github.com/pkg/errors", "github.com/pkg/errors",
"github.com/sirupsen/logrus", "github.com/sirupsen/logrus",
"go.opencensus.io/exporter/jaeger",
"go.opencensus.io/plugin/ocgrpc", "go.opencensus.io/plugin/ocgrpc",
"go.opencensus.io/plugin/ochttp", "go.opencensus.io/plugin/ochttp",
"go.opencensus.io/plugin/ochttp/propagation/b3", "go.opencensus.io/plugin/ochttp/propagation/b3",

View file

@ -26,6 +26,7 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/exporter/jaeger"
"go.opencensus.io/plugin/ocgrpc" "go.opencensus.io/plugin/ocgrpc"
"go.opencensus.io/plugin/ochttp" "go.opencensus.io/plugin/ochttp"
"go.opencensus.io/plugin/ochttp/propagation/b3" "go.opencensus.io/plugin/ochttp/propagation/b3"
@ -142,6 +143,29 @@ func main() {
log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler)) log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler))
} }
func initJaegerTracing(log logrus.FieldLogger) {
svcAddr := os.Getenv("JAEGER_SERVICE_ADDR")
if svcAddr == "" {
log.Info("jaeger initialization disabled.")
return
}
// Register the Jaeger exporter to be able to retrieve
// the collected spans.
exporter, err := jaeger.NewExporter(jaeger.Options{
Endpoint: fmt.Sprintf("http://%s", svcAddr),
Process: jaeger.Process{
ServiceName: "frontend",
},
})
if err != nil {
log.Fatal(err)
}
trace.RegisterExporter(exporter)
log.Info("jaeger initialization completed.")
}
func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) { func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) {
view.SetReportingPeriod(60 * time.Second) view.SetReportingPeriod(60 * time.Second)
view.RegisterExporter(exporter) view.RegisterExporter(exporter)
@ -157,17 +181,19 @@ func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) {
} }
} }
func initTracing(log logrus.FieldLogger) { func initStackdriverTracing(log logrus.FieldLogger) {
// TODO(ahmetb) this method is duplicated in other microservices using Go // TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages. // since they are not sharing packages.
for i := 1; i <= 3; i++ { for i := 1; i <= 3; i++ {
log = log.WithField("retry", i) log = log.WithField("retry", i)
exporter, err := stackdriver.NewExporter(stackdriver.Options{}) exporter, err := stackdriver.NewExporter(stackdriver.Options{})
if err != nil { if err != nil {
// log.Warnf is used since there are multiple backends (stackdriver & jaeger)
// to store the traces. In production setup most likely you would use only one backend.
// In that case you should use log.Fatalf.
log.Warnf("failed to initialize stackdriver exporter: %+v", err) log.Warnf("failed to initialize stackdriver exporter: %+v", err)
} else { } else {
trace.RegisterExporter(exporter) trace.RegisterExporter(exporter)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
log.Info("registered stackdriver tracing") log.Info("registered stackdriver tracing")
// Register the views to collect server stats. // Register the views to collect server stats.
@ -181,6 +207,18 @@ func initTracing(log logrus.FieldLogger) {
log.Warn("could not initialize stackdriver exporter after retrying, giving up") log.Warn("could not initialize stackdriver exporter after retrying, giving up")
} }
func initTracing(log logrus.FieldLogger) {
// This is a demo app with low QPS. trace.AlwaysSample() is used here
// to make sure traces are available for observation and analysis.
// In a production environment or high QPS setup please use
// trace.ProbabilitySampler set at the desired probability.
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
initJaegerTracing(log)
initStackdriverTracing(log)
}
func initProfiling(log logrus.FieldLogger, service, version string) { func initProfiling(log logrus.FieldLogger, service, version string) {
// TODO(ahmetb) this method is duplicated in other microservices using Go // TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages. // since they are not sharing packages.

View file

@ -1,14 +1,10 @@
FROM python:3-alpine as base FROM python:3-slim as base
FROM base as builder FROM base as builder
RUN apk add --update --no-cache \ RUN apt-get -qq update \
gcc \ && apt-get install -y --no-install-recommends \
linux-headers \ g++
make \
musl-dev \
python-dev \
g++
COPY requirements.txt . COPY requirements.txt .

View file

@ -0,0 +1 @@
locustio==0.8.1

View file

@ -1,2 +1,23 @@
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements.txt requirements.in
#
certifi==2018.11.29 # via requests
chardet==3.0.4 # via requests
click==7.0 # via flask
flask==1.0.2 # via locustio
gevent==1.4.0 # via locustio
greenlet==0.4.15 # via gevent
idna==2.8 # via requests
itsdangerous==1.1.0 # via flask
jinja2==2.10 # via flask
locustio==0.8.1 locustio==0.8.1
pyzmq==17.0.0 markupsafe==1.1.0 # via jinja2
msgpack-python==0.5.6 # via locustio
pyzmq==17.0.0 # via locustio
requests==2.21.0 # via locustio
six==1.12.0 # via locustio
urllib3==1.24.1 # via requests
werkzeug==0.14.1 # via flask

View file

@ -2,27 +2,46 @@
[[projects]] [[projects]]
digest = "1:467af0aad47996b25b838d6f14c8371123a8a76ec239020a6c5894e1f8f60272"
name = "cloud.google.com/go" name = "cloud.google.com/go"
packages = [ packages = [
"compute/metadata", "compute/metadata",
"internal/version", "internal/version",
"monitoring/apiv3", "monitoring/apiv3",
"profiler", "profiler",
"trace/apiv2" "trace/apiv2",
] ]
pruneopts = "UT"
revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad" revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad"
version = "v0.27.0" version = "v0.27.0"
[[projects]] [[projects]]
digest = "1:4b96dcd8534bc6450a922bd16a76360ba3381f0d1daf40abbaec91c053fbfeb5"
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"
packages = [ packages = ["."]
".", pruneopts = "UT"
"propagation"
]
revision = "37aa2801fbf0205003e15636096ebf0373510288" revision = "37aa2801fbf0205003e15636096ebf0373510288"
version = "v0.5.0" version = "v0.5.0"
[[projects]] [[projects]]
branch = "master"
digest = "1:d3a57cdbaefaceca4ebe6258ed86a992bdcfc93a8442dbda5343e2d43a8f8a6a"
name = "git.apache.org/thrift.git"
packages = ["lib/go/thrift"]
pruneopts = "UT"
revision = "67df34afa782be67154034b31e4ad7cb3834fed1"
source = "github.com/apache/thrift"
[[projects]]
branch = "master"
digest = "1:14e66208d324c0ecb49934b5ac311c50a94e3a458e92b0026ef9e26919ac8d9d"
name = "github.com/GoogleCloudPlatform/microservices-demo"
packages = ["src/productcatalogservice/genproto"]
pruneopts = "UT"
revision = "10dfd04ab174cc680ed6ffef26cc4fb09ec40404"
[[projects]]
digest = "1:4fbf68bee2a60f6af6414572936edb295f6f26b73c6fb25ab0e7b03b013854f5"
name = "github.com/golang/protobuf" name = "github.com/golang/protobuf"
packages = [ packages = [
"jsonpb", "jsonpb",
@ -34,46 +53,67 @@
"ptypes/empty", "ptypes/empty",
"ptypes/struct", "ptypes/struct",
"ptypes/timestamp", "ptypes/timestamp",
"ptypes/wrappers" "ptypes/wrappers",
] ]
pruneopts = "UT"
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0" version = "v1.2.0"
[[projects]] [[projects]]
digest = "1:2e3c336fc7fde5c984d2841455a658a6d626450b1754a854b3b32e7a8f49a07a"
name = "github.com/google/go-cmp" name = "github.com/google/go-cmp"
packages = [ packages = [
"cmp", "cmp",
"cmp/internal/diff", "cmp/internal/diff",
"cmp/internal/function", "cmp/internal/function",
"cmp/internal/value" "cmp/internal/value",
] ]
pruneopts = "UT"
revision = "3af367b6b30c263d47e8895973edcca9a49cf029" revision = "3af367b6b30c263d47e8895973edcca9a49cf029"
version = "v0.2.0" version = "v0.2.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:fc55304e290027108ae0cac675a171bcd854f9c657678c20ceea837718ea6819"
name = "github.com/google/pprof" name = "github.com/google/pprof"
packages = ["profile"] packages = ["profile"]
revision = "e027b505a088ac3c68c339a1d7ce7724bf34538b" pruneopts = "UT"
revision = "e84dfd68c163c45ea47aa24b3dc7eaa93f6675b1"
[[projects]] [[projects]]
digest = "1:cd9864c6366515827a759931746738ede6079faa08df9c584596370d6add135c"
name = "github.com/googleapis/gax-go" name = "github.com/googleapis/gax-go"
packages = ["."] packages = [
revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f" ".",
version = "v2.0.0" "v2",
]
pruneopts = "UT"
revision = "c8a15bac9b9fe955bd9f900272f9a306465d28cf"
version = "v2.0.3"
[[projects]] [[projects]]
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc" digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
version = "v1.0.1"
[[projects]]
digest = "1:87c2e02fb01c27060ccc5ba7c5a407cc91147726f8f40b70cceeedbc52b1f3a8"
name = "github.com/sirupsen/logrus" name = "github.com/sirupsen/logrus"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "3e01752db0189b9157070a0e1668a620f9a85da2" revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5"
version = "v1.0.6" version = "v1.3.0"
[[projects]] [[projects]]
digest = "1:a5154dfd6b37bef5a3eab759e13296348e639dc8c7604f538368167782b08ccd"
name = "go.opencensus.io" name = "go.opencensus.io"
packages = [ packages = [
".", ".",
"exporter/jaeger",
"exporter/jaeger/internal/gen-go/jaeger",
"internal", "internal",
"internal/tagencoding", "internal/tagencoding",
"plugin/ocgrpc", "plugin/ocgrpc",
@ -86,21 +126,23 @@
"trace", "trace",
"trace/internal", "trace/internal",
"trace/propagation", "trace/propagation",
"trace/tracestate" "trace/tracestate",
] ]
pruneopts = "UT"
revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89" revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89"
version = "v0.16.0" version = "v0.16.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8" digest = "1:38f553aff0273ad6f367cb0a0f8b6eecbaef8dc6cb8b50e57b6a81c1d5b1e332"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = ["ssh/terminal"] packages = ["ssh/terminal"]
pruneopts = "UT" pruneopts = "UT"
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c" revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:9d2f08c64693fbe7177b5980f80c35672c80f12be79bb3bc86948b934d70e4ee"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = [ packages = [
"context", "context",
@ -110,35 +152,46 @@
"http2/hpack", "http2/hpack",
"idna", "idna",
"internal/timeseries", "internal/timeseries",
"trace" "trace",
] ]
revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2" pruneopts = "UT"
revision = "ed066c81e75eba56dd9bd2139ade88125b855585"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:511a6232760c10dcb1ebf1ab83ef0291e2baf801f203ca6314759c5458b73a6a"
name = "golang.org/x/oauth2" name = "golang.org/x/oauth2"
packages = [ packages = [
".", ".",
"google", "google",
"internal", "internal",
"jws", "jws",
"jwt" "jwt",
] ]
revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9" pruneopts = "UT"
revision = "5dab4167f31cbd76b407f1486c86b40748bc5073"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:75515eedc0dc2cb0b40372008b616fa2841d831c63eedd403285ff286c593295"
name = "golang.org/x/sync" name = "golang.org/x/sync"
packages = ["semaphore"] packages = ["semaphore"]
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" pruneopts = "UT"
revision = "37e7f081c4d4c64e13b10787722085407fe5d15f"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:43cde116ff48f299eddb7e6515677e6d0a2c915854bb05a333877f07c3bb3033"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix"] packages = [
revision = "1561086e645b2809fb9f8a1e2a38160bf8d53bf4" "unix",
"windows",
]
pruneopts = "UT"
revision = "11f53e03133963fb11ae0588e08b5e0b85be8be5"
[[projects]] [[projects]]
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
name = "golang.org/x/text" name = "golang.org/x/text"
packages = [ packages = [
"collate", "collate",
@ -154,13 +207,15 @@
"unicode/bidi", "unicode/bidi",
"unicode/cldr", "unicode/cldr",
"unicode/norm", "unicode/norm",
"unicode/rangetable" "unicode/rangetable",
] ]
pruneopts = "UT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0" version = "v0.3.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:26a71f62c83707b9952821c2a895bd041588501fa370cc267221817fcc721253"
name = "google.golang.org/api" name = "google.golang.org/api"
packages = [ packages = [
"googleapi/transport", "googleapi/transport",
@ -170,11 +225,14 @@
"support/bundler", "support/bundler",
"transport", "transport",
"transport/grpc", "transport/grpc",
"transport/http" "transport/http",
"transport/http/internal/propagation",
] ]
revision = "19ff8768a5c0b8e46ea281065664787eefc24121" pruneopts = "UT"
revision = "43037ff31f6958582e5d3c19d9ac1a4d2819669c"
[[projects]] [[projects]]
digest = "1:c4eaa5f79d36f76ef4bd0c4f96e36bc1b7b5a359528d1267f0cb7a5d58b7b5bb"
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
packages = [ packages = [
".", ".",
@ -188,13 +246,15 @@
"internal/socket", "internal/socket",
"internal/urlfetch", "internal/urlfetch",
"socket", "socket",
"urlfetch" "urlfetch",
] ]
revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06" pruneopts = "UT"
version = "v1.2.0" revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
version = "v1.4.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:3552e7267a98c605e6cbfe6b03c34589265ab72e6078b95fb2e10e0cb44f5cc8"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = [ packages = [
"googleapis/api/annotations", "googleapis/api/annotations",
@ -207,11 +267,13 @@
"googleapis/monitoring/v3", "googleapis/monitoring/v3",
"googleapis/rpc/errdetails", "googleapis/rpc/errdetails",
"googleapis/rpc/status", "googleapis/rpc/status",
"protobuf/field_mask" "protobuf/field_mask",
] ]
revision = "c3f76f3b92d1ffa4c58a9ff842a58b8877655e0f" pruneopts = "UT"
revision = "db91494dd46c1fdcbbde05e5ff5eb56df8f7d79a"
[[projects]] [[projects]]
digest = "1:6497ab07ec89179db8d5a563d33635be04ceffaa29007a3ae74b9f15f4d3068e"
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
packages = [ packages = [
".", ".",
@ -241,14 +303,32 @@
"resolver/passthrough", "resolver/passthrough",
"stats", "stats",
"status", "status",
"tap" "tap",
] ]
pruneopts = "UT"
revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
version = "v1.14.0" version = "v1.14.0"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "b68fd9438c2eb711d9fc51c1f23c5ca0d5169bf4022351dfc400cd35ba39dfaa" 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",
"github.com/sirupsen/logrus",
"go.opencensus.io/exporter/jaeger",
"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/health/grpc_health_v1",
"google.golang.org/grpc/status",
]
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -29,3 +29,10 @@ kubectl exec \
$(kubectl get pods -l app=productcatalogservice -o jsonpath='{.items[0].metadata.name}') \ $(kubectl get pods -l app=productcatalogservice -o jsonpath='{.items[0].metadata.name}') \
-c server -- kill -USR2 1 -c server -- kill -USR2 1
``` ```
## Latency injection
This service has an `EXTRA_LATENCY` environment variable. This will inject a sleep for the specified [time.Duration](https://golang.org/pkg/time/#ParseDuration) on every call to
to the server.
For example, use `EXTRA_LATENCY="5.5s"` to sleep for 5.5 seconds on every request.

View file

@ -35,6 +35,7 @@ import (
"contrib.go.opencensus.io/exporter/stackdriver" "contrib.go.opencensus.io/exporter/stackdriver"
"github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/jsonpb"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/exporter/jaeger"
"go.opencensus.io/plugin/ocgrpc" "go.opencensus.io/plugin/ocgrpc"
"go.opencensus.io/stats/view" "go.opencensus.io/stats/view"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@ -47,6 +48,7 @@ var (
cat pb.ListProductsResponse cat pb.ListProductsResponse
catalogMutex *sync.Mutex catalogMutex *sync.Mutex
log *logrus.Logger log *logrus.Logger
extraLatency time.Duration
port = flag.Int("port", 3550, "port to listen at") port = flag.Int("port", 3550, "port to listen at")
@ -76,6 +78,18 @@ func main() {
go initProfiling("productcatalogservice", "1.0.0") go initProfiling("productcatalogservice", "1.0.0")
flag.Parse() flag.Parse()
// set injected latency
if s := os.Getenv("EXTRA_LATENCY"); s != "" {
v, err := time.ParseDuration(s)
if err != nil {
log.Fatalf("failed to parse EXTRA_LATENCY (%s) as time.Duration: %+v", v, err)
}
extraLatency = v
log.Infof("extra latency enabled (duration: %v)", extraLatency)
} else {
extraLatency = time.Duration(0)
}
sigs := make(chan os.Signal, 1) sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGUSR2) signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGUSR2)
go func() { go func() {
@ -110,6 +124,27 @@ func run(port int) string {
return l.Addr().String() return l.Addr().String()
} }
func initJaegerTracing() {
svcAddr := os.Getenv("JAEGER_SERVICE_ADDR")
if svcAddr == "" {
log.Info("jaeger initialization disabled.")
return
}
// Register the Jaeger exporter to be able to retrieve
// the collected spans.
exporter, err := jaeger.NewExporter(jaeger.Options{
Endpoint: fmt.Sprintf("http://%s", svcAddr),
Process: jaeger.Process{
ServiceName: "productcatalogservice",
},
})
if err != nil {
log.Fatal(err)
}
trace.RegisterExporter(exporter)
log.Info("jaeger initialization completed.")
}
func initStats(exporter *stackdriver.Exporter) { func initStats(exporter *stackdriver.Exporter) {
view.SetReportingPeriod(60 * time.Second) view.SetReportingPeriod(60 * time.Second)
view.RegisterExporter(exporter) view.RegisterExporter(exporter)
@ -120,7 +155,7 @@ func initStats(exporter *stackdriver.Exporter) {
} }
} }
func initTracing() { func initStackDriverTracing() {
// TODO(ahmetb) this method is duplicated in other microservices using Go // TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages. // since they are not sharing packages.
for i := 1; i <= 3; i++ { for i := 1; i <= 3; i++ {
@ -143,6 +178,11 @@ func initTracing() {
log.Warn("could not initialize stackdriver exporter after retrying, giving up") log.Warn("could not initialize stackdriver exporter after retrying, giving up")
} }
func initTracing() {
initJaegerTracing()
initStackDriverTracing()
}
func initProfiling(service, version string) { func initProfiling(service, version string) {
// TODO(ahmetb) this method is duplicated in other microservices using Go // TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages. // since they are not sharing packages.
@ -198,10 +238,12 @@ func (p *productCatalog) Check(ctx context.Context, req *healthpb.HealthCheckReq
} }
func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) { func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) {
time.Sleep(extraLatency)
return &pb.ListProductsResponse{Products: parseCatalog()}, nil return &pb.ListProductsResponse{Products: parseCatalog()}, nil
} }
func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductRequest) (*pb.Product, error) { func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductRequest) (*pb.Product, error) {
time.Sleep(extraLatency)
var found *pb.Product var found *pb.Product
for i := 0; i < len(parseCatalog()); i++ { for i := 0; i < len(parseCatalog()); i++ {
if req.Id == parseCatalog()[i].Id { if req.Id == parseCatalog()[i].Id {
@ -215,6 +257,7 @@ func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductReque
} }
func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProductsRequest) (*pb.SearchProductsResponse, error) { func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProductsRequest) (*pb.SearchProductsResponse, error) {
time.Sleep(extraLatency)
// Intepret query as a substring match in name or description. // Intepret query as a substring match in name or description.
var ps []*pb.Product var ps []*pb.Product
for _, p := range parseCatalog() { for _, p := range parseCatalog() {

View file

@ -0,0 +1,6 @@
google-api-core==1.6.0
google-python-cloud-debugger==2.9
grpcio-health-checking==1.13.0
grpcio==1.16.1
opencensus[stackdriver]==0.1.10
python-json-logger==0.1.9

View file

@ -1,30 +1,35 @@
cachetools==2.1.0 #
certifi==2018.4.16 # This file is autogenerated by pip-compile
chardet==3.0.4 # To update, run:
enum34==1.1.6 #
futures==3.2.0 # pip-compile --output-file requirements.txt requirements.in
google-api-core==1.6.0 #
google-api-python-client==1.7.4 cachetools==3.1.0 # via google-auth
google-auth==1.6.1 certifi==2018.11.29 # via requests
google-auth-httplib2==0.0.3 chardet==3.0.4 # via requests
google-cloud-core==0.29.0 enum34==1.1.6 # via grpcio
google-python-cloud-debugger==2.8 futures==3.2.0 # via google-api-core, grpcio
googleapis-common-protos==1.5.3 google-api-core[grpc]==1.6.0
grpcio==1.13.0 google-api-python-client==1.7.8 # via google-python-cloud-debugger
google-auth-httplib2==0.0.3 # via google-api-python-client, google-python-cloud-debugger
google-auth==1.6.2 # via google-api-core, google-api-python-client, google-auth-httplib2, google-python-cloud-debugger
google-cloud-core==0.29.1 # via google-cloud-trace
google-cloud-trace==0.20.2 # via opencensus
google-python-cloud-debugger==2.9
googleapis-common-protos==1.5.6 # via google-api-core
grpcio-health-checking==1.13.0 grpcio-health-checking==1.13.0
grpcio-tools==1.0.0 grpcio==1.16.1
httplib2==0.11.3 httplib2==0.12.0 # via google-api-python-client, google-auth-httplib2
idna==2.7 idna==2.8 # via requests
opencensus[stackdriver]==0.1.10 opencensus[stackdriver]==0.1.10
protobuf==3.5.2.post1 protobuf==3.6.1 # via google-api-core, googleapis-common-protos, grpcio-health-checking
pyasn1==0.4.3 pyasn1-modules==0.2.4 # via google-auth
pyasn1-modules==0.2.2 pyasn1==0.4.5 # via pyasn1-modules, rsa
python-json-logger==0.1.9 python-json-logger==0.1.9
pytz==2018.5 pytz==2018.9 # via google-api-core
PyYAML==3.13 pyyaml==3.13 # via google-python-cloud-debugger
requests==2.20.0 requests==2.21.0 # via google-api-core
rsa==3.4.2 rsa==4.0 # via google-auth
six==1.11.0 six==1.12.0 # via google-api-core, google-api-python-client, google-auth, google-python-cloud-debugger, grpcio, protobuf
uritemplate==3.0.0 uritemplate==3.0.0 # via google-api-python-client
urllib3==1.23 urllib3==1.24.1 # via requests
virtualenv==16.0.0

View file

@ -2,27 +2,46 @@
[[projects]] [[projects]]
digest = "1:467af0aad47996b25b838d6f14c8371123a8a76ec239020a6c5894e1f8f60272"
name = "cloud.google.com/go" name = "cloud.google.com/go"
packages = [ packages = [
"compute/metadata", "compute/metadata",
"internal/version", "internal/version",
"monitoring/apiv3", "monitoring/apiv3",
"profiler", "profiler",
"trace/apiv2" "trace/apiv2",
] ]
pruneopts = "UT"
revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad" revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad"
version = "v0.27.0" version = "v0.27.0"
[[projects]] [[projects]]
digest = "1:4b96dcd8534bc6450a922bd16a76360ba3381f0d1daf40abbaec91c053fbfeb5"
name = "contrib.go.opencensus.io/exporter/stackdriver" name = "contrib.go.opencensus.io/exporter/stackdriver"
packages = [ packages = ["."]
".", pruneopts = "UT"
"propagation"
]
revision = "37aa2801fbf0205003e15636096ebf0373510288" revision = "37aa2801fbf0205003e15636096ebf0373510288"
version = "v0.5.0" version = "v0.5.0"
[[projects]] [[projects]]
branch = "master"
digest = "1:d3a57cdbaefaceca4ebe6258ed86a992bdcfc93a8442dbda5343e2d43a8f8a6a"
name = "git.apache.org/thrift.git"
packages = ["lib/go/thrift"]
pruneopts = "UT"
revision = "67df34afa782be67154034b31e4ad7cb3834fed1"
source = "github.com/apache/thrift"
[[projects]]
branch = "master"
digest = "1:27490301253ac5063d502480ef3794b95222eea6cb997ae6e689a058b1cd5253"
name = "github.com/GoogleCloudPlatform/microservices-demo"
packages = ["src/shippingservice/genproto"]
pruneopts = "UT"
revision = "10dfd04ab174cc680ed6ffef26cc4fb09ec40404"
[[projects]]
digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a"
name = "github.com/golang/protobuf" name = "github.com/golang/protobuf"
packages = [ packages = [
"proto", "proto",
@ -33,35 +52,54 @@
"ptypes/empty", "ptypes/empty",
"ptypes/struct", "ptypes/struct",
"ptypes/timestamp", "ptypes/timestamp",
"ptypes/wrappers" "ptypes/wrappers",
] ]
pruneopts = "UT"
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0" version = "v1.2.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:fc55304e290027108ae0cac675a171bcd854f9c657678c20ceea837718ea6819"
name = "github.com/google/pprof" name = "github.com/google/pprof"
packages = ["profile"] packages = ["profile"]
revision = "e027b505a088ac3c68c339a1d7ce7724bf34538b" pruneopts = "UT"
revision = "e84dfd68c163c45ea47aa24b3dc7eaa93f6675b1"
[[projects]] [[projects]]
digest = "1:cd9864c6366515827a759931746738ede6079faa08df9c584596370d6add135c"
name = "github.com/googleapis/gax-go" name = "github.com/googleapis/gax-go"
packages = ["."] packages = [
revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f" ".",
version = "v2.0.0" "v2",
]
pruneopts = "UT"
revision = "c8a15bac9b9fe955bd9f900272f9a306465d28cf"
version = "v2.0.3"
[[projects]] [[projects]]
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc" digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
version = "v1.0.1"
[[projects]]
digest = "1:87c2e02fb01c27060ccc5ba7c5a407cc91147726f8f40b70cceeedbc52b1f3a8"
name = "github.com/sirupsen/logrus" name = "github.com/sirupsen/logrus"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "3e01752db0189b9157070a0e1668a620f9a85da2" revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5"
version = "v1.0.6" version = "v1.3.0"
[[projects]] [[projects]]
digest = "1:a5154dfd6b37bef5a3eab759e13296348e639dc8c7604f538368167782b08ccd"
name = "go.opencensus.io" name = "go.opencensus.io"
packages = [ packages = [
".", ".",
"exporter/jaeger",
"exporter/jaeger/internal/gen-go/jaeger",
"internal", "internal",
"internal/tagencoding", "internal/tagencoding",
"plugin/ocgrpc", "plugin/ocgrpc",
@ -74,21 +112,23 @@
"trace", "trace",
"trace/internal", "trace/internal",
"trace/propagation", "trace/propagation",
"trace/tracestate" "trace/tracestate",
] ]
pruneopts = "UT"
revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89" revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89"
version = "v0.16.0" version = "v0.16.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8" digest = "1:38f553aff0273ad6f367cb0a0f8b6eecbaef8dc6cb8b50e57b6a81c1d5b1e332"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = ["ssh/terminal"] packages = ["ssh/terminal"]
pruneopts = "UT" pruneopts = "UT"
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c" revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:9d2f08c64693fbe7177b5980f80c35672c80f12be79bb3bc86948b934d70e4ee"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = [ packages = [
"context", "context",
@ -98,35 +138,46 @@
"http2/hpack", "http2/hpack",
"idna", "idna",
"internal/timeseries", "internal/timeseries",
"trace" "trace",
] ]
revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2" pruneopts = "UT"
revision = "ed066c81e75eba56dd9bd2139ade88125b855585"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:511a6232760c10dcb1ebf1ab83ef0291e2baf801f203ca6314759c5458b73a6a"
name = "golang.org/x/oauth2" name = "golang.org/x/oauth2"
packages = [ packages = [
".", ".",
"google", "google",
"internal", "internal",
"jws", "jws",
"jwt" "jwt",
] ]
revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9" pruneopts = "UT"
revision = "5dab4167f31cbd76b407f1486c86b40748bc5073"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:75515eedc0dc2cb0b40372008b616fa2841d831c63eedd403285ff286c593295"
name = "golang.org/x/sync" name = "golang.org/x/sync"
packages = ["semaphore"] packages = ["semaphore"]
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" pruneopts = "UT"
revision = "37e7f081c4d4c64e13b10787722085407fe5d15f"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:43cde116ff48f299eddb7e6515677e6d0a2c915854bb05a333877f07c3bb3033"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix"] packages = [
revision = "1561086e645b2809fb9f8a1e2a38160bf8d53bf4" "unix",
"windows",
]
pruneopts = "UT"
revision = "11f53e03133963fb11ae0588e08b5e0b85be8be5"
[[projects]] [[projects]]
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
name = "golang.org/x/text" name = "golang.org/x/text"
packages = [ packages = [
"collate", "collate",
@ -142,13 +193,15 @@
"unicode/bidi", "unicode/bidi",
"unicode/cldr", "unicode/cldr",
"unicode/norm", "unicode/norm",
"unicode/rangetable" "unicode/rangetable",
] ]
pruneopts = "UT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0" version = "v0.3.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:26a71f62c83707b9952821c2a895bd041588501fa370cc267221817fcc721253"
name = "google.golang.org/api" name = "google.golang.org/api"
packages = [ packages = [
"googleapi/transport", "googleapi/transport",
@ -158,11 +211,14 @@
"support/bundler", "support/bundler",
"transport", "transport",
"transport/grpc", "transport/grpc",
"transport/http" "transport/http",
"transport/http/internal/propagation",
] ]
revision = "19ff8768a5c0b8e46ea281065664787eefc24121" pruneopts = "UT"
revision = "43037ff31f6958582e5d3c19d9ac1a4d2819669c"
[[projects]] [[projects]]
digest = "1:c4eaa5f79d36f76ef4bd0c4f96e36bc1b7b5a359528d1267f0cb7a5d58b7b5bb"
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
packages = [ packages = [
".", ".",
@ -176,13 +232,15 @@
"internal/socket", "internal/socket",
"internal/urlfetch", "internal/urlfetch",
"socket", "socket",
"urlfetch" "urlfetch",
] ]
revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06" pruneopts = "UT"
version = "v1.2.0" revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
version = "v1.4.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:3552e7267a98c605e6cbfe6b03c34589265ab72e6078b95fb2e10e0cb44f5cc8"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = [ packages = [
"googleapis/api/annotations", "googleapis/api/annotations",
@ -195,11 +253,13 @@
"googleapis/monitoring/v3", "googleapis/monitoring/v3",
"googleapis/rpc/errdetails", "googleapis/rpc/errdetails",
"googleapis/rpc/status", "googleapis/rpc/status",
"protobuf/field_mask" "protobuf/field_mask",
] ]
revision = "c3f76f3b92d1ffa4c58a9ff842a58b8877655e0f" pruneopts = "UT"
revision = "db91494dd46c1fdcbbde05e5ff5eb56df8f7d79a"
[[projects]] [[projects]]
digest = "1:f3fea5ef1fb1f632ae0dd9a86af6aa2048f3243d1da0075706fca1def38d9fbb"
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
packages = [ packages = [
".", ".",
@ -231,14 +291,29 @@
"resolver/passthrough", "resolver/passthrough",
"stats", "stats",
"status", "status",
"tap" "tap",
] ]
pruneopts = "UT"
revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
version = "v1.14.0" version = "v1.14.0"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "5dac84cd5efcc89491aa3cda06a774c1b370c8e0cbdb99668cbfd8ba27b3e32c" 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",
"github.com/sirupsen/logrus",
"go.opencensus.io/exporter/jaeger",
"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/health/grpc_health_v1",
"google.golang.org/grpc/reflection",
]
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -23,6 +23,7 @@ import (
"cloud.google.com/go/profiler" "cloud.google.com/go/profiler"
"contrib.go.opencensus.io/exporter/stackdriver" "contrib.go.opencensus.io/exporter/stackdriver"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/exporter/jaeger"
"go.opencensus.io/plugin/ocgrpc" "go.opencensus.io/plugin/ocgrpc"
"go.opencensus.io/stats/view" "go.opencensus.io/stats/view"
"go.opencensus.io/trace" "go.opencensus.io/trace"
@ -128,6 +129,28 @@ func (s *server) ShipOrder(ctx context.Context, in *pb.ShipOrderRequest) (*pb.Sh
}, nil }, nil
} }
func initJaegerTracing() {
svcAddr := os.Getenv("JAEGER_SERVICE_ADDR")
if svcAddr == "" {
log.Info("jaeger initialization disabled.")
return
}
// Register the Jaeger exporter to be able to retrieve
// the collected spans.
exporter, err := jaeger.NewExporter(jaeger.Options{
Endpoint: fmt.Sprintf("http://%s", svcAddr),
Process: jaeger.Process{
ServiceName: "shippingservice",
},
})
if err != nil {
log.Fatal(err)
}
trace.RegisterExporter(exporter)
log.Info("jaeger initialization completed.")
}
func initStats(exporter *stackdriver.Exporter) { func initStats(exporter *stackdriver.Exporter) {
view.SetReportingPeriod(60 * time.Second) view.SetReportingPeriod(60 * time.Second)
view.RegisterExporter(exporter) view.RegisterExporter(exporter)
@ -138,7 +161,7 @@ func initStats(exporter *stackdriver.Exporter) {
} }
} }
func initTracing() { func initStackDriverTracing() {
// TODO(ahmetb) this method is duplicated in other microservices using Go // TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages. // since they are not sharing packages.
for i := 1; i <= 3; i++ { for i := 1; i <= 3; i++ {
@ -161,6 +184,11 @@ func initTracing() {
log.Warn("could not initialize stackdriver exporter after retrying, giving up") log.Warn("could not initialize stackdriver exporter after retrying, giving up")
} }
func initTracing() {
initJaegerTracing()
initStackDriverTracing()
}
func initProfiling(service, version string) { func initProfiling(service, version string) {
// TODO(ahmetb) this method is duplicated in other microservices using Go // TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages. // since they are not sharing packages.