Skip to content

Commit

Permalink
Allow setting Gateway url in Lambda examples (signalfx#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
rmfitzpatrick authored and mpetazzoni committed Dec 24, 2018
1 parent 70c4d6b commit 91f320d
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 55 deletions.
13 changes: 8 additions & 5 deletions aws-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ requests to an API Gateway endpoint.
| ↑
Trigger Respond
↓ |
[Your Lambda Function] — Spans via HTTP POST → [SignalFx]
[Your Lambda Function] — Spans via HTTP POST → [SignalFx Gateway]
```

If you are using asynchronous or non-`RequestResponse` invocation types, the examples can still serve
Expand All @@ -37,14 +37,17 @@ will need to be updated to reflect your application's functionality.
## Deployment and Configuration

Each example provides a description of generating and configuring a Deployment Package for its respective
runtime. All of these examples presume the setting of the `SIGNALFX_ACCESS_TOKEN` environment variable
to associate your traces with your organization. If this variable is not set for your Lambda function via the
AWS Console or CLI, all invocations will generate an internal server error that will be logged to CloudWatch.
runtime. All of these examples presume the setting of the `SIGNALFX_INGEST_URL` environment variable to
forward your traces to your deployed SignalFx Gateway or `SIGNALFX_ACCESS_TOKEN` for direct association
with your organization. **Please note that bypassing the SignalFx Gateway is for demonstration purposes
only, and is not a supported deployment pattern. The Gateway enables many powerful analytical features for
μAPM.** If neither the variables are set for your Lambda function via the AWS Console or CLI, all invocations
will generate an internal server error that will be logged to CloudWatch.

```
$ update-function-configuration \
--function-name <MyTracedFunction> \
--environment Variables={SIGNALFX_ACCESS_TOKEN=<MyAccessToken>}
--environment Variables={SIGNALFX_INGEST_URL=<MyGateway>}
```


Expand Down
4 changes: 2 additions & 2 deletions aws-lambda/jaeger-go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ $ zip my_traced_golang_lambda.zip ./jaeger-go

The resulting `my_traced_golang_lambda.zip` can be uploaded to S3 or in your browser via the AWS Console
during function creation. Register your handler as `jaeger-go` and don't forget to set the
`SIGNALFX_ACCESS_TOKEN` environment variable. You should be able test the application with
the following test event:
`SIGNALFX_INGEST_URL` environment variable to point to your Gateway. You should be able test the application
with the following test event:

```
{
Expand Down
20 changes: 14 additions & 6 deletions aws-lambda/jaeger-go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,15 @@ func handleRequest(ctx context.Context, request events.APIGatewayProxyRequest) (

func createTracer() (opentracing.Tracer, io.Closer) {
accessToken := os.Getenv("SIGNALFX_ACCESS_TOKEN")
if accessToken == "" {
// Raised panic contexts will be logged to CloudWatch
panic(errors.New("You must set the SIGNALFX_ACCESS_TOKEN Lambda environment variable to be your token."))
ingestUrl := os.Getenv("SIGNALFX_INGEST_URL")
if ingestUrl == "" {
if accessToken == "" {
// Raised panic contexts will be logged to CloudWatch
panic(errors.New("You must set the SIGNALFX_ACCESS_TOKEN Lambda environment variable to be your token " +
"if you don't set SIGNALFX_INGEST_URL to point to your Gateway."))
}
ingestUrl = "https://ingest.signalfx.com/v1/trace"
}
const ingestUrl = "https://ingest.signalfx.com/v1/trace"

// This creates a configuration struct for Jaeger based on environment variables.
// See https://github.com/jaegertracing/jaeger-client-go/blob/master/README.md#environment-variables
Expand All @@ -125,7 +129,11 @@ func createTracer() (opentracing.Tracer, io.Closer) {

// Create a Jaeger HTTP Thrift transport, pointing it to our trace endpoint
// which accepts thrift encoded spans.
transport := transport.NewHTTPTransport(ingestUrl, transport.HTTPBasicAuth("auth", accessToken))
var options []transport.HTTPOption
if accessToken != "" {
options = append(options, transport.HTTPBasicAuth("auth", accessToken))
}
httpTransport := transport.NewHTTPTransport(ingestUrl, options...)

// Here we override the service name for the tracer for this example. This
// would otherwise be set from the env var JAEGER_SERVICE_NAME.
Expand All @@ -140,7 +148,7 @@ func createTracer() (opentracing.Tracer, io.Closer) {
}

// This creates the Jaeger tracer from the configuration, using our Thrift HTTP transport.
tracer, closer, err := cfg.NewTracer(jaegercfg.Reporter(jaeger.NewRemoteReporter(transport)))
tracer, closer, err := cfg.NewTracer(jaegercfg.Reporter(jaeger.NewRemoteReporter(httpTransport)))
if err != nil {
panic(errors.New(fmt.Sprintf("Could not initialize jaeger tracer: %v", err.Error())))
}
Expand Down
4 changes: 2 additions & 2 deletions aws-lambda/jaeger-java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ $ mvn package

The resulting `./target/lambda-java-example.jar` can be uploaded to S3 or in your browser via the AWS Console
during function creation. Register your handler as `example.RoulettePlayer::handleRequest` and don't forget
to set the `SIGNALFX_ACCESS_TOKEN` environment variable. You should be able verify the application with
the following test event:
to set the `SIGNALFX_INGEST_URL` environment variable to point to your Gateway. You should be able verify the
application with the following test event:

```
{
Expand Down
37 changes: 21 additions & 16 deletions aws-lambda/jaeger-java/src/main/java/example/RoulettePlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import zipkin2.reporter.okhttp3.OkHttpSender;

// This example is for an API Gateway-proxied Lambda function. Use your custom event parameters where needed.
public class RoulettePlayer implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent>{
public class RoulettePlayer implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

// Roulette wheel address to position mapping, helpful for "00"
private static final String[] numToChoice = initNumToChoice();
Expand All @@ -61,19 +61,23 @@ private static final Map<String, Integer> initChoiceToNum() {
private Tracer tracer;

/**
* It's expected that there will be a single instance of an opentracing.Tracer per process,
* It's expected that there will be a single instance of an opentracing.Tracer per process,
* and it's a best practice to register it with io.opentracing.util.GlobalTracer.
* However, since no RequestHandler will ever field more than one request at a time in Lambda
* we will cycle through io.opentracing.Tracer member instances to allow forcing a span flush
* at the end of each request.
*/
private static io.opentracing.Tracer initTracer() {
String ingestUrl = "https://ingest.signalfx.com/v1/trace";
String ingestUrl = System.getenv("SIGNALFX_INGEST_URL");
String accessToken = System.getenv("SIGNALFX_ACCESS_TOKEN");
if (accessToken == null) {
throw new RuntimeException(
"You must set the SIGNALFX_ACCESS_TOKEN Lambda environment variable to be your token."
);
if (ingestUrl == null) {
if (accessToken == null) {
throw new RuntimeException(
"You must set the SIGNALFX_ACCESS_TOKEN Lambda environment variable to be your token " +
"if you don't set SIGNALFX_INGEST_URL to point to your Gateway."
);
}
ingestUrl = "https://ingest.signalfx.com/v1/trace";
}

// Build the sender that does the HTTP request containing spans to our ingest server.
Expand All @@ -83,10 +87,11 @@ private static io.opentracing.Tracer initTracer() {

// Add an interceptor to inject the SignalFx X-SF-Token auth header.
senderBuilder.clientBuilder().addInterceptor(chain -> {
Request request = chain.request().newBuilder()
.addHeader("X-SF-Token", accessToken)
.build();

Request.Builder builder = chain.request().newBuilder();
if (accessToken != null) {
builder.addHeader("X-SF-Token", accessToken);
}
Request request = builder.build();
return chain.proceed(request);
});

Expand Down Expand Up @@ -169,7 +174,7 @@ public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent re
// This is a Jaeger-specific requirement to make sure the Tracer flushes
// and sends its spans since this is a short lived handler that regenerates
// the Tracer member variable with every invocation.
((io.jaegertracing.internal.JaegerTracer) tracer).close();
((io.jaegertracing.internal.JaegerTracer) tracer).close();
}
}

Expand Down Expand Up @@ -198,19 +203,19 @@ private String getChoice(APIGatewayProxyRequestEvent requestEvent) {
choice = "win";
winFlag = true;
} else if (queryParameters.containsKey("choice")
&& choiceToNum.containsKey(queryParameters.get("choice"))) {
&& choiceToNum.containsKey(queryParameters.get("choice"))) {
choice = queryParameters.get("choice");
span.log("Request contains valid choice " + choice);
} else {
choice = getRandomPosition();
span.setTag("randomChoice", choice);
choice = getRandomPosition();
span.setTag("randomChoice", choice);
span.log("Request didn't provide valid choice. Using " + choice + " selected at random.");
}
span.setTag("winFlag", winFlag);
return choice;
}

/**
/**
* Converts a long to Zipkin trace ID format. Per OpenTracing, trace IDs are implementation
* specific, so this Jaeger interface is not intended for instrumentation and is for
* ease of demo trace retrieval only.
Expand Down
4 changes: 2 additions & 2 deletions aws-lambda/jaeger-nodejs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ $ zip -r my_traced_node_lambda.zip *

The resulting `my_traced_node_lambda.zip` can be uploaded to S3 or in your browser via the AWS Console
during function creation. Register your handler as `index.requestHandler` and don't forget to set the
`SIGNALFX_ACCESS_TOKEN` environment variable. You should be able test the application with
the following test event:
`SIGNALFX_INGEST_URL` environment variable to point to your Gateway. You should be able test the application
with the following test event:

```
{
Expand Down
19 changes: 13 additions & 6 deletions aws-lambda/jaeger-nodejs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,12 @@ function handleRequest(event, context) {

function createTracer() {
const accessToken = process.env.SIGNALFX_ACCESS_TOKEN;
if (!accessToken) {
throw new Error('You must set the SIGNALFX_ACCESS_TOKEN Lambda environment variable to be your token.');
let ingestUrl = process.env.SIGNALFX_INGEST_URL;
if (!ingestUrl) {
if (!accessToken) {
throw new Error('You must set the SIGNALFX_ACCESS_TOKEN Lambda environment variable to be your token.');
}
ingestUrl = 'https://ingest.signalfx.com/v1/trace'
}

const config = {
Expand All @@ -101,13 +105,16 @@ function createTracer() {
param: 1,
},
reporter: {
collectorEndpoint: 'https://ingest.signalfx.com/v1/trace',
// SignalFx supports Basic authentication with username "auth" and access token as password
username: 'auth',
password: accessToken,
collectorEndpoint: ingestUrl,
},
};

if (accessToken) {
// SignalFx supports Basic authentication with username "auth" and access token as password
config.reporter.username = 'auth'
config.reporter.password = accessToken
}

const options = { logger: console };
const tracer = initTracer(config, options);
// Register our tracer instance as the global tracer for easy access
Expand Down
4 changes: 2 additions & 2 deletions aws-lambda/jaeger-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ $ zip -r my_traced_python_lambda.zip *

The resulting `my_traced_python_lambda.zip` can be uploaded to S3 or in your browser via the AWS Console
during function creation. Register your handler as `example.request_handler` and don't forget to set the
`SIGNALFX_ACCESS_TOKEN` environment variable. You should be able test the application with
the following test event:
`SIGNALFX_INGEST_URL` environment variable to point to your Gateway. You should be able test the application
with the following test event:

```
{
Expand Down
32 changes: 18 additions & 14 deletions aws-lambda/jaeger-python/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,27 @@ def handle_request(self, event, context):

def create_tracer(self):
access_token = os.getenv('SIGNALFX_ACCESS_TOKEN')
if access_token is None:
raise Exception('You must set the SIGNALFX_ACCESS_TOKEN Lambda environment variable to be your token.')
ingest_url = os.getenv('SIGNALFX_INGEST_URL')

if ingest_url is None:
if access_token is None:
raise Exception("You must set the SIGNALFX_ACCESS_TOKEN Lambda environment variable to be your token "
"if you don't set SIGNALFX_INGEST_URL to point to your Gateway.")
ingest_url = 'https://ingest.signalfx.com/v1/trace'

# Establish a jaeger-client-python configuration to report spans to SignalFx
config = {'sampler': {'type': 'const',
'param': 1},
'jaeger_endpoint': ingest_url,
'reporter_flush_interval': .01,
'logging': False} # Report helpful span submission statements and errors to log handler

if access_token is not None:
# Required static username for Access Token authentication via Basic Access
config.update(dict(jaeger_user='auth', jaeger_password=access_token))

config = Config(
config={
'sampler': {
'type': 'const',
'param': 1,
},
'jaeger_endpoint': 'https://ingest.signalfx.com/v1/trace',
'jaeger_format_params': '', # No format query parameters required by SignalFx
'jaeger_user': 'auth', # Required static username for Access Token authentication via Basic Access
'jaeger_password': access_token,
'reporter_flush_interval': .01,
'logging': False, # Report helpful span submission statements and errors to log handler
},
config=config,
service_name='signalfx-lambda-python-example',
validate=True, # Have jaeger_client fail quickly on invalid configuration
)
Expand Down

0 comments on commit 91f320d

Please sign in to comment.