|
1 | 1 | 'use strict' |
2 | 2 |
|
3 | | -const { MEASURED } = require('../../../ext/tags') |
4 | | -const { storage } = require('../../datadog-core') |
5 | | -const TracingPlugin = require('../../dd-trace/src/plugins/tracing') |
| 3 | +const LangChainTracingPlugin = require('./tracing') |
| 4 | +const LangChainLLMObsPlugin = require('../../dd-trace/src/llmobs/plugins/langchain') |
| 5 | +const CompositePlugin = require('../../dd-trace/src/plugins/composite') |
6 | 6 |
|
7 | | -const API_KEY = 'langchain.request.api_key' |
8 | | -const MODEL = 'langchain.request.model' |
9 | | -const PROVIDER = 'langchain.request.provider' |
10 | | -const TYPE = 'langchain.request.type' |
11 | | - |
12 | | -const LangChainHandler = require('./handlers/default') |
13 | | -const LangChainChatModelHandler = require('./handlers/language_models/chat_model') |
14 | | -const LangChainLLMHandler = require('./handlers/language_models/llm') |
15 | | -const LangChainChainHandler = require('./handlers/chain') |
16 | | -const LangChainEmbeddingHandler = require('./handlers/embedding') |
17 | | - |
18 | | -class LangChainPlugin extends TracingPlugin { |
| 7 | +class LangChainPlugin extends CompositePlugin { |
19 | 8 | static get id () { return 'langchain' } |
20 | | - static get operation () { return 'invoke' } |
21 | | - static get system () { return 'langchain' } |
22 | | - static get prefix () { |
23 | | - return 'tracing:apm:langchain:invoke' |
24 | | - } |
25 | | - |
26 | | - constructor () { |
27 | | - super(...arguments) |
28 | | - |
29 | | - const langchainConfig = this._tracerConfig.langchain || {} |
30 | | - this.handlers = { |
31 | | - chain: new LangChainChainHandler(langchainConfig), |
32 | | - chat_model: new LangChainChatModelHandler(langchainConfig), |
33 | | - llm: new LangChainLLMHandler(langchainConfig), |
34 | | - embedding: new LangChainEmbeddingHandler(langchainConfig), |
35 | | - default: new LangChainHandler(langchainConfig) |
| 9 | + static get plugins () { |
| 10 | + return { |
| 11 | + // ordering here is important - the llm observability plugin must come first |
| 12 | + // so that we can add annotations associated with the span before it finishes. |
| 13 | + // however, because the tracing plugin uses `bindStart` vs the llmobs' `start`, |
| 14 | + // the span is guaranteed to be created in the tracing plugin before the llmobs one is called |
| 15 | + llmobs: LangChainLLMObsPlugin, |
| 16 | + tracing: LangChainTracingPlugin |
36 | 17 | } |
37 | 18 | } |
38 | | - |
39 | | - bindStart (ctx) { |
40 | | - const { resource, type } = ctx |
41 | | - const handler = this.handlers[type] |
42 | | - |
43 | | - const instance = ctx.instance |
44 | | - const apiKey = handler.extractApiKey(instance) |
45 | | - const provider = handler.extractProvider(instance) |
46 | | - const model = handler.extractModel(instance) |
47 | | - |
48 | | - const tags = handler.getSpanStartTags(ctx, provider) || [] |
49 | | - |
50 | | - if (apiKey) tags[API_KEY] = apiKey |
51 | | - if (provider) tags[PROVIDER] = provider |
52 | | - if (model) tags[MODEL] = model |
53 | | - if (type) tags[TYPE] = type |
54 | | - |
55 | | - const span = this.startSpan('langchain.request', { |
56 | | - service: this.config.service, |
57 | | - resource, |
58 | | - kind: 'client', |
59 | | - meta: { |
60 | | - [MEASURED]: 1, |
61 | | - ...tags |
62 | | - } |
63 | | - }, false) |
64 | | - |
65 | | - const store = storage.getStore() || {} |
66 | | - ctx.currentStore = { ...store, span } |
67 | | - |
68 | | - return ctx.currentStore |
69 | | - } |
70 | | - |
71 | | - asyncEnd (ctx) { |
72 | | - const span = ctx.currentStore.span |
73 | | - |
74 | | - const { type } = ctx |
75 | | - |
76 | | - const handler = this.handlers[type] |
77 | | - const tags = handler.getSpanEndTags(ctx) || {} |
78 | | - |
79 | | - span.addTags(tags) |
80 | | - |
81 | | - span.finish() |
82 | | - } |
83 | | - |
84 | | - getHandler (type) { |
85 | | - return this.handlers[type] || this.handlers.default |
86 | | - } |
87 | 19 | } |
88 | 20 |
|
89 | 21 | module.exports = LangChainPlugin |
0 commit comments