Skip to content

Commit

Permalink
LaunchDarkly: Add the option to specify a custom events host name (se…
Browse files Browse the repository at this point in the history
…gmentio#1690)

* Add enable_batching to destination action (#9)

Co-authored-by: Kelly Hofmann <khofmann@launchdarkly.com>
Co-authored-by: Clifford Tawiah <ctawiah@launchdarkly.com>
Co-authored-by: Kelly Hofmann <55991524+k3llymariee@users.noreply.github.com>
Co-authored-by: Cliff Tawiah <82856282+ctawiah@users.noreply.github.com>
Co-authored-by: Molly <molly.jones@launchdarkly.com>

* LaunchDarkly: Add the option to specify a custom events host name

---------

Co-authored-by: Kelly Hofmann <khofmann@launchdarkly.com>
Co-authored-by: Clifford Tawiah <ctawiah@launchdarkly.com>
Co-authored-by: Kelly Hofmann <55991524+k3llymariee@users.noreply.github.com>
Co-authored-by: Cliff Tawiah <82856282+ctawiah@users.noreply.github.com>
Co-authored-by: Molly <molly.jones@launchdarkly.com>
  • Loading branch information
6 people authored Nov 1, 2023
1 parent 9a724fa commit 97ebdf8
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,13 @@ describe('LaunchDarkly', () => {
}
await expect(testDestination.testAuthentication(authData)).rejects.toThrowError()
})
it('should succeed if a custom host name is provided', async () => {
nock(`https://clientsdk.launchdarkly.com`).head(`/sdk/goals/invalid`).reply(404, {})
const authData = {
client_id: 'anything',
events_host_name: 'events2.launchdarkly.com'
}
await expect(testDestination.testAuthentication(authData)).resolves.not.toThrowError()
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,37 @@ describe('LaunchDarkly.aliasUser', () => {
])
})

it('should send an alias event to a custom host for identify events when specified in the settings', async () => {
const customEventsHost = 'events2.launchdarkly.com'
const settingsWithCustomHost: Settings = { ...testSettings, events_host_name: customEventsHost }
nock(`https://${customEventsHost}`).post(`/events/bulk/${testSettings.client_id}`).reply(202)

const event = createTestEvent({
type: 'identify',
userId: 'user1234',
anonymousId: '701a9c00-aabe-4074-80b7-0fd6cab41c08',
timestamp: '2022-03-30T17:24:58Z'
})

const responses = await testDestination.testAction(actionSlug, {
event,
settings: settingsWithCustomHost,
useDefaultMappings: true
})
expect(responses.length).toBe(1)
expect(responses[0].status).toBe(202)
expect(responses[0].options.json).toMatchObject([
{
kind: 'alias',
key: 'user1234',
previousKey: '701a9c00-aabe-4074-80b7-0fd6cab41c08',
contextKind: 'user',
previousContextKind: 'anonymousUser',
creationDate: 1648661098000
}
])
})

it('should send an identify event to LaunchDarkly for alias events with default mapping', async () => {
nock('https://events.launchdarkly.com').post(`/events/bulk/${testSettings.client_id}`).reply(202)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const action: ActionDefinition<Settings, Payload> = {
perform: (request, { payload, settings }) => {
const event = convertPayloadToLDEvent(payload)

return request(getEventsUrl(settings.client_id), {
return request(getEventsUrl(settings), {
method: 'post',
json: [event]
})
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Settings } from './generated-types'

import aliasUser from './aliasUser'
import trackEvent from './trackEvent'
import { DEFAULT_EVENTS_HOST_NAME } from './utils'

const presets: Preset[] = [
{
Expand Down Expand Up @@ -36,9 +37,23 @@ const destination: DestinationDefinition<Settings> = {
description: 'Find and copy the client-side ID in the LaunchDarkly account settings page.',
type: 'string',
required: true
},
events_host_name: {
label: 'LaunchDarkly events host name',
description: `Your LaunchDarkly events host name. If not specified, the default value of ${DEFAULT_EVENTS_HOST_NAME} will be used. Most customers will not need to change this setting.`,
type: 'string',
default: DEFAULT_EVENTS_HOST_NAME,
required: false,
format: 'hostname'
}
},
testAuthentication: (request, { settings }) => {
// The endpoint we are using to validate the clientID is only compatible with the default host name so we only
// validate it if the default host name is provided.
const hostname = settings.events_host_name || DEFAULT_EVENTS_HOST_NAME
if (hostname !== DEFAULT_EVENTS_HOST_NAME) {
return true
}
// The sdk/goals/{clientID} endpoint returns a 200 if the client ID is valid and a 404 otherwise.
return request(`https://clientsdk.launchdarkly.com/sdk/goals/${settings.client_id}`, { method: 'head' })
}
Expand All @@ -47,7 +62,7 @@ const destination: DestinationDefinition<Settings> = {
extendRequest: () => {
return {
headers: {
'User-Agent': 'SegmentDestination/2.1.0',
'User-Agent': 'SegmentDestination/2.2.0',
'Content-Type': 'application/json',
'X-LaunchDarkly-Event-Schema': '4'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,41 @@ describe('LaunchDarkly.trackEvent', () => {
])
})

it('should send custom events to a custom host when specified in the settings', async () => {
const customEventsHost = 'events2.launchdarkly.com'
const settingsWithCustomHost = { ...testSettings, events_host_name: customEventsHost }
nock(`https://${customEventsHost}`).post(`/events/bulk/${testSettings.client_id}`).reply(202)

const event = createTestEvent({
type: 'track',
event: 'Test Event',
userId: 'user1234',
anonymousId: '72d7bed1-4f42-4f2f-8955-72677340546b',
timestamp: '2022-03-30T17:24:58Z',
properties: {
revenue: 123.456
}
})

const responses = await testDestination.testAction(actionSlug, {
event,
settings: settingsWithCustomHost,
useDefaultMappings: true
})

expect(responses.length).toBe(1)
expect(responses[0].status).toBe(202)
expect(responses[0].options.json).toMatchObject([
{
key: 'Test Event',
contextKeys: { user: 'user1234', unauthenticatedUser: '72d7bed1-4f42-4f2f-8955-72677340546b' },
kind: 'custom',
metricValue: 123.456,
creationDate: 1648661098000
}
])
})

it('should use custom context kinds if provided', async () => {
nock('https://events.launchdarkly.com').post(`/events/bulk/${testSettings.client_id}`).reply(202)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ const action: ActionDefinition<Settings, Payload> = {
},
perform: (request, { payload, settings }) => {
const event = convertPayloadToLDEvent(payload)
return request(getEventsUrl(settings.client_id), {
return request(getEventsUrl(settings), {
method: 'post',
json: [event]
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import dayjs from '../../lib/dayjs'
const BULK_EVENTS_BASE_URL = 'https://events.launchdarkly.com/events/bulk'
import { Settings } from './generated-types'
export const DEFAULT_EVENTS_HOST_NAME = 'events.launchdarkly.com'
const BULK_EVENTS_PATH = 'events/bulk'

export const getEventsUrl = (clientID: string) => {
return `${BULK_EVENTS_BASE_URL}/${clientID}`
export const getEventsUrl = (settings: Settings) => {
const { client_id, events_host_name } = settings
return `https://${events_host_name || DEFAULT_EVENTS_HOST_NAME}/${BULK_EVENTS_PATH}/${client_id}`
}

export const parseTimestamp = (ts?: string | number): number => {
Expand Down

0 comments on commit 97ebdf8

Please sign in to comment.