Skip to content

Instantly share code, notes, and snippets.

@lmolkova
Created December 8, 2021 18:51
Show Gist options
  • Select an option

  • Save lmolkova/95e22b5d44c88543c12f96b8158234d7 to your computer and use it in GitHub Desktop.

Select an option

Save lmolkova/95e22b5d44c88543c12f96b8158234d7 to your computer and use it in GitHub Desktop.
package org.example.functions;
import com.azure.core.models.CloudEvent;
import com.azure.core.util.serializer.TypeReference;
import com.azure.messaging.eventgrid.EventGridEvent;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.EventGridTrigger;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapPropagator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Logger;
public class HttpTriggerFunction {
// make sure to enable Application Insights (preview) support for Azure Functions:
// https://docs.microsoft.com/azure/azure-monitor/app/monitor-functions
private final static Tracer TRACER = GlobalOpenTelemetry.getTracer("my-function");
private static final TextMapPropagator PROPAGATOR = W3CTraceContextPropagator.getInstance();
// Helper class that reads trace context from CloudEvent
private static final TextMapGetter<Map<String, Object>> GETTER = new TextMapGetter<Map<String, Object>>() {
@Override
public Iterable<String> keys(Map<String, Object> carrier) {
return carrier.keySet();
}
@Override
public String get(Map<String, Object> carrier, String key) {
return carrier.get(key).toString();
}
};
@FunctionName("HttpExample")
public HttpResponseMessage run(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST, HttpMethod.OPTIONS},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");
if (request.getHttpMethod() == HttpMethod.OPTIONS) {
String header = request.getHeaders().get("WebHook-Request-Origin");
return request.createResponseBuilder(HttpStatus.OK).header("Webhook-Allowed-Origin", header).build();
}
if (request.getBody().isPresent()) {
List<CloudEvent> events = CloudEvent.fromString(request.getBody().get());
events.stream().forEach( event -> {
Context traceContext = W3CTraceContextPropagator.getInstance().extract(Context.current(), event.getExtensionAttributes(), GETTER);
processWithTracing(event, traceContext, context.getLogger());
});
}
return request.createResponseBuilder(HttpStatus.OK).body("Hello").build();
}
@FunctionName("CloudEvent")
public void logEvent1(@EventGridTrigger(name = "cloudEvent") String eventsStr, final ExecutionContext context) {
List<CloudEvent> events = CloudEvent.fromString(eventsStr);
events.stream().forEach( event -> {
Context traceContext = W3CTraceContextPropagator.getInstance().extract(Context.current(), event.getExtensionAttributes(), GETTER);
processWithTracing(event, traceContext, context.getLogger());
});
}
@FunctionName("EventGridEvent")
public void logEvent2(@EventGridTrigger(name = "eventGridEvent") String eventsStr, final ExecutionContext context) {
List<EventGridEvent> events = EventGridEvent.fromString(eventsStr);
events.stream().forEach( event -> {
// For optimal performance, change data type to your model representing EventGridEvent payload.
// Make sure to add `traceparent` and `tracestate` properties to your model.
Map<String, Object> dataObj = event.getData().toObject(new TypeReference<Map<String, Object>>() { });
Context traceContext = W3CTraceContextPropagator.getInstance().extract(Context.current(), dataObj, GETTER);
processWithTracing(event, traceContext, context.getLogger());
});
}
private void processWithTracing(Object myEventData, Context traceContext, Logger logger) {
// Start a new span: it is nested under function execution
// and linked to context from the event.
Span span = TRACER.spanBuilder("Process event")
.addLink(Span.fromContext(traceContext).getSpanContext())
.startSpan();
try (Scope unused = span.makeCurrent()) {
// process the event here
logger.info("Processing event... " + myEventData);
} catch (Exception ex) {
span.setStatus(StatusCode.ERROR);
span.end();
} finally {
span.end();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment