forked from temporalio/samples-typescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add mtls and opentelemetry samples (#5)
* add mtls and opentelemetry samples * Standardize workflow script & file name * Add prettier to match sdk-node * Standardize package.json
- Loading branch information
Showing
17 changed files
with
392 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"printWidth": 120, | ||
"singleQuote": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "hello-world-mtls", | ||
"version": "0.1.0", | ||
"private": true, | ||
"scripts": { | ||
"build": "tsc --build", | ||
"build.watch": "tsc --build --watch", | ||
"start": "ts-node src/worker.ts", | ||
"start.watch": "nodemon src/worker.ts", | ||
"workflow": "ts-node src/execute-workflow.ts" | ||
}, | ||
"dependencies": { | ||
"temporalio": "^0.4.1" | ||
}, | ||
"devDependencies": { | ||
"@tsconfig/node16": "^1.0.0", | ||
"nodemon": "^2.0.12", | ||
"ts-node": "^10.2.1", | ||
"typescript": "^4.4.2" | ||
}, | ||
"nodemonConfig": { | ||
"watch": [ | ||
"src" | ||
], | ||
"ext": "ts", | ||
"execMap": { | ||
"ts": "ts-node" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export async function greet(name: string): Promise<string> { | ||
return `Hello, ${name}!`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import fs from 'fs'; | ||
import { Connection, WorkflowClient } from '@temporalio/client'; | ||
import { Example } from './interfaces/workflows'; | ||
import { getEnv, Env } from './mtls-env'; | ||
|
||
/** | ||
* Schedule a Workflow connecting with mTLS, configuration is provided via environment variables. | ||
* Note that serverNameOverride and serverRootCACertificate are optional. | ||
*/ | ||
async function run({ | ||
address, | ||
namespace, | ||
clientCertPath, | ||
clientKeyPath, | ||
serverNameOverride, | ||
serverRootCACertificatePath, | ||
taskQueue, | ||
}: Env) { | ||
let serverRootCACertificate: Buffer | undefined = undefined; | ||
if (serverRootCACertificatePath) { | ||
serverRootCACertificate = fs.readFileSync(serverRootCACertificatePath); | ||
} | ||
const connection = new Connection({ | ||
address, | ||
tls: { | ||
serverNameOverride, | ||
serverRootCACertificate, | ||
clientCertPair: { | ||
crt: fs.readFileSync(clientCertPath), | ||
key: fs.readFileSync(clientKeyPath), | ||
}, | ||
}, | ||
}); | ||
await connection.untilReady(); | ||
const client = new WorkflowClient(connection.service, { namespace }); | ||
// Create a typed client using the Example Workflow interface, | ||
const workflow = client.stub<Example>('example', { taskQueue }); | ||
const result = await workflow.execute('Temporal'); | ||
console.log(result); // Hello, Temporal! | ||
} | ||
|
||
run(getEnv()).then( | ||
() => process.exit(0), | ||
(err) => { | ||
console.error(err); | ||
process.exit(1); | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Workflow } from '@temporalio/workflow'; | ||
|
||
// Extend the generic Workflow interface to check that Example is a valid workflow interface | ||
// Workflow interfaces are useful for generating type safe workflow clients | ||
export interface Example extends Workflow { | ||
main(name: string): Promise<string>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Helpers for configuring the mTLS client and worker samples | ||
|
||
function requiredEnv(name: string): string { | ||
const value = process.env[name]; | ||
if (!value) { | ||
throw new ReferenceError(`${name} environment variable is not defined`); | ||
} | ||
return value; | ||
} | ||
|
||
export interface Env { | ||
address: string; | ||
namespace: string; | ||
clientCertPath: string; | ||
clientKeyPath: string; | ||
serverNameOverride?: string; | ||
serverRootCACertificatePath?: string; | ||
taskQueue: string; | ||
} | ||
|
||
export function getEnv(): Env { | ||
return { | ||
address: requiredEnv('TEMPORAL_ADDRESS'), | ||
namespace: requiredEnv('TEMPORAL_NAMESPACE'), | ||
clientCertPath: requiredEnv('TEMPORAL_CLIENT_CERT_PATH'), | ||
clientKeyPath: requiredEnv('TEMPORAL_CLIENT_KEY_PATH'), | ||
serverNameOverride: process.env.TEMPORAL_SERVER_NAME_OVERRIDE, | ||
serverRootCACertificatePath: process.env.TEMPORAL_SERVER_ROOT_CA_CERT_PATH, | ||
taskQueue: process.env.TEMPORAL_TASK_QUEUE || 'tutorial', | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import fs from 'fs'; | ||
import { Worker, Core } from '@temporalio/worker'; | ||
import { getEnv, Env } from './mtls-env'; | ||
|
||
/** | ||
* Run a Worker with an mTLS connection, configuration is provided via environment variables. | ||
* Note that serverNameOverride and serverRootCACertificate are optional. | ||
*/ | ||
async function run({ | ||
address, | ||
namespace, | ||
clientCertPath, | ||
clientKeyPath, | ||
serverNameOverride, | ||
serverRootCACertificatePath, | ||
taskQueue, | ||
}: Env) { | ||
let serverRootCACertificate: Buffer | undefined = undefined; | ||
if (serverRootCACertificatePath) { | ||
serverRootCACertificate = fs.readFileSync(serverRootCACertificatePath); | ||
} | ||
|
||
await Core.install({ | ||
serverOptions: { | ||
address, | ||
namespace, | ||
tls: { | ||
serverNameOverride, | ||
serverRootCACertificate, | ||
// See docs for other TLS options | ||
clientCertPair: { | ||
crt: fs.readFileSync(clientCertPath), | ||
key: fs.readFileSync(clientKeyPath), | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
const worker = await Worker.create({ | ||
workDir: __dirname, | ||
taskQueue, | ||
}); | ||
console.log('Worker connection succesfully established'); | ||
// Start accepting tasks on the `tutorial` queue | ||
await worker.run(); | ||
} | ||
|
||
run(getEnv()).catch((err) => { | ||
console.error(err); | ||
process.exit(1); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Context } from '@temporalio/workflow'; | ||
import * as activities from '../activities'; | ||
|
||
const { greet } = Context.configureActivities<typeof activities>({ | ||
type: 'remote', | ||
startToCloseTimeout: '30 minutes', | ||
}); | ||
|
||
// A workflow that simply calls an activity | ||
async function main(name: string): Promise<string> { | ||
return greet(name); | ||
} | ||
|
||
export const workflow = { main }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"extends": "@tsconfig/node16/tsconfig.json", | ||
"version": "4.4.2", | ||
"compilerOptions": { | ||
"emitDecoratorMetadata": false, | ||
"experimentalDecorators": false, | ||
"declaration": true, | ||
"declarationMap": true, | ||
"sourceMap": true, | ||
"composite": true, | ||
"rootDir": "./src", | ||
"outDir": "./lib" | ||
}, | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"exclude": [ | ||
"node_modules" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "interceptors-opentelemetry-sample", | ||
"version": "0.1.0", | ||
"private": true, | ||
"scripts": { | ||
"build": "tsc --build", | ||
"build.watch": "tsc --build --watch", | ||
"start": "ts-node src/worker.ts", | ||
"start.watch": "nodemon src/worker.ts", | ||
"workflow": "ts-node src/execute-workflow.ts" | ||
}, | ||
"dependencies": { | ||
"@temporalio/interceptors-opentelemetry": "^0.1.2", | ||
"temporalio": "^0.4.1" | ||
}, | ||
"devDependencies": { | ||
"@tsconfig/node14": "^1.0.0", | ||
"nodemon": "^2.0.12", | ||
"ts-node": "^10.2.1", | ||
"typescript": "^4.2.2" | ||
}, | ||
"nodemonConfig": { | ||
"watch": [ | ||
"src" | ||
], | ||
"ext": "ts", | ||
"execMap": { | ||
"ts": "ts-node" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export async function greet(name: string): Promise<string> { | ||
return `Hello, ${name}!`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Connection, WorkflowClient } from '@temporalio/client'; | ||
import { OpenTelemetryWorkflowClientCallsInterceptor } from '@temporalio/interceptors-opentelemetry/lib/client'; | ||
import { Example } from './interfaces/workflows'; | ||
import { setupOpentelemetry } from './worker/setup'; | ||
|
||
async function run() { | ||
const otel = await setupOpentelemetry(); | ||
// Connect to localhost with default ConnectionOptions, | ||
// pass options to the Connection constructor to configure TLS and other settings. | ||
const connection = new Connection({}); | ||
// Attach the OpenTelemetryWorkflowClientCallsInterceptor to the client. | ||
const client = new WorkflowClient(connection.service, { | ||
interceptors: { | ||
calls: [() => new OpenTelemetryWorkflowClientCallsInterceptor()], | ||
}, | ||
}); | ||
// Create a typed client using the Example Workflow interface, | ||
// Workflow will be started in the "default" namespace unless specified otherwise. | ||
const example = client.stub<Example>('example', { | ||
taskQueue: 'interceptors-opentelemetry-example', | ||
}); | ||
const result = await example.execute('Temporal'); | ||
console.log(result); // Hello, Temporal! | ||
await otel.sdk.shutdown(); | ||
} | ||
|
||
run().catch((err) => { | ||
console.error(err); | ||
process.exit(1); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Workflow } from '@temporalio/workflow'; | ||
|
||
// Extend the generic Workflow interface to check that Example is a valid workflow interface | ||
// Workflow interfaces are useful for generating type safe workflow clients | ||
export interface Example extends Workflow { | ||
main(name: string): Promise<string>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { DefaultLogger, Worker } from '@temporalio/worker'; | ||
import { OpenTelemetryDependencies } from '@temporalio/interceptors-opentelemetry/lib/workflow'; | ||
import { | ||
OpenTelemetryActivityInboundInterceptor, | ||
makeWorkflowExporter, | ||
} from '@temporalio/interceptors-opentelemetry/lib/worker'; | ||
import { setupOpentelemetry } from './setup'; | ||
|
||
async function main() { | ||
const otel = await setupOpentelemetry(); | ||
|
||
// Automatically locate and register Activities and Workflows relative to __dirname | ||
// (assuming package was bootstrapped with `npm init @temporalio`). | ||
// Worker connects to localhost by default and uses console error for logging. | ||
// Customize the Worker by passing more options to create(). | ||
// create() tries to connect to the server and will throw if a connection could not be established. | ||
// You may create multiple Workers in a single process in order to poll on multiple task queues. | ||
// In order to configure the server connection parameters and other global options, | ||
// use the Core.install() method to configure the Rust Core SDK singleton. | ||
const worker = await Worker.create<{ dependencies: OpenTelemetryDependencies }>({ | ||
workDir: __dirname, | ||
// Silence the Worker logs to better see the span output | ||
logger: new DefaultLogger('WARNING'), | ||
taskQueue: 'interceptors-opentelemetry-example', | ||
dependencies: { | ||
exporter: makeWorkflowExporter(otel.exporter), | ||
}, | ||
// Registers opentelemetry interceptors for Workflow and Activity calls | ||
interceptors: { | ||
workflowModules: ['example'], // example contains both workflow and interceptors | ||
activityInbound: [(_ctx) => new OpenTelemetryActivityInboundInterceptor()], | ||
}, | ||
}); | ||
await worker.run(); | ||
await otel.sdk.shutdown(); | ||
} | ||
|
||
main().then( | ||
() => void process.exit(0), | ||
(err) => { | ||
console.error(err); | ||
process.exit(1); | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { ExportResult } from '@opentelemetry/core'; | ||
import { ConsoleSpanExporter, ReadableSpan } from '@opentelemetry/tracing'; | ||
import { NodeSDK } from '@opentelemetry/sdk-node'; | ||
import { SpanName } from '@temporalio/interceptors-opentelemetry/lib/workflow'; | ||
|
||
// Only print the spans generated by interceptors | ||
export const instrumentedSpans = new Set<string>(Object.values(SpanName)); | ||
|
||
export class SpanExporter extends ConsoleSpanExporter { | ||
public export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void { | ||
const filtered = spans.filter(({ name }) => instrumentedSpans.has(name)); | ||
super.export(filtered, resultCallback); | ||
} | ||
} | ||
|
||
export interface OpentelemtryEnv { | ||
sdk: NodeSDK; | ||
exporter: SpanExporter; | ||
} | ||
|
||
export async function setupOpentelemetry(): Promise<OpentelemtryEnv> { | ||
const exporter = new SpanExporter(); | ||
const sdk = new NodeSDK({ traceExporter: exporter }); | ||
await sdk.start(); | ||
return { sdk, exporter }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { WorkflowInterceptors } from '@temporalio/workflow'; | ||
import { | ||
OpenTelemetryInboundInterceptor, | ||
OpenTelemetryOutboundInterceptor, | ||
registerOpentelemetryTracerProvider, | ||
} from '@temporalio/interceptors-opentelemetry/lib/workflow'; | ||
import { Example } from '../interfaces/workflows'; | ||
import { greet } from '@activities/greeter'; | ||
|
||
// A workflow that simply calls an activity | ||
async function main(name: string): Promise<string> { | ||
return greet(name); | ||
} | ||
|
||
// Declare the workflow's type to be checked by the Typescript compiler | ||
export const workflow: Example = { main }; | ||
|
||
export const interceptors: WorkflowInterceptors = { | ||
inbound: [new OpenTelemetryInboundInterceptor()], | ||
outbound: [new OpenTelemetryOutboundInterceptor()], | ||
}; | ||
|
||
registerOpentelemetryTracerProvider(); |
Oops, something went wrong.