This application is issued from Angular tutorial
Instrumentation code below is coming from https://github.com/open-telemetry/opentelemetry-demo/blob/main/docs/services/frontend.md#browser-instrumentation
- Install the OpenTelemetry libraries
npm install @opentelemetry/api @opentelemetry/core @opentelemetry/sdk-trace-web @opentelemetry/sdk-trace-base @opentelemetry/instrumentation @opentelemetry/auto-instrumentations-web @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/exporter-trace-otlp-http @opentelemetry/context-zone
- Create tracing wrapper file
./src/utils/telemetry/FrontendTracer.ts
import {
CompositePropagator,
W3CBaggagePropagator,
W3CTraceContextPropagator,
} from '@opentelemetry/core';
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web';
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { environment } from './../../environments/environment';
const FrontendTracer = async () => {
const { ZoneContextManager } = await import('@opentelemetry/context-zone');
const provider = new WebTracerProvider({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: environment.OTEL_SERVICE_NAME,
}),
});
//const traceExporter = new ConsoleSpanExporter();
//const traceExporter = new OTLPTraceExporter();
// Sending directly to Lightstep, you should add token in your headers
// headers: { 'lightstep-access-token': environment.LIGHTSTEP_ACCESS_TOKEN },
const traceExporter = new OTLPTraceExporter({
url: environment.OTEL_EXPORTER_OTLP_ENDPOINT,
});
provider.addSpanProcessor(new SimpleSpanProcessor(traceExporter));
const contextManager = new ZoneContextManager();
provider.register({
contextManager,
propagator: new CompositePropagator({
propagators: [
new W3CBaggagePropagator(),
new W3CTraceContextPropagator(),
],
}),
});
registerInstrumentations({
tracerProvider: provider,
instrumentations: [
getWebAutoInstrumentations({
'@opentelemetry/instrumentation-fetch': {
propagateTraceHeaderCorsUrls: /.*/,
clearTimingResources: true,
},
}),
],
});
};
export default FrontendTracer;
- add use of tracer in your application, for this, put these 2 lines just after the list of imports in
src/main.ts
:
import FrontendTracer from './utils/telemetry/FrontendTracer';
if (typeof window !== 'undefined') FrontendTracer();
NOTE: You can also put them in
src/app/app.module.ts
using path../utils/telemetry/FrontendTracer
instead
- in order to manage you trace exporter properties (endpoint, access token), we will generate an environment file before each build using this script
./src/environments/createEnvFile.sh
#! /bin/sh
#### GENERATOR FOR ENVIRONMENT FILE
## Variables defined here with $ prefix can be defined using a shell EXPORT before launching the script
## Define LIGHTSTEP_ACCESS_TOKEN variable only if you want to directly send traces to Lightstep for test purposes
## Define OTEL_EXPORTER_OTLP_ENDPOINT to go to your OpenTelemetry collector or directly to Lightstep for test purposes
## For Otel Collector, you can use: https://<YOU_OTEL_COLLECTOR_HOST>:4318/v1/traces
## For Lightstep, you can use: https://ingest.lightstep.com:443/traces/otlp/v0.9
## Recommended architecture in production is to go through Otel Collector
SCRIPTDIR=$(dirname "$0")
cat <<EOF > ./$SCRIPTDIR/environment.ts
export const environment = {
production: false,
title: 'Local Environment Heading',
LIGHTSTEP_ACCESS_TOKEN: '$LIGHTSTEP_ACCESS_TOKEN',
OTEL_EXPORTER_OTLP_ENDPOINT: '$OTEL_EXPORTER_OTLP_ENDPOINT',
OTEL_SERVICE_NAME: 'angular-frontend',
};
EOF
- before each build, you will have to export the environment variables and then, run script
./src/environments/createEnvFile.sh
to generate yourenvironment.ts
file
export OTEL_EXPORTER_OTLP_ENDPOINT=<YOUR_VALUE>
- example of Collector endpoint for traces over http: `https://otel-collector:4318/v1/traces`
- see [here](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http) for more code examples
- example of Lightstep endpoint for traces over http: `https://ingest.lightstep.com:443/traces/otlp/v0.9`
- see [here](https://docs.lightstep.com/otel/general-otlp-configuration) for more Lightstep endpoints
- if you want to send traces directly to Lightstep , you should also export you token value
```shell
export LIGHTSTEP_ACCESS_TOKEN=<YOUR_VALUE>
```
- Finally, build and start the application using
ng serve
- You can now test it connecting to http://localhost:4200
-
on Backend build, getting error:
# Starting phase: build 2022-02-14T02:47:02.527Z [INFO]: �[31mInvalid feature flag configuration�[39m 2022-02-14T02:47:02.530Z [INFO]: �[31mThese feature flags are defined in the "amplify/cli.json" configuration file and are unknown to the currently running Amplify CLI:�[39m �[31m - project�[39m
- check you version of amplify cli with
amplify --version
- Then update version in your AWS Amplify console -> Build Settings -> Build Image Settings -> Live package updates -> Amplify CLI
- see more details here
- check you version of amplify cli with
-
on Frontend build, getting error:
Error: src/main.ts:5:30 - error TS2307: Cannot find module 'aws-amplify' or its corresponding type declarations. 5 import { Amplify, API } from 'aws-amplify';
- install aws-amplify library with
npm install aws-amplify
- install aws-amplify library with
-
on Frontend build, getting error: `Error: src/main.ts:6:23 - error TS7016: Could not find a declaration file for module './aws-exports'``
- if present, remove
aws-export
from your.gitignore
file
- if present, remove
-
on Frontend build, getting error:
error TS7006: Parameter 'error' implicitly has an 'any' type
- add
"noImplicitAny": false,
in yourtsconfig.json
file
- add
-
At runtime, getting error in browser console:
Uncaught ReferenceError: global is not defined
- update
./src/index.html
to add at the beginning:
<script> if (global === undefined) { var global = window; } </script>
- update
-
At runtime, getting error in browser console:
Access to XMLHttpRequest at 'ingest.lightstep.com:443' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted
- you forgot to put
https://
orhttp:
at the beginning of your OTEL_EXPORTER_OTLP_ENDPOINT YOUR_VALUE
- you forgot to put
-
At runtime, getting error in browser console:
Access to resource at 'https://ingest.lightstep.com/traces/otlp/v0.9' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'
- you may have forgotten to put an access token value in your header
- see
src/utils/telemetry/FrontendTracer-toLightstep.ts
as example
-
At runtime, getting error in browser console:
Access to XMLHttpRequest at 'https://ingest.lightstep.com/traces/otlp/v0.9' from origin 'http://localhost:4200' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
- check your request header, you may have unnecessary information
-
At runtime, getting error code http 400 in browser console when calling OTLP backend:
- check if you use the correct Lightstep access token
-
At runtime, getting error in browser console when calling external API: `Access to XMLHttpRequest at 'https://your_api' from origin 'https://your_app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.``
- update your lambda function to return CORS header. Example below is for node JS
exports.handler = async (event) => {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "https://www.example.com",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
- see details [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html)